Android 电源管理相关逻辑之PMS

一.PowerManagerService

1.概述

       PowerManagerService是负责管理、协调设备电源管理的系统服务之一,设备常见功能如亮灭屏、亮度调节、低电量模式、保持CPU唤醒等,都会通过PMS的协调和处理。其继承自SystemService,因此具有SystemService子类的共性:具有生命周期方法,由SystemServer启动、注册到系统服务中,通过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);
    }
}

       通过上面可以看到,在构造方法中首先创建了一个HandlerThread;其次获取了两个Suspend锁,SuspendBlocker是一种锁机制,只用于系统内部,上层申请的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的监听。

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是一个二进制的标记位,用来表示电源状态哪一部分发生了改变,通过对其进行置位(|操作)、清零(~操作),得到二进制数各个位的值(0或1),进行不同的处理 ,然后执行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)、电池状态监听服务(BatteryService)等服务,用于进行交互;
  b.注册用于和其他Sytem交互的广播;
  c.调用updateSettingsLocked()方法更新Settings中值的变化;
  d.调用readConfigurationLocked()方法读取配置文件中的默认值;
  e.注册SettingsObserver监听;

image

  以上就是PowerManagerService的整个启动过程;

二.屏幕亮度调节

1.调节流程

       当通过系统设置等进行屏幕亮度调节时,会调用到PMS内部的updatePowerStateLocked(),通过该方法进行接下来的逻辑执行,最终通过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);
    }
}

       当亮度调节时,处理逻辑主要是在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作为参数传入,mDisplayManagerInternal是在systemReady()内部获取的;

1.2.DisplayPowerController.java

1.2.1.requestPowerState()

       DisplayManagerInternal内部的requestPowerState为抽象方法,因此会调用到实现类中,具体是在DisplayManagerService内部的LocalService,看一下具体实现:

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,后续会使用;接着执行sendUpdatePowerStateLocked(),在该方法内部会发送异步消息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();
    ....................................
    .....根据策略选择最终的brightness值.....
    ....................................
    animateScreenBrightness(brightness,
        slowChange ? mBrightnessRampRateSlow : mBrightnessRampRateFast);
    ...........
}

       该方法内部主要干了6件事:
  a.将要更新的DisplayPowerRequest实例赋值给mPowerRequest;
  b.如果为首次执行的话,需要执行initialize()来执行初始化操作,创建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.根据mPowerRequest.policy来更新state,此处为Display.STATE_ON
  d.执行animateScreenStateChange(state, performScreenOffTransition)来更新DisplayPowerState;
  e.根据策略进行选择,最终确定要更新的brightness值;
  f.执行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()内部会执行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()会执行到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);
        }
    }
}
}

       可以看到,在执行setState()后,最终会执行mBlanker.requestDisplayState(state, backlight),mBlanker是DisplayBlanker实例,初始化是在DisplayPowerController构造方法内,在DisplayPowerController内部的initialize()内部传入的,根据调用关系会追溯到DisplayMangerService的LocalService的initPowerManagerment()方法,该方法是在PowerManagerService的systemReady()方法内执行的;

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,执行到requestGlobalDisplayStateInternal(state, brightness),根据调用关系最终会执行到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;
}

       根据调用关系看到,会通过DisplayDevice的requestDisplayStateLocked()来获取到Runnable;
  在DisplayManagerService的onStart()内发送消息来执行registerDisplayAdapterLocked(new LocalDisplayAdapter())加载BUILT_IN_DISPLAY_IDS_TO_SCAN对应的LocalDisplayDevice(继承DisplayDevice),加载成功后存入mDisplayDevices列表内进行管理;
  在创建LocalDisplayDeivce时会通过lights.getLight(LightsManager.LIGHT_ID_BACKLIGHT)获取mBackLight,对应的是LightsService内部的LightImpl继承light;
  在通过LocalDisplayDevice获取到Runnable后接着执行run(),会执行到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()内部会执行到mBacklight.setBrightness(brightness),具体实现逻辑是在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.调节方式

       不同的调节方式对应不同的入口及判断逻辑,只分析调用入口及涉及的关键策略来选择最终目标brightness值逻辑;

2.1.系统设置调节

       系统设置在调节屏幕亮度时,会实时更新Settings.SCREEN_BRIGHTNESS值,DisplayPowerController在监听到该值变化后会执行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);
}

       监听到变化后,先通过getScreenBrightnessSetting()来获取到当前值,然后赋值给mPendingScreenBrightnessSetting,接下来执行sendUpdatePowerState(),最终执行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;
}

       结论:系统设置会根据mCurrentScreenBrightnessSetting的值来设置对应的目标brightness值;

2.2.快速设置调节

       快速设置来滑动进度条来调节屏幕亮度时,会调用PowerManagerService的setTemporaryScreenBrightnessSettingOverride()方法:

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

       跟随调用关系,调用到DisplayPowerController的setTemporaryBrightness()方法,发送MSG_SET_TEMPORARY_BRIGHTNESS消息,设置mTemporaryScreenBrightness为传入的值,然后执行updatePowerState():

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

  结论:快速设置会根据mTemporaryScreenBrightness的值来设置对应的目标brightness值;

2.3.Window属性调节

在视频播放界面可以通过左侧上下滑动来调节屏幕亮度,具体实现方式如下:

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后执行window.setAttributes(lp)可以来调节屏幕亮度;
  Window执行setAttributes()会执行到Activity的onWindowAttributesChanged()方法,调用到WindowManagerGlobal的updateViewLayout()最终调用到ViewRootImpl的setLayoutParams来执行重新绘制;
  绘制流程就不陈述了,最终会执行到RootWindowContainer内部的performSurfacePlacement()方法,接下来通过handleNotObscuredLocked()获取到对应WindowState的w.mAttrs.screenBrightness赋值给mScreenBrightness,然后在performSurfacePlacement()发送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,然后执行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,经过设置后screenBrightness>0,接着执行到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属性调节会根据mScreenBrightnessOverrideFromWindowManager的值来设置对应的目标brightness值;

2.4.总结

       设置屏幕亮度时,主要是在DisplayPowerController内部的updatePowerState()来对目标screenBrightness进行设置,screenBrightness默认值为PowerManager.BRIGHTNESS_DEFAULT = -1,会根据DisplayPowerRequest及其他策略进行选择,顺序依次为:
  a.if (brightness < 0 && mPowerRequest.screenBrightness >= 0):通过设置Window属性来进行调节(视频播放界面)
  b.if (mTemporaryScreenBrightness > 0):通过快速设置滑动来进行调节
  c.if (brightness < 0) {brightness = clampScreenBrightness(mCurrentScreenBrightnessSetting)}:通过系统设置滑动调节

三.自动进入屏保

       当系统设置内部设置了自动进入屏保时间后,如果在此段时间后满足进入条件,会进入屏保,该逻辑入口是在PMS内部的updatePowerStateLocked(),一起看一下:

1.整体流程

       本流程只分析满足条件后进入屏保的整个过程,关于条件判断会在下一节中进行分析,先从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);
    ...................
}

       在该方法内部首先循环执行了三个方法:
  a.updateWakeLockSummaryLocked():根据mWakeLocks来计算得到mWakeLockSummary的值;
       b.updateUserActivitySummaryLocked():计算得到mUserActivitySummary以及何时进行下一次check;
       c.updateWakefulnessLocked():判断是否可以进入屏保及更新mWakefulness状态;
  d.updateDreamLocked():根据当前状态选择是否进入屏保;

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;
}

       当满足以上条件后,执行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状态WAKEFULNESS_DREAMING,最后返回true;
  前面的循环中当结果返回true时,会执行下一次循环,重新计算mWakeLockSummary和mUserActivitySummary,最终返回false,执行break退出循环,执行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();
        }
    }
}

       满足条件后执行scheduleSandmanLocked()来发送异步消息,执行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时,执行stopDream()、startDream(),接下来再执行wakeUpNoUpdateLocked(),一起看一下该方法的实现:

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;然后再执行 userActivityNoUpdateLocked()来更新user activity相关信息,接着上面进行分析,执行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()逻辑执行过程中首先获取到本地屏保实现的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()来启动本地实现的屏保服务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;
        }
    }
}

       根据当前持有的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;
        }
    }
}

       根据用户最后一次活跃时间得到进入屏保的时间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,表示在该时间时发送MSG_USER_ACTIVITY_TIMEOUT消息进行check;

3.禁止进入屏保

       禁止进入屏保就是创造不满足进入屏保的条件就可以了,主要是来影响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.执行流程

       最终会执行到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();
        ...............
    }
}

       创建WakeLock并加入到mWakeLocks进行管理,更新mDrity值DIRTY_WAKE_LOCKS,接下来执行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;
    }
    ..........................
}

       可以看到,在该方法内根据上层申请的WakeLocks计算得到的结果mWakeLockSummary来决定是否通过mWakeLockSuspendBlocker向底层进行acquire();

3.2.更新UserActivity

3.2.1.userActivityWithDisplayId()

3.2.2.userActivityFromNative()

3.2.3.执行流程

       以上两种方式都会执行到userActivityInternal()方法:

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

       先执行userActivityNoUpdateLocked()来执行一些更新操作;

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,接下来执行updatePowerStateLocked()来进行新一轮的计算;

四.设备管理状态

1.WAKEFULNESS_AWAKE

       设备的初始状态或设备被唤醒时的状态,在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;
}

       当设备被重新唤醒时,会将状态设为WAKEFULNESS_AWAKE并执行userActivityNoUpdateLocked()来更新User Actiivty信息;

2. WAKEFULNESS_DREAMING

       设备在一定时间没有用户活动参与和没有应用持有WakeLock时,会进入DREAMING状态启动屏保来进行关屏;

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;
}

       前面分析到,当定期执行updateUserActivitySummaryLocked()去检测发现在指定的时间段内没有用户活动参与时,会将mUserActivitySummary设为 USER_ACTIVITY_SCREEN_DREAM,接下来将状态设置为WAKEFULNESS_DREAMING然后进入屏保;

3.WAKEFULNESS_DOZING

       WAKEFULNESS_ASLEEP之前的一个过渡状态,在执行goToSleep()如果没有将flag设置为
PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE就会进入该状态;

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来执行goToSleep(),如果flag设置了PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE,则会直接进入ASLEEP状态;

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()中更新屏保状态时,如果此时处于Doze状态且没有进行屏保,则会进入ASLEEP状态;

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.状态转换图

image

       未完待续.....

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容