Android 電源管理相關邏輯之PMS

一.PowerManagerService

1.概述

???????PowerManagerService是負責管理、協(xié)調設備電源管理的系統(tǒng)服務之一,設備常見功能如亮滅屏、亮度調節(jié)、低電量模式、保持CPU喚醒等,都會通過PMS的協(xié)調和處理。其繼承自SystemService,因此具有SystemService子類的共性:具有生命周期方法,由SystemServer啟動、注冊到系統(tǒng)服務中,通過Binder和其他組件進行交互等。

2.結構圖

image

3.啟動過程

???????和SystemService的其他子類一樣,PMS由SystemServer通過反射的方式啟動,看一下PMS的構造方法:

3.1.構造方法

public PowerManagerService(Context context) {
    super(context);
    mContext = context;
    mHandlerThread = new ServiceThread(TAG,
            Process.THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
    mHandlerThread.start();
    mHandler = new PowerManagerHandler(mHandlerThread.getLooper());
    mConstants = new Constants(mHandler);
    mAmbientDisplayConfiguration = new AmbientDisplayConfiguration(mContext);
    mBatterySaverPolicy = new BatterySaverPolicy(mHandler);

    qcNsrmPowExt = new QCNsrmPowerExtension(this);
    synchronized (mLock) {
        mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks");
        mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display");
        mDisplaySuspendBlocker.acquire();
        mHoldingDisplaySuspendBlocker = true;
        mHalAutoSuspendModeEnabled = false;
        mHalInteractiveModeEnabled = true;
        mWakefulness = WAKEFULNESS_AWAKE;
        sQuiescent = SystemProperties.get(SYSTEM_PROPERTY_QUIESCENT, "0").equals("1");
        nativeInit();
        nativeSetAutoSuspend(false);
        nativeSetInteractive(true);
        nativeSetFeature(POWER_FEATURE_DOUBLE_TAP_TO_WAKE, 0);
    }
}

???????通過上面可以看到,在構造方法中首先創(chuàng)建了一個HandlerThread;其次獲取了兩個Suspend鎖,SuspendBlocker是一種鎖機制,只用于系統(tǒng)內部,上層申請的Wakelock鎖在PMS中都會反映為SuspendBlocker鎖。這里獲取的兩個Suspend鎖在申請Wakelock時會用到;最后調用了native方法,這幾個方法會通過JNI層調用到HAL層。

3.2.onStart()

public void onStart() {
    publishBinderService(Context.POWER_SERVICE, new BinderService());
    publishLocalService(PowerManagerInternal.class, new LocalService());

    Watchdog.getInstance().addMonitor(this);
    Watchdog.getInstance().addThread(mHandler);
}

???????在該方法中,首先對該服務進行Binder注冊和本地注冊,當進行Binder注冊后,在其他模塊中就可以通過Binder機制獲取其實例,同理,當進行本地注冊后,只有在System進程才能獲取到其實例;最后設置Watchdog的監(jiān)聽。

3.3.onBootPhase()

@Override
public void onBootPhase(int phase) {
    synchronized (mLock) {
        if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
            incrementBootCount();
        } else if (phase == PHASE_BOOT_COMPLETED) {
            final long now = SystemClock.uptimeMillis();
            mBootCompleted = true;
            mDirty |= DIRTY_BOOT_COMPLETED;
            userActivityNoUpdateLocked(now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0,
                    Process.SYSTEM_UID, Display.DEFAULT_DISPLAY);
            updatePowerStateLocked();
            if (!ArrayUtils.isEmpty(mBootCompletedRunnables)) {
                Slog.d(TAG, "Posting " + mBootCompletedRunnables.length + " delayed runnables");
                for (Runnable r : mBootCompletedRunnables) {
                    BackgroundThread.getHandler().post(r);
                }
            }
            mBootCompletedRunnables = null;
        }
    }
}

???????在這個方法中,設置mBootCompleted為true,表示啟動完成,將mDirty置位,mDirty是一個二進制的標記位,用來表示電源狀態(tài)哪一部分發(fā)生了改變,通過對其進行置位(|操作)、清零(~操作),得到二進制數(shù)各個位的值(0或1),進行不同的處理 ,然后執(zhí)行updatePowerStateLocked()方法,這是整個PMS中最重要的方法,這塊會在下文中具體功能中進行詳細分析。

3.4.systemReady()

public void systemReady(IAppOpsService appOps) {
    synchronized (mLock) {
        mSystemReady = true;
        mAppOps = appOps;
        mDreamManager = getLocalService(DreamManagerInternal.class);
        mDisplayManagerInternal = getLocalService(DisplayManagerInternal.class);
        mPolicy = getLocalService(WindowManagerPolicy.class);
        mBatteryManagerInternal = getLocalService(BatteryManagerInternal.class);

        PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
        mScreenBrightnessSettingMinimum = pm.getMinimumScreenBrightnessSetting();
        mScreenBrightnessSettingMaximum = pm.getMaximumScreenBrightnessSetting();
        mScreenBrightnessSettingDefault = pm.getDefaultScreenBrightnessSetting();

        mScreenBrightnessForVrSettingDefault = pm.getDefaultScreenBrightnessForVrSetting();

        SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper());

        // The notifier runs on the system server's main looper so as not to interfere
        // with the animations and other critical functions of the power manager.
        mBatteryStats = BatteryStatsService.getService();
        mNotifier = new Notifier(Looper.getMainLooper(), mContext, mBatteryStats,
                mAppOps, createSuspendBlockerLocked("PowerManagerService.Broadcasts"),
                mPolicy);

        mWirelessChargerDetector = new WirelessChargerDetector(sensorManager,
                createSuspendBlockerLocked("PowerManagerService.WirelessChargerDetector"),
                mHandler);
        mSettingsObserver = new SettingsObserver(mHandler);

        mLightsManager = getLocalService(LightsManager.class);
        mAttentionLight = mLightsManager.getLight(LightsManager.LIGHT_ID_ATTENTION);

        mDisplayManagerInternal.initPowerManagement(
                mDisplayPowerCallbacks, mHandler, sensorManager);

        // Go.
        readConfigurationLocked();
        updateSettingsLocked();
        mDirty |= DIRTY_BATTERY_STATE;
        updatePowerStateLocked();
    }

    final ContentResolver resolver = mContext.getContentResolver();
    mConstants.start(resolver);
    mBatterySaverPolicy.start(resolver);

    // Register for settings changes.
    resolver.registerContentObserver(Settings.Secure.getUriFor(
            Settings.Secure.SCREENSAVER_ENABLED),
            false, mSettingsObserver, UserHandle.USER_ALL);
    ..........

    resolver.registerContentObserver(Settings.System.getUriFor(
            Settings.System.DREAM_TIMEOUT),
            false, mSettingsObserver, UserHandle.USER_ALL);

    ..............

    // Register for broadcasts from other components of the system.
    IntentFilter filter = new IntentFilter();
    filter.addAction(Intent.ACTION_BATTERY_CHANGED);
    filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
    mContext.registerReceiver(new BatteryReceiver(), filter, null, mHandler);
    ..............
}

???????該方法內主要有5個重要功能
  a.獲取各類本地服務和遠程服務,如屏保(DreamMangerService)、窗口(PhoneWindowManager)、電池狀態(tài)監(jiān)聽服務(BatteryService)等服務,用于進行交互;
  b.注冊用于和其他Sytem交互的廣播;
  c.調用updateSettingsLocked()方法更新Settings中值的變化;
  d.調用readConfigurationLocked()方法讀取配置文件中的默認值;
  e.注冊SettingsObserver監(jiān)聽;

image

  以上就是PowerManagerService的整個啟動過程;

二.屏幕亮度調節(jié)

1.調節(jié)流程

???????當通過系統(tǒng)設置等進行屏幕亮度調節(jié)時,會調用到PMS內部的updatePowerStateLocked(),通過該方法進行接下來的邏輯執(zhí)行,最終通過HAL層來設置屏幕亮度,本文基于Android 8.1版本進行分析:

1.1.PowerManagerService.java

1.1.1.updatePowerStateLocked()

protected void updatePowerStateLocked() {
    if (!mSystemReady || mDirty == 0) {
        return;
    }
    ...................
    try {
        // Phase 0: Basic state updates.
        updateIsPoweredLocked(mDirty);
        updateStayOnLocked(mDirty);
        updateScreenBrightnessBoostLocked(mDirty);

        // Phase 1: Update wakefulness.
        final long now = SystemClock.uptimeMillis();
        int dirtyPhase2 = 0;
        for (;;) {
            int dirtyPhase1 = mDirty;
            dirtyPhase2 |= dirtyPhase1;
            mDirty = 0;

            updateWakeLockSummaryLocked(dirtyPhase1);
            updateUserActivitySummaryLocked(now, dirtyPhase1);
            if (!updateWakefulnessLocked(dirtyPhase1)) {
                break;
            }
        }

        // Phase 2: Update display power state.
        boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);

        // Phase 3: Update dream state (depends on display ready signal).
        updateDreamLocked(dirtyPhase2, displayBecameReady);

        // Phase 4: Send notifications, if needed.
        finishWakefulnessChangeIfNeededLocked();

        // Phase 5: Update suspend blocker.
        updateSuspendBlockerLocked();
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_POWER);
    }
}

???????當亮度調節(jié)時,處理邏輯主要是在phase 2,即updateDisplayPowerStateLocked(dirtyPhase2),一起看一下該方法:

1.1.2.updateDisplayPowerStateLocked()

private boolean updateDisplayPowerStateLocked(int dirty) {
    final boolean oldDisplayReady = mDisplayReady;
    if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS
            | DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED | DIRTY_BOOT_COMPLETED
            | DIRTY_SETTINGS | DIRTY_SCREEN_BRIGHTNESS_BOOST | DIRTY_VR_MODE_CHANGED |
            DIRTY_QUIESCENT)) != 0) {
        mDisplayPowerRequest.policy = getDesiredScreenPolicyLocked();

        int screenBrightness;
        boolean autoBrightness;

        if (!mBootCompleted)
            // Keep the brightness steady during boot. This requires the
            // bootloader brightness and the default brightness to be identical.
            autoBrightness = false;
            screenBrightness = mScreenBrightnessSettingMinimum;
        } else if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)) {
            screenBrightness = mScreenBrightnessOverrideFromWindowManager;
            screenBrightness = Math.max(Math.min(screenBrightness,
                    mScreenBrightnessSettingMaximum), mScreenBrightnessSettingMinimum);
            autoBrightness = false;
        } else {
            autoBrightness = (mScreenBrightnessModeSetting ==
                    Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
            screenBrightness = -1;
        }
        ....................

        // Update display power request.
        mDisplayPowerRequest.screenBrightness = screenBrightness;
        mDisplayPowerRequest.useAutoBrightness = autoBrightness;
        mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();
        mDisplayPowerRequest.boostScreenBrightness = shouldBoostScreenBrightness();

        ........................

        mDisplayReady = mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest,
                mRequestWaitForNegativeProximity);
        mRequestWaitForNegativeProximity = false;

        if ((dirty & DIRTY_QUIESCENT) != 0) {
            sQuiescent = false;
        }
       ...............
    }
    return mDisplayReady && !oldDisplayReady;
}

???????該方法內部主要做了兩件事:
  a.封裝DisplayPowerRequest實例mDisplayPowerRequest,包括通過
getDesiredScreenPolicyLocked()獲取policy,此處為DisplayPowerRequest.POLICY_BRIGHT;還有screenBrightness等;
  b.調用DisplayManagerInternal的requestPowerState(),上步封裝的DisplayPowerRequest作為參數(shù)傳入,mDisplayManagerInternal是在systemReady()內部獲取的;

1.2.DisplayPowerController.java

1.2.1.requestPowerState()

???????DisplayManagerInternal內部的requestPowerState為抽象方法,因此會調用到實現(xiàn)類中,具體是在DisplayManagerService內部的LocalService,看一下具體實現(xiàn):

public boolean requestPowerState(DisplayPowerRequest request,
    return mDisplayPowerController.requestPowerState(request,waitForNegativeProximity);
}

???????最終會調用到DisplayPowerController內部的requestPowerState()方法:

public boolean requestPowerState(DisplayPowerRequest request,
        boolean waitForNegativeProximity) {
    synchronized (mLock) {
        boolean changed = false;

        if (waitForNegativeProximity
                && !mPendingWaitForNegativeProximityLocked) {
            mPendingWaitForNegativeProximityLocked = true;
            changed = true;
        }

        if (mPendingRequestLocked == null) {
            mPendingRequestLocked = new DisplayPowerRequest(request);
            changed = true;
        } else if (!mPendingRequestLocked.equals(request)) {
            mPendingRequestLocked.copyFrom(request);
            changed = true;
        }

        if (changed) {
            mDisplayReadyLocked = false;
        }

        if (changed && !mPendingRequestChangedLocked) {
            mPendingRequestChangedLocked = true;
            sendUpdatePowerStateLocked();
        }

        return mDisplayReadyLocked;
    }
}

???????在該方法內部先將傳入的DisplayPowerRequest對象賦值給mPendingRequestLocked,后續(xù)會使用;接著執(zhí)行sendUpdatePowerStateLocked(),在該方法內部會發(fā)送異步消息MSG_UPDATE_POWER_STATE,對應處理方法為updatePowerState();

1.2.2.updatePowerState()

private void updatePowerState() {
    ...............
    synchronized (mLock) {
        mPendingUpdatePowerStateLocked = false;
        if (mPendingRequestLocked == null) {
            return; // wait until first actual power request
        }

        if (mPowerRequest == null) {
            mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked);
            mWaitingForNegativeProximity = mPendingWaitForNegativeProximityLocked;
            mPendingWaitForNegativeProximityLocked = false;
            mPendingRequestChangedLocked = false;
            mustInitialize = true;
        } else if (mPendingRequestChangedLocked) {
            autoBrightnessAdjustmentChanged = (mPowerRequest.screenAutoBrightnessAdjustment
                != mPendingRequestLocked.screenAutoBrightnessAdjustment);
            mPowerRequest.copyFrom(mPendingRequestLocked);
            mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
            mPendingWaitForNegativeProximityLocked = false;
            mPendingRequestChangedLocked = false;
            mDisplayReadyLocked = false;
        }

        mustNotify = !mDisplayReadyLocked;
    }
    // Initialize things the first time the power state is changed.
    if (mustInitialize) {
       initialize();
    }

    int state;
    int brightness = PowerManager.BRIGHTNESS_DEFAULT;
    boolean performScreenOffTransition = false;
    switch (mPowerRequest.policy) {
        case DisplayPowerRequest.POLICY_OFF:
            state = Display.STATE_OFF;
            performScreenOffTransition = true;
            break;
        ............
        case DisplayPowerRequest.POLICY_DIM:
        case DisplayPowerRequest.POLICY_BRIGHT:
        default:
            state = Display.STATE_ON;
            break;
    }
    ..........................
    ..........................
    final int oldState = mPowerState.getScreenState();
    animateScreenStateChange(state, performScreenOffTransition);
    state = mPowerState.getScreenState();
    ....................................
    .....根據(jù)策略選擇最終的brightness值.....
    ....................................
    animateScreenBrightness(brightness,
        slowChange ? mBrightnessRampRateSlow : mBrightnessRampRateFast);
    ...........
}

???????該方法內部主要干了6件事:
  a.將要更新的DisplayPowerRequest實例賦值給mPowerRequest;
  b.如果為首次執(zhí)行的話,需要執(zhí)行initialize()來執(zhí)行初始化操作,創(chuàng)建DisplayPowerState實例mPowerState、RampAnimator實例mScreenBrightnessRampAnimator等;

  private void initialize() {
    // Initialize the power state object for the default display.
    // In the future, we might manage multiple displays independently.
    mPowerState = new DisplayPowerState(mBlanker,
            mColorFadeEnabled ? new ColorFade(Display.DEFAULT_DISPLAY) : null);

    mScreenBrightnessRampAnimator = new RampAnimator<DisplayPowerState>(
            mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS);
    mScreenBrightnessRampAnimator.setListener(mRampAnimatorListener);

    // Initialize screen state for battery stats.
    try {
        mBatteryStats.noteScreenState(mPowerState.getScreenState());
        mBatteryStats.noteScreenBrightness(mPowerState.getScreenBrightness());
    } catch (RemoteException ex) {
        // same process
    }
}    

???????c.根據(jù)mPowerRequest.policy來更新state,此處為Display.STATE_ON;
  d.執(zhí)行animateScreenStateChange(state, performScreenOffTransition)來更新DisplayPowerState;
  e.根據(jù)策略進行選擇,最終確定要更新的brightness值;
  f.執(zhí)行animateScreenBrightness(brightness,slowChange ? mBrightnessRampRateSlow : mBrightnessRampRateFast)來進行更新;

1.3.RampAnimator.java

1.3.1.animateScreenBightness()

private void animateScreenBrightness(int target, int rate) {
    if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {
        Trace.traceCounter(Trace.TRACE_TAG_POWER, "TargetScreenBrightness", target);
        try {
            mBatteryStats.noteScreenBrightness(target);
        } catch (RemoteException ex) {
            // same process
        }
    }
}

1.3.2.animateTo()

public boolean animateTo(int target, int rate) {
    // Immediately jump to the target the first time.
    if (mFirstTime || rate <= 0) {
        if (mFirstTime || target != mCurrentValue) {
            mFirstTime = false;
            mRate = 0;
            mTargetValue = target;
            mCurrentValue = target;
            mProperty.setValue(mObject, target);
            if (mAnimating) {
                mAnimating = false;
                cancelAnimationCallback();
            }
            if (mListener != null) {
                mListener.onAnimationEnd();
            }
            return true;
        }
        return false;
    }
    ......................
    return changed;
}

???????可以看到,在animateTo()內部會執(zhí)行mProperty.setValue(mObject, target),mProperty對應的是
DisplayPowerState.SCREEN_BRIGHTNESS,mObject對應的是mPowerState,都是在DisplayPowerController內部的initialize()內部傳入的,接下來就進入了DisplayPowerState內部了;

1.4.DisplayPowerState.java

1.4.1.setScreenBightness()

public void setScreenBrightness(int brightness) {
    if (mScreenBrightness != brightness) {
        if (DEBUG) {
            Slog.d(TAG, "setScreenBrightness: brightness=" + brightness);
        }

        mScreenBrightness = brightness;
        if (mScreenState != Display.STATE_OFF) {
            mScreenReady = false;
            scheduleScreenUpdate();
        }
    }
}

???????scheduleScreenUpdate()會執(zhí)行到postScreenUpdateThreadSafe(),然后會post mScreenUpdateRunnable;

1.4.2.mScreenUpdateRunnable

private final Runnable mScreenUpdateRunnable = new Runnable() {
    @Override
    public void run() {
        mScreenUpdatePending = false;

        int brightness = mScreenState != Display.STATE_OFF
                && mColorFadeLevel > 0f ? mScreenBrightness : 0;

        if (mPhotonicModulator.setState(mScreenState, brightness)) {
            if (DEBUG) {
                Slog.d(TAG, "Screen ready");
            }
            mScreenReady = true;
            invokeCleanListenerIfNeeded();
        } else {
            if (DEBUG) {
                Slog.d(TAG, "Screen not ready");
            }
        }
    }
};

1.4.3.PhotonicModulator.setState()

private final class PhotonicModulator extends Thread {
    ................
    ................

    public boolean setState(int state, int backlight) {
        synchronized (mLock) {
            boolean stateChanged = state != mPendingState;
            boolean backlightChanged = backlight != mPendingBacklight;
            if (stateChanged || backlightChanged) {

                 mPendingState = state;
                 mPendingBacklight = backlight;
                 ..................
                 if (!changeInProgress) {
                     mLock.notifyAll();
                 }
            }
        }
        return !mStateChangeInProgress;
    }

    @Override
    public void run() {
        for (;;) {
            // Get pending change.
            final int state;
            final boolean stateChanged;
            final int backlight;
            final boolean backlightChanged;
            synchronized (mLock) {
                state = mPendingState;
                stateChanged = (state != mActualState);
                backlight = mPendingBacklight;
                backlightChanged = (backlight != mActualBacklight);
                if (!stateChanged) {
                    // State changed applied, notify outer class.
                    postScreenUpdateThreadSafe();
                    mStateChangeInProgress = false;
                }
                if (!backlightChanged) {
                    mBacklightChangeInProgress = false;
                }
                if (!stateChanged && !backlightChanged) {
                    try {
                        mLock.wait();
                    } catch (InterruptedException ex) { }
                    continue;
                }
                mActualState = state;
                mActualBacklight = backlight;
            }

            // Apply pending change.
            if (DEBUG) {
                Slog.d(TAG, "Updating screen state: state="
                        + Display.stateToString(state) + ", backlight=" + backlight);
            }
            mBlanker.requestDisplayState(state, backlight);
        }
    }
}
}

???????可以看到,在執(zhí)行setState()后,最終會執(zhí)行mBlanker.requestDisplayState(state, backlight),mBlanker是DisplayBlanker實例,初始化是在DisplayPowerController構造方法內,在DisplayPowerController內部的initialize()內部傳入的,根據(jù)調用關系會追溯到DisplayMangerService的LocalService的initPowerManagerment()方法,該方法是在PowerManagerService的systemReady()方法內執(zhí)行的;

1.5.DisplayManagerService.java

1.5.1.requestDisplayState()

@Override
public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler,
        SensorManager sensorManager) {
    synchronized (mSyncRoot) {
        DisplayBlanker blanker = new DisplayBlanker() {
            @Override
            public void requestDisplayState(int state, int brightness) {
                // The order of operations is important for legacy reasons.
                if (state == Display.STATE_OFF) {
                    requestGlobalDisplayStateInternal(state, brightness);
                }

                callbacks.onDisplayStateChange(state);

                if (state != Display.STATE_OFF) {
                    requestGlobalDisplayStateInternal(state, brightness);
                }
            }
        };
        mDisplayPowerController = new DisplayPowerController(
                mContext, callbacks, handler, sensorManager, blanker);
    }
}

???????由于傳入的state為Display.STATE_ON,執(zhí)行到requestGlobalDisplayStateInternal(state, brightness),根據(jù)調用關系最終會執(zhí)行到updateDisplayStateLocked()獲取Runnable實例;

1.5.2.updateDisplayStateLocked()

private void applyGlobalDisplayStateLocked(List<Runnable> workQueue) {
    final int count = mDisplayDevices.size();
    for (int i = 0; i < count; i++) {
        DisplayDevice device = mDisplayDevices.get(i);
        Runnable runnable = updateDisplayStateLocked(device);
        if (runnable != null) {
            workQueue.add(runnable);
        }
    }
}

private Runnable updateDisplayStateLocked(DisplayDevice device) {
    // Blank or unblank the display immediately to match the state requested
    // by the display power controller (if known).
    DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
    if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
        return device.requestDisplayStateLocked(mGlobalDisplayState, mGlobalDisplayBrightness);
    }
    return null;
}

???????根據(jù)調用關系看到,會通過DisplayDevice的requestDisplayStateLocked()來獲取到Runnable;
  在DisplayManagerService的onStart()內發(fā)送消息來執(zhí)行registerDisplayAdapterLocked(new LocalDisplayAdapter())加載BUILT_IN_DISPLAY_IDS_TO_SCAN對應的LocalDisplayDevice(繼承DisplayDevice),加載成功后存入mDisplayDevices列表內進行管理;
  在創(chuàng)建LocalDisplayDeivce時會通過lights.getLight(LightsManager.LIGHT_ID_BACKLIGHT)獲取mBackLight,對應的是LightsService內部的LightImpl繼承l(wèi)ight;
  在通過LocalDisplayDevice獲取到Runnable后接著執(zhí)行run(),會執(zhí)行到setDisplayBrightness();

1.6.LocalDisplayDevice

1.6.1.setDisplayBrightness()

private void setDisplayBrightness(int brightness) {
    if (DEBUG) {
        Slog.d(TAG, "setDisplayBrightness("
                    + "id=" + displayId + ", brightness=" + brightness + ")");
    }

    Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayBrightness("
                + "id=" + displayId + ", brightness=" + brightness + ")");
    try {
        mBacklight.setBrightness(brightness);
        Trace.traceCounter(Trace.TRACE_TAG_POWER,
                    "ScreenBrightness", brightness);
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_POWER);
    }
}

???????在setDisplayBrightness()內部會執(zhí)行到mBacklight.setBrightness(brightness),具體實現(xiàn)邏輯是在LightsService內部;

1.7.LightsService.java

1.7.1.setLightLocked()

private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode, int displayId) {
    ..............
    try {
        setLight_native(mId, color, mode, onMS, offMS, brightnessMode, displayId);
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_POWER);
    }
}

???????最終通過native方法調用到HAL層對屏幕的背光進行設置。

1.8.流程總結

image

2.調節(jié)方式

???????不同的調節(jié)方式對應不同的入口及判斷邏輯,只分析調用入口及涉及的關鍵策略來選擇最終目標brightness值邏輯;

2.1.系統(tǒng)設置調節(jié)

???????系統(tǒng)設置在調節(jié)屏幕亮度時,會實時更新Settings.SCREEN_BRIGHTNESS值,DisplayPowerController在監(jiān)聽到該值變化后會執(zhí)行handleSettingsChanged()方法:

private void handleSettingsChange(boolean userSwitch) {
    mPendingScreenBrightnessSetting = getScreenBrightnessSetting();
    sendUpdatePowerState();
}

private int getScreenBrightnessSetting() {
    final int brightness = Settings.System.getIntForUser(mContext.getContentResolver(),
            Settings.System.SCREEN_BRIGHTNESS,
            mScreenBrightnessDefault, UserHandle.USER_CURRENT);
    return clampAbsoluteBrightness(brightness);
}

???????監(jiān)聽到變化后,先通過getScreenBrightnessSetting()來獲取到當前值,然后賦值給mPendingScreenBrightnessSetting,接下來執(zhí)行sendUpdatePowerState(),最終執(zhí)行updatePowerState()方法:

private void updatePowerState() {
    ..................
    ..................
    final boolean userSetBrightnessChanged = updateUserSetScreenBrightness();
    if (brightness < 0) {
    brightness = clampScreenBrightness(mCurrentScreenBrightnessSetting);
    Slog.i(TAG, "updatePowerState mCurrentScreenBrightnessSetting="
            + mCurrentScreenBrightnessSetting);
}

private boolean updateUserSetScreenBrightness() {
    if (mPendingScreenBrightnessSetting < 0) {
        return false;
    }
    if (mCurrentScreenBrightnessSetting == mPendingScreenBrightnessSetting) {
        mPendingScreenBrightnessSetting = -1;
        mTemporaryScreenBrightness = -1;
        return false;
    }
    mCurrentScreenBrightnessSetting = mPendingScreenBrightnessSetting;
    mLastUserSetScreenBrightness = mPendingScreenBrightnessSetting;
    mPendingScreenBrightnessSetting = -1;
    mTemporaryScreenBrightness = -1;
    return true;
}

???????結論:系統(tǒng)設置會根據(jù)mCurrentScreenBrightnessSetting的值來設置對應的目標brightness值;

2.2.快速設置調節(jié)

???????快速設置來滑動進度條來調節(jié)屏幕亮度時,會調用PowerManagerService的setTemporaryScreenBrightnessSettingOverride()方法:

private void setTemporaryScreenBrightnessSettingOverrideInternal(int brightness) {
    synchronized (mLock) {
        mDisplayManagerInternal.setTemporaryBrightness(brightness);
    }
}

???????跟隨調用關系,調用到DisplayPowerController的setTemporaryBrightness()方法,發(fā)送MSG_SET_TEMPORARY_BRIGHTNESS消息,設置mTemporaryScreenBrightness為傳入的值,然后執(zhí)行updatePowerState():

private void updatePowerState() {
    ..................
    ..................
    if (mTemporaryScreenBrightness > 0) {
        Slog.i(TAG, "updatePowerState mTemporaryScreenBrightness="
            + mTemporaryScreenBrightness);
        brightness = mTemporaryScreenBrightness;
    }
}

  結論:快速設置會根據(jù)mTemporaryScreenBrightness的值來設置對應的目標brightness值;

2.3.Window屬性調節(jié)

在視頻播放界面可以通過左側上下滑動來調節(jié)屏幕亮度,具體實現(xiàn)方式如下:

private synchronized void adjustLight(Window window, float value) {
     value = value / FULL_SCREEN_HEIGHT * 2;
     WindowManager.LayoutParams lp = window.getAttributes();
     if (lp.screenBrightness < 0) {
         lp.screenBrightness = Utils.getSystemBrightness(this);
     }
     lp.screenBrightness = lp.screenBrightness + value;
     if (lp.screenBrightness > 1f) {
         lp.screenBrightness = 1f;
     } else if (lp.screenBrightness < 0f) {
         lp.screenBrightness = 0f;
     }
     window.setAttributes(lp);
}

???????Window是activity對應的Window,通過getWindow()可以得到,設置WindowManager.LayoutParams內部的screenBrightness后執(zhí)行window.setAttributes(lp)可以來調節(jié)屏幕亮度;
  Window執(zhí)行setAttributes()會執(zhí)行到Activity的onWindowAttributesChanged()方法,調用到WindowManagerGlobal的updateViewLayout()最終調用到ViewRootImpl的setLayoutParams來執(zhí)行重新繪制;
  繪制流程就不陳述了,最終會執(zhí)行到RootWindowContainer內部的performSurfacePlacement()方法,接下來通過handleNotObscuredLocked()獲取到對應WindowState的w.mAttrs.screenBrightness賦值給mScreenBrightness,然后在performSurfacePlacement()發(fā)送SET_SCREEN_BRIGHTNESS_OVERRIDE消息,最終通過WindowManagerService來調用到PowerManagerService內部的setScreenBrightnessOverrideFromWindowManager()方法:

@Override
public void setScreenBrightnessOverrideFromWindowManager(int screenBrightness) {
    if (screenBrightness < PowerManager.BRIGHTNESS_DEFAULT
            || screenBrightness > PowerManager.BRIGHTNESS_ON) {
        screenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
    }
    setScreenBrightnessOverrideFromWindowManagerInternal(screenBrightness);
}

private void setScreenBrightnessOverrideFromWindowManagerInternal(int brightness) {
    synchronized (mLock) {
        if (mScreenBrightnessOverrideFromWindowManager != brightness) {
            mScreenBrightnessOverrideFromWindowManager = brightness;
            mDirty |= DIRTY_SETTINGS;
            updatePowerStateLocked();
        }
    }
}

???????可以看到,在setScreenBrightnessOverrideFromWindowManagerInternal()內部會將brightness賦值給mScreenBrightnessOverrideFromWindowManager,然后執(zhí)行updatePowerStateLocked(),先看
updateDisplayPowerStateLocked()方法:

private boolean updateDisplayPowerStateLocked(int dirty) {
    ...........................
    ...........................

    else if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)) {
        screenBrightness = mScreenBrightnessOverrideFromWindowManager;
        screenBrightness = Math.max(Math.min(screenBrightness,
            mScreenBrightnessSettingMaximum), mScreenBrightnessSettingMinimum);
        autoBrightness = false;
    }

???????可以看到,screenBrightness會設置為mScreenBrightnessOverrideFromWindowManager,該值默認為-1,經(jīng)過設置后screenBrightness>0,接著執(zhí)行到DisplayPowerController的updatePowerState()方法:

private void updatePowerState() {
    ..................
    ..................
    if (brightness < 0 && mPowerRequest.screenBrightness >= 0) {
        Slog.i(TAG, "updatePowerState mPowerRequest.screenBrightness="
            + mPowerRequest.screenBrightness);
        brightness = mPowerRequest.screenBrightness;
        // boot or WindowManager override brightness need clear temporary
        mTemporaryScreenBrightness = -1;
    }
}

  結論:Window屬性調節(jié)會根據(jù)mScreenBrightnessOverrideFromWindowManager的值來設置對應的目標brightness值;

2.4.總結

???????設置屏幕亮度時,主要是在DisplayPowerController內部的updatePowerState()來對目標screenBrightness進行設置,screenBrightness默認值為PowerManager.BRIGHTNESS_DEFAULT = -1,會根據(jù)DisplayPowerRequest及其他策略進行選擇,順序依次為:
  a.if (brightness < 0 && mPowerRequest.screenBrightness >= 0):通過設置Window屬性來進行調節(jié)(視頻播放界面)
  b.if (mTemporaryScreenBrightness > 0):通過快速設置滑動來進行調節(jié)
  c.if (brightness < 0) {brightness = clampScreenBrightness(mCurrentScreenBrightnessSetting)}:通過系統(tǒng)設置滑動調節(jié)

三.自動進入屏保

???????當系統(tǒng)設置內部設置了自動進入屏保時間后,如果在此段時間后滿足進入條件,會進入屏保,該邏輯入口是在PMS內部的updatePowerStateLocked(),一起看一下:

1.整體流程

???????本流程只分析滿足條件后進入屏保的整個過程,關于條件判斷會在下一節(jié)中進行分析,先從updatePowerStateLocked()看起:

1.1.PowerManagerService.java

1.1.1.updatePowerStateLocked()

protected void updatePowerStateLocked() {
    .................
    .................
    for (;;) {
        int dirtyPhase1 = mDirty;
        dirtyPhase2 |= dirtyPhase1;
        mDirty = 0;

        updateWakeLockSummaryLocked(dirtyPhase1);
        updateUserActivitySummaryLocked(now, dirtyPhase1);
        if (!updateWakefulnessLocked(dirtyPhase1)) {
            break;
        }
    }
    ....................
    // Phase 3: Update dream state (depends on display ready signal).
    updateDreamLocked(dirtyPhase2, displayBecameReady);
    ...................
}

???????在該方法內部首先循環(huán)執(zhí)行了三個方法:
  a.updateWakeLockSummaryLocked():根據(jù)mWakeLocks來計算得到mWakeLockSummary的值;
???????b.updateUserActivitySummaryLocked():計算得到mUserActivitySummary以及何時進行下一次check;
???????c.updateWakefulnessLocked():判斷是否可以進入屏保及更新mWakefulness狀態(tài);
  d.updateDreamLocked():根據(jù)當前狀態(tài)選擇是否進入屏保;

1.1.2.updateWakefulnessLocked()

private boolean updateWakefulnessLocked(int dirty) {
    boolean changed = false;
    if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_BOOT_COMPLETED
            | DIRTY_WAKEFULNESS | DIRTY_STAY_ON | DIRTY_PROXIMITY_POSITIVE
            | DIRTY_DOCK_STATE)) != 0) {
        if (mWakefulness == WAKEFULNESS_AWAKE && isItBedTimeYetLocked()) {
            if (DEBUG_SPEW) {
                Slog.d(TAG, "updateWakefulnessLocked: Bed time...");
            }
            final long time = SystemClock.uptimeMillis();
            if (shouldNapAtBedTimeLocked()) {
                changed = napNoUpdateLocked(time, Process.SYSTEM_UID);
            }
        }
    }
    return changed;
}

???????當mWakefulness為WAKEFULNESS_AWAKE時,且isItBedTimeYetLocked(),即:副駕滿足進入屏保的條件,看一下該方法的邏輯:

private boolean isItBedTimeYetLocked() {
    return mBootCompleted && !isBeingKeptAwakeLocked();
}

private boolean isBeingKeptAwakeLocked() {
    return mStayOn
                || mProximityPositive
                || (mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) != 0
                || (mUserActivitySummary & (USER_ACTIVITY_SCREEN_BRIGHT
                        | USER_ACTIVITY_SCREEN_DIM)) != 0
                || mScreenBrightnessBoostInProgress;
}

???????當滿足以上條件后,執(zhí)行napNoUpdateLocked():

private boolean napNoUpdateLocked(long eventTime, int uid) {
    if (eventTime < mLastWakeTime || mWakefulness != WAKEFULNESS_AWAKE
            || !mBootCompleted || !mSystemReady) {
        return false;
    }
    Trace.traceBegin(Trace.TRACE_TAG_POWER, "nap");
    try {
        Slog.i(TAG, "Nap time (uid " + uid +")...");

        mSandmanSummoned = true;
        setWakefulnessLocked(WAKEFULNESS_DREAMING, 0);
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_POWER);
    }
    return true;
}

???????設置mSandmanSummoned為true,更新當前mWakefulness狀態(tài)WAKEFULNESS_DREAMING,最后返回true;
  前面的循環(huán)中當結果返回true時,會執(zhí)行下一次循環(huán),重新計算mWakeLockSummary和mUserActivitySummary,最終返回false,執(zhí)行break退出循環(huán),執(zhí)行updateDreamLocked();

1.1.3.updateDreamLocked(xx, xx)

private void updateDreamLocked(int dirty, boolean displayBecameReady) {
    if ((dirty & (DIRTY_WAKEFULNESS
            | DIRTY_USER_ACTIVITY
            | DIRTY_WAKE_LOCKS
            | DIRTY_BOOT_COMPLETED
            | DIRTY_SETTINGS
            | DIRTY_IS_POWERED
            | DIRTY_STAY_ON
            | DIRTY_PROXIMITY_POSITIVE
            | DIRTY_BATTERY_STATE)) != 0 || displayBecameReady) {
        if (mDisplayReady) {
            scheduleSandmanLocked();
        }
    }
}

???????滿足條件后執(zhí)行scheduleSandmanLocked()來發(fā)送異步消息,執(zhí)行handleSandman(),mDisplayReady是在updateDisplayPowerStateLocked()內部最終通過DisplayPowerController內部返回的;

1.1.4.handleSandman()

private void handleSandman() { // runs on handler thread
    // Handle preconditions.
    final boolean startDreaming;
    final int wakefulness;
    synchronized (mLock) {
        mSandmanScheduled = false;
        wakefulness = mWakefulness;
        if (mSandmanSummoned && mDisplayReady) {
            startDreaming = canDreamLocked() || canDozeLocked();
            mSandmanSummoned = false;
        } else {
            startDreaming = false;
        }
    }

    final boolean isDreaming;
    if (mDreamManager != null) {
        // Restart the dream whenever the sandman is summoned.
        if (startDreaming) {
            mDreamManager.stopDream(false /*immediate*/);
            mDreamManager.startDream(wakefulness == WAKEFULNESS_DOZING);
        }
        isDreaming = mDreamManager.isDreaming();
    } else {
        isDreaming = false;
    }

    // Update dream state.
    synchronized (mLock) {
        // Remember the initial battery level when the dream started.
        if (startDreaming && isDreaming) {
            mBatteryLevelWhenDreamStarted = mBatteryLevel;
            if (wakefulness == WAKEFULNESS_DOZING) {
                Slog.i(TAG, "Dozing...");
            } else {
                Slog.i(TAG, "Dreaming...");
            }
        }
        .....................
        // Determine whether the dream should continue.
        if (wakefulness == WAKEFULNESS_DREAMING) {
            ...................
            // Dream has ended or will be stopped.  Update the power state.
            if (isItBedTimeYetLocked()) {
                updatePowerStateLocked();
            } else {
                wakeUpNoUpdateLocked(SystemClock.uptimeMillis(), "android.server.power:DREAM",
                        Process.SYSTEM_UID, mContext.getOpPackageName(), Process.SYSTEM_UID);
                updatePowerStateLocked();
            }
        }
        ....................
    }
    // Stop dream.
    if (isDreaming) {
        mDreamManager.stopDream(false /*immediate*/);
    }
}

???????在handleSandman()先進行判斷,滿足條件后即startDreaming為true時,執(zhí)行stopDream()、startDream(),接下來再執(zhí)行wakeUpNoUpdateLocked(),一起看一下該方法的實現(xiàn):

private boolean wakeUpNoUpdateLocked(long eventTime, String reason, int reasonUid,
        String opPackageName, int opUid) {
    .........................
    .........................
    try {
        switch (mWakefulness) {
            case WAKEFULNESS_ASLEEP:
                Slog.i(TAG, "Waking up from sleep (uid=" + reasonUid + " reason=" + reason
                        + ")...");
                break;
            case WAKEFULNESS_DREAMING:
                Slog.i(TAG, "Waking up from dream (uid=" + reasonUid + " reason=" + reason
                        + ")...");
                break;
            case WAKEFULNESS_DOZING:
                Slog.i(TAG, "Waking up from dozing (uid=" + reasonUid + " reason=" + reason
                        + ")...");
                break;
        }

        mLastWakeTime = eventTime;
        setWakefulnessLocked(WAKEFULNESS_AWAKE, 0);
        mNotifier.onWakeUp(reason, reasonUid, opPackageName, opUid);
        userActivityNoUpdateLocked(eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER,
                0, reasonUid, Display.DEFAULT_DISPLAY);
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_POWER);
    }
    return true;
}

???????將mWakefulness更新為WAKEFULNESS_AWAKE;然后再執(zhí)行 userActivityNoUpdateLocked()來更新user activity相關信息,接著上面進行分析,執(zhí)行startDream()進入屏保;

1.2.DreamManagerSerivce.java

1.2.1.startDream()

public void startDream(boolean doze) {
    startDreamInternal(doze);
}

private void startDreamInternal(boolean doze) {
    final int userId = ActivityManager.getCurrentUser();
    final ComponentName dream = chooseDreamForUser(doze, userId);
    if (dream != null) {
        synchronized (mLock) {
            startDreamLocked(dream, false /*isTest*/, doze, userId);
        }
    }
}

private void startDreamLocked(final ComponentName name,
        final boolean isTest, final boolean canDoze, final int userId) {
    .........................
    stopDreamLocked(true /*immediate*/);
    Slog.i(TAG, "Entering dreamland.");
    final Binder newToken = new Binder();
    mCurrentDreamToken = newToken;
    mCurrentDreamName = name;
    mCurrentDreamIsTest = isTest;
    mCurrentDreamCanDoze = canDoze;
    mCurrentDreamUserId = userId;

    PowerManager.WakeLock wakeLock = mPowerManager
            .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "startDream");
    mHandler.post(wakeLock.wrap(
            () -> mController.startDream(newToken, name, isTest, canDoze, userId, wakeLock)));
}

???????在startDream()邏輯執(zhí)行過程中首先獲取到本地屏保實現(xiàn)的ComponentName,通過在core/res/res/values/config.xml內進行配置:

<string name="config_dreamsDefaultComponent" translatable="false">
com.hly.screensaver/com.hly.screensaver.SevenDreamService
</string>

???????接下來最終通過DreamController的startDream()來啟動;

1.3.DreamController.java

1.3.1.startDream()

public void startDream(Binder token, ComponentName name,
        boolean isTest, boolean canDoze, int userId, PowerManager.WakeLock wakeLock) {
    stopDream(true /*immediate*/);
    try {
        ............................
        Intent intent = new Intent(DreamService.SERVICE_INTERFACE);
        intent.setComponent(name);
        intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
        try {
            if (!mContext.bindServiceAsUser(intent, mCurrentDream,
                    Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
                    new UserHandle(userId))) {
                Slog.e(TAG, "Unable to bind dream service: " + intent);
                stopDream(true /*immediate*/);
                return;
            }
        }
        ........................
}

???????可以看到在startDream()內部通過bindService()來啟動本地實現(xiàn)的屏保服務SevenDreamService;

1.4.SevenDreamService.java

<uses-permission
    android:name="android.permission.BIND_DREAM_SERVICE"
    tools:ignore="ProtectedPermissions" />

<service
    android:name="com.hly.screensaver.SevenDreamService"
    android:exported="true"
    android:permission="android.permission.BIND_DREAM_SERVICE">
    <intent-filter>
        <action android:name="android.service.dreams.DreamService" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</service>

1.5.總結

image.png

2.條件判斷

2.1.updateWakeLockSummaryLocked()

private void updateWakeLockSummaryLocked(int dirty) {
    if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_WAKEFULNESS)) != 0) {
        mWakeLockSummary = 0;

        final int numWakeLocks = mWakeLocks.size();
        for (int i = 0; i < numWakeLocks; i++) {
            final WakeLock wakeLock = mWakeLocks.get(i);
            switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
                case PowerManager.PARTIAL_WAKE_LOCK:
                    if (!wakeLock.mDisabled) {
                        // We only respect this if the wake lock is not disabled.
                        mWakeLockSummary |= WAKE_LOCK_CPU;
                    }
                    break;
                case PowerManager.FULL_WAKE_LOCK:
                    mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_BUTTON_BRIGHT;
                    break;
                case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
                    mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT;
                    break;
                case PowerManager.SCREEN_DIM_WAKE_LOCK:
                    mWakeLockSummary |= WAKE_LOCK_SCREEN_DIM;
                    break;
                case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
                    mWakeLockSummary |= WAKE_LOCK_PROXIMITY_SCREEN_OFF;
                    break;
                case PowerManager.DOZE_WAKE_LOCK:
                    mWakeLockSummary |= WAKE_LOCK_DOZE;
                    break;
                case PowerManager.DRAW_WAKE_LOCK:
                    mWakeLockSummary |= WAKE_LOCK_DRAW;
                    break;
            }
        }

        // Cancel wake locks that make no sense based on the current state.
        if (mWakefulness != WAKEFULNESS_DOZING) {
            mWakeLockSummary &= ~(WAKE_LOCK_DOZE | WAKE_LOCK_DRAW);
        }
        if (mWakefulness == WAKEFULNESS_ASLEEP
                || (mWakeLockSummary & WAKE_LOCK_DOZE) != 0) {
            mWakeLockSummary &= ~(WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM
                    | WAKE_LOCK_BUTTON_BRIGHT);
            if (mWakefulness == WAKEFULNESS_ASLEEP) {
                mWakeLockSummary &= ~WAKE_LOCK_PROXIMITY_SCREEN_OFF;
            }
        }

        // Infer implied wake locks where necessary based on the current state.
        if ((mWakeLockSummary & (WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM)) != 0) {
            if (mWakefulness == WAKEFULNESS_AWAKE) {
                mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_STAY_AWAKE;
            } else if (mWakefulness == WAKEFULNESS_DREAMING) {
                mWakeLockSummary |= WAKE_LOCK_CPU;
            }
        }
        if ((mWakeLockSummary & WAKE_LOCK_DRAW) != 0) {
            mWakeLockSummary |= WAKE_LOCK_CPU;
        }
    }
}

???????根據(jù)當前持有的mWakeLocks進行處理,計算得到mWakeLockSummary,用來在進入屏保前進行判斷;

private boolean isBeingKeptAwakeLocked() {
    return (mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) != 0
            || .......);
}

2.2.updateUserActivitySummaryLocked()

private void updateUserActivitySummaryLocked(long now, int dirty) {
    if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY
            | DIRTY_WAKEFULNESS | DIRTY_SETTINGS)) != 0) {
        mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT);

        long nextTimeout = 0;
        long screenSaveNextTimeout = 0;

        if (mWakefulness == WAKEFULNESS_AWAKE
                || mWakefulness == WAKEFULNESS_DREAMING
                || mWakefulness == WAKEFULNESS_DOZING) {
            ..............
            final int screenSaveTimeout = getScreenSaveTimeoutLocked();

            mUserActivitySummary = 0;
            if (mLastUserActivityTime >= mLastWakeTime) {
                nextTimeout = mLastUserActivityTime
                        + screenOffTimeout - screenDimDuration;

               screenSaveNextTimeout = mLastUserActivityTime + screenSaveTimeout;

                if (now < nextTimeout) {
                    if(mScreenSaveEnable && (screenOffTimeout > screenSaveTimeout)
                            && (now > ScreenSaveNextTimeout)){
                        mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;
                    } else {
                        mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;
                    }
                }
            }           
            ....................
            ....................
            if (mUserActivitySummary != 0 && nextTimeout >= 0) {
                long checkInNextTime = nextTimeout;
                if (mScreenSaveEnable && screenOffTimeout > screenSaveTimeout
                        && now < screenSaveNextTimeout){
                    checkInNextTime = screenSaveNextTimeout;
                }
                Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT);
                msg.setAsynchronous(true);
                mHandler.sendMessageAtTime(msg, checkInNextTime);
            }
        } else {
            mUserActivitySummary = 0;
        }
    }
}

???????根據(jù)用戶最后一次活躍時間得到進入屏保的時間screenSaveNextTimeout,如果當前時間大于screenSaveNextTimeout,則設置mUserActivitySummary為USER_ACTIVITY_SCREEN_DREAM,表示可以進入屏保,否則設置為USER_ACTIVITY_SCREEN_BRIGHT,表示不可以進入屏保;

private boolean isBeingKeptAwakeLocked() {
    return (XX
            || (mUserActivitySummary & (USER_ACTIVITY_SCREEN_BRIGHT
            | USER_ACTIVITY_SCREEN_DIM)) != 0
            || XX;
}

???????當滿足進入屏保時,checkInNextTime為最大值,表示不會進行check了;當不滿足進入屏保時,checkInNextTime為screenSaveNextTimeout,表示在該時間時發(fā)送MSG_USER_ACTIVITY_TIMEOUT消息進行check;

3.禁止進入屏保

???????禁止進入屏保就是創(chuàng)造不滿足進入屏保的條件就可以了,主要是來影響mWakeLockSummary和mUserActivitySummary的值;

3.1.申請WakeLock

3.1.1.newWakeLock()

mScreenWakeLock = mPowerManager.newWakeLock(
        PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG);
mScreenWakeLock.acquire();

3.1.2.FLAG_KEEP_SCREEN_ON

getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)

3.1.3.執(zhí)行流程

???????最終會執(zhí)行到PMS內部的acquireWakeLockInternal()方法:

private void acquireWakeLockInternal(IBinder lock, int flags, String tag, String packageName,
        WorkSource ws, String historyTag, int uid, int pid, int displayId) {
    synchronized (mLock) {
        WakeLock wakeLock;
        int index = findWakeLockIndexLocked(lock);
        boolean notifyAcquire;
        .................

        wakeLock = new WakeLock(lock, flags, tag, packageName, ws, historyTag, uid, pid,
                    state, displayId);
        try {
            lock.linkToDeath(wakeLock, 0);
        }
        mWakeLocks.add(wakeLock);
        setWakeLockDisabledStateLocked(wakeLock);
        qcNsrmPowExt.checkPmsBlockedWakelocks(uid, pid, flags, tag, wakeLock);
        notifyAcquire = true;

        applyWakeLockFlagsOnAcquireLocked(wakeLock, uid);
        mDirty |= DIRTY_WAKE_LOCKS;
        updatePowerStateLocked();
        ...............
    }
}

???????創(chuàng)建WakeLock并加入到mWakeLocks進行管理,更新mDrity值DIRTY_WAKE_LOCKS,接下來執(zhí)行updatePowerStateLocked()來進行新一輪的計算,在方法最后有一個updateSuspendBlockerLocked()方法:

private void updateSuspendBlockerLocked() {
    final boolean needWakeLockSuspendBlocker = ((mWakeLockSummary & WAKE_LOCK_CPU) != 0);
    final boolean needDisplaySuspendBlocker = needDisplaySuspendBlockerLocked();
    ...................

    // First acquire suspend blockers if needed.
    if (needWakeLockSuspendBlocker && !mHoldingWakeLockSuspendBlocker) {
        mWakeLockSuspendBlocker.acquire();
        mHoldingWakeLockSuspendBlocker = true;
    }
    if (needDisplaySuspendBlocker && !mHoldingDisplaySuspendBlocker) {
        mDisplaySuspendBlocker.acquire();
        mHoldingDisplaySuspendBlocker = true;
    }
    ...............
    // Then release suspend blockers if needed.
    if (!needWakeLockSuspendBlocker && mHoldingWakeLockSuspendBlocker) {
        mWakeLockSuspendBlocker.release();
        mHoldingWakeLockSuspendBlocker = false;
    }
    if (!needDisplaySuspendBlocker && mHoldingDisplaySuspendBlocker) {
        mDisplaySuspendBlocker.release();
        mHoldingDisplaySuspendBlocker = false;
    }
    ..........................
}

???????可以看到,在該方法內根據(jù)上層申請的WakeLocks計算得到的結果mWakeLockSummary來決定是否通過mWakeLockSuspendBlocker向底層進行acquire();

3.2.更新UserActivity

3.2.1.userActivityWithDisplayId()

3.2.2.userActivityFromNative()

3.2.3.執(zhí)行流程

???????以上兩種方式都會執(zhí)行到userActivityInternal()方法:

private void userActivityInternal(long eventTime, int event, int flags, int uid, int displayId) {
    synchronized (mLock) {
        if (userActivityNoUpdateLocked(eventTime, event, flags, uid, displayId)) {
            updatePowerStateLocked();
        }
    }
}

???????先執(zhí)行userActivityNoUpdateLocked()來執(zhí)行一些更新操作;

private boolean userActivityNoUpdateLocked(long eventTime, int event, int flags, int uid,
                                           int displayId) {
    .....................
    try {
        ....................
        if (mWakefulness == WAKEFULNESS_ASLEEP
                || mWakefulness == WAKEFULNESS_DOZING
                || (flags & PowerManager.USER_ACTIVITY_FLAG_INDIRECT) != 0) {
            return false;
        }

        .................
        else {
            if(displayId == Display.DEFAULT_DISPLAY) {
                if (eventTime > mLastUserActivityTime) {
                    mLastUserActivityTime = eventTime;
                    mDirty |= DIRTY_USER_ACTIVITY;
                    if (event == PowerManager.USER_ACTIVITY_EVENT_BUTTON) {
                        mDirty |= DIRTY_QUIESCENT;
                    }
                    return true;
                }
            }
        }
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_POWER);
    }
    return false;
}

???????在userActivityNoUpdateLocked()內部主要更新了mLastUserActivityTime,接下來執(zhí)行updatePowerStateLocked()來進行新一輪的計算;

四.設備管理狀態(tài)

1.WAKEFULNESS_AWAKE

???????設備的初始狀態(tài)或設備被喚醒時的狀態(tài),在wakeUpNoUpdateLocked()內調用setWakefulnessLocked()進行設置;

private boolean wakeUpNoUpdateLocked(long eventTime, String reason, int reasonUid,
        String opPackageName, int opUid) {

    if (eventTime < mLastSleepTime || mWakefulness == WAKEFULNESS_AWAKE
            || !mBootCompleted || !mSystemReady) {
        return false;
    }

    Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, TRACE_SCREEN_ON, 0);

    Trace.traceBegin(Trace.TRACE_TAG_POWER, "wakeUp");
    try {
        switch (mWakefulness) {
            case WAKEFULNESS_ASLEEP:
                Slog.i(TAG, "Waking up from sleep (uid=" + reasonUid + " reason=" + reason
                        + ")...");
                break;
            case WAKEFULNESS_DREAMING:
                Slog.i(TAG, "Waking up from dream (uid=" + reasonUid + " reason=" + reason
                        + ")...");
                break;
            case WAKEFULNESS_DOZING:
                Slog.i(TAG, "Waking up from dozing (uid=" + reasonUid + " reason=" + reason
                        + ")...");
                break;
        }

        mLastWakeTime = eventTime;
        setWakefulnessLocked(WAKEFULNESS_AWAKE, 0);
        mNotifier.onWakeUp(reason, reasonUid, opPackageName, opUid);

        userActivityNoUpdateLocked(eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER,
                0, reasonUid, Display.DEFAULT_DISPLAY);
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_POWER);
    }
    return true;
}

???????當設備被重新喚醒時,會將狀態(tài)設為WAKEFULNESS_AWAKE并執(zhí)行userActivityNoUpdateLocked()來更新User Actiivty信息;

2. WAKEFULNESS_DREAMING

???????設備在一定時間沒有用戶活動參與和沒有應用持有WakeLock時,會進入DREAMING狀態(tài)啟動屏保來進行關屏;

private boolean napNoUpdateLocked(long eventTime, int uid) {
    if (eventTime < mLastWakeTime || mWakefulness != WAKEFULNESS_AWAKE
            || !mBootCompleted || !mSystemReady) {
        return false;
    }

    Trace.traceBegin(Trace.TRACE_TAG_POWER, "nap");
    try {
        Slog.i(TAG, "Nap time (uid " + uid +")...");

        mSandmanSummoned = true;
        setWakefulnessLocked(WAKEFULNESS_DREAMING, 0);
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_POWER);
    }
    return true;
}

???????前面分析到,當定期執(zhí)行updateUserActivitySummaryLocked()去檢測發(fā)現(xiàn)在指定的時間段內沒有用戶活動參與時,會將mUserActivitySummary設為 USER_ACTIVITY_SCREEN_DREAM,接下來將狀態(tài)設置為WAKEFULNESS_DREAMING然后進入屏保;

3.WAKEFULNESS_DOZING

???????WAKEFULNESS_ASLEEP之前的一個過渡狀態(tài),在執(zhí)行goToSleep()如果沒有將flag設置為
PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE就會進入該狀態(tài);

private boolean goToSleepNoUpdateLocked(long eventTime, int reason, int flags, int uid) {
    if (eventTime < mLastWakeTime
            || mWakefulness == WAKEFULNESS_ASLEEP
            || mWakefulness == WAKEFULNESS_DOZING
            || !mBootCompleted || !mSystemReady) {
        return false;
    }

    Trace.traceBegin(Trace.TRACE_TAG_POWER, "goToSleep");
    try {
        switch (reason) {
            case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN:
                Slog.i(TAG, "Going to sleep due to device administration policy "
                        + "(uid " + uid +")...");
                break;
            case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT:
                Slog.i(TAG, "Going to sleep due to screen timeout (uid " + uid +")...");
                break;
            case PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH:
                Slog.i(TAG, "Going to sleep due to lid switch (uid " + uid +")...");
                break;
            case PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON:
                Slog.i(TAG, "Going to sleep due to power button (uid " + uid +")...");
                break;
            case PowerManager.GO_TO_SLEEP_REASON_SLEEP_BUTTON:
                Slog.i(TAG, "Going to sleep due to sleep button (uid " + uid +")...");
                break;
            case PowerManager.GO_TO_SLEEP_REASON_HDMI:
                Slog.i(TAG, "Going to sleep due to HDMI standby (uid " + uid +")...");
                break;
            default:
                Slog.i(TAG, "Going to sleep by application request (uid " + uid +")...");
                reason = PowerManager.GO_TO_SLEEP_REASON_APPLICATION;
                break;
        }

        mLastSleepTime = eventTime;
        mSandmanSummoned = true;
        setWakefulnessLocked(WAKEFULNESS_DOZING, reason);

        // Report the number of wake locks that will be cleared by going to sleep.
        int numWakeLocksCleared = 0;
        final int numWakeLocks = mWakeLocks.size();
        for (int i = 0; i < numWakeLocks; i++) {
            final WakeLock wakeLock = mWakeLocks.get(i);
            switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
                case PowerManager.FULL_WAKE_LOCK:
                case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
                case PowerManager.SCREEN_DIM_WAKE_LOCK:
                    numWakeLocksCleared += 1;
                    Slog.d(TAG, " Wl info: pkg:"+ wakeLock.mPackageName);
                    break;
            }
        }
        EventLog.writeEvent(EventLogTags.POWER_SLEEP_REQUESTED, numWakeLocksCleared);

        // Skip dozing if requested.
        if ((flags & PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE) != 0) {
            reallyGoToSleepNoUpdateLocked(eventTime, uid);
        }
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_POWER);
    }
    return true;
}

4.WAKEFULNESS_ASLEEP

???????當power鍵滅屏時,會在PhoneWindowManager中處理按鍵事件后,調用到PMS的gotoSleep()進行滅屏處理,車機上會通過CarService來執(zhí)行goToSleep(),如果flag設置了PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE,則會直接進入ASLEEP狀態(tài);

private boolean goToSleepNoUpdateLocked(long eventTime, int reason, int flags, int uid) {
    ..................
    ..................

    // Skip dozing if requested.
    if ((flags & PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE) != 0) {
        reallyGoToSleepNoUpdateLocked(eventTime, uid);
    }

    return true;
}

private boolean reallyGoToSleepNoUpdateLocked(long eventTime, int uid) {

    if (eventTime < mLastWakeTime || mWakefulness == WAKEFULNESS_ASLEEP
            || !mBootCompleted || !mSystemReady) {
        return false;
    }

    Trace.traceBegin(Trace.TRACE_TAG_POWER, "reallyGoToSleep");
    try {
        Slog.i(TAG, "Sleeping (uid " + uid +")...");

        setWakefulnessLocked(WAKEFULNESS_ASLEEP, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_POWER);
    }
    return true;
}

???????如果Flag沒有設置PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE,則會在updateDreamLocked()中更新屏保狀態(tài)時,如果此時處于Doze狀態(tài)且沒有進行屏保,則會進入ASLEEP狀態(tài);

if (wakefulness == WAKEFULNESS_DREAMING) {
    ....................
    ....................
    wakeUpNoUpdateLocked(SystemClock.uptimeMillis(), "android.server.power:DREAM",
             Process.SYSTEM_UID, mContext.getOpPackageName(), Process.SYSTEM_UID);
    updatePowerStateLocked();
} else if (wakefulness == WAKEFULNESS_DOZING) {
    if (isDreaming) {
        return; // continue dozing
    }

    // Doze has ended or will be stopped.  Update the power state.
    reallyGoToSleepNoUpdateLocked(SystemClock.uptimeMillis(), Process.SYSTEM_UID);
    updatePowerStateLocked();
}

5.狀態(tài)轉換圖

image

???????未完待續(xù).....

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容