Android 电源管理相关逻辑之PMS
一.PowerManagerService
1.概述
PowerManagerService是负责管理、协调设备电源管理的系统服务之一,设备常见功能如亮灭屏、亮度调节、低电量模式、保持CPU唤醒等,都会通过PMS的协调和处理。其继承自SystemService,因此具有SystemService子类的共性:具有生命周期方法,由SystemServer启动、注册到系统服务中,通过Binder和其他组件进行交互等。
2.结构图
image3.启动过程
和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监听;
以上就是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.流程总结
image2.调节方式
不同的调节方式对应不同的入口及判断逻辑,只分析调用入口及涉及的关键策略来选择最终目标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.png2.条件判断
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未完待续.....