PMS

PowerManagerService是负责管理、协调设备电源管理的系统服务之一,它在Framework层建立起一个策略控制方案,向下决策HAL层以及kernel层来控制设备待机状态、控制显示屏、背光灯、距离或光线传感器等硬件设备的状态。向上提供给应用程序相应的操作接口,如听音乐保持系统唤醒、应用通知唤醒屏幕等场景。

该类继承自SystemService,具有生命周期方法,由SystemServer启动并注册到系统服务中,通过Binder和其他组件进行交互。

生命周期方法:(1)Constructor:通过反射调用,获取实例;(2)onStart()方法:开启对应的SystemService;(3)onBootPhase()方法:在SystemService服务启动过程中指定服务的启动阶段,每个阶段的工作。

1、PMS的启动

PMS和SystemService的其他子类一样由SystemServer通过反射的方式启动。首先,在SystemServer的main()方法中调用自身的run()方法,并在run()方法中启动三类服务:引导服务、核心服务和其他服务,引导服务就包括了PMS。

1
2
3
4
//SystemServer的main()中。
public static void main(String[] args){
new SystemServer().run();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
//SystemServer的run()方法
private void run() {
//......
try {
startBootstrapServices();//启动引导服务
startCoreServices();//启动核心服务
startOtherServices();//启动其他服务
} catch (Throwable ex) {
} finally {
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
......
}

在启动引导服务时,PMS随之启动,如下代码:

1
2
3
4
5
6
7
private void startBootstrapServices() {
//通过SystemManagerService的startService()方法进行启动,在startService()中,获取了PowerManagerService的Class对象,然后使用反射机制,通过Class对象获取PMS的构造函数,从而获得了一个PMS对象。
mPowerManagerService = mSystemServiceManager.
startService(PowerManagerService.class);
//AMS中初始化PowerManager
mActivityManagerService.initPowerManagement();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//startService()方法
public <T extends SystemService> T startService(Class<T> serviceClass) {
try {
//...
final T service;
try {
//通过反射创建 PowerManagerService
Constructor<T> constructor = serviceClass.getConstructor(Context.class);
service = constructor.newInstance(mContext);
} catch (InstantiationException ex) {
//...
}

startService(service);
return service;
} finally {}
}

public void startService(@NonNull final SystemService service) {
// 将服务添加到服务列表里
mServices.add(service);

try {
// 启动服务,最终回调到 onStart 方法
service.onStart();
} catch (RuntimeException ex) {}
}

startService()方法可以看到对于PMS,先执行了其构造方法,接着执行了onStart()方法。构造方法如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public PowerManagerService(Context context) {
super(context);
mContext = context;
//获取一个系统级别的HandlerThread,继承于Thread
mHandlerThread = new ServiceThread(TAG,
Process.THREAD_PRIORITY_DISPLAY, false );
mHandlerThread.start();//开启线程
//根据Looper实例化一个Handler
mHandler = new PowerManagerHandler(mHandlerThread.getLooper());
synchronized (mLock) {
//获取当应用申请wakelock后让CUP保持激活状态的Suspendlocker实例
mWakeLockSuspendBlocker =
createSuspendBlockerLocked("PowerManagerService.WakeLocks");
//获取当显示屏开启、显示屏准备就绪或者有用户活动后让CPU保持激活状态的Suspendlocker
mDisplaySuspendBlocker =
createSuspendBlockerLocked("PowerManagerService.Display");
//申请PowerManagerService.Display类型的suspendBloker锁
mDisplaySuspendBlocker.acquire();
//持有Display锁的bool值
mHoldingDisplaySuspendBlocker = true;
//AutoSuspend模式是否开启
mHalAutoSuspendModeEnabled = false;
//是否处于交互模式
mHalInteractiveModeEnabled = true;
//设置wakefulness为亮屏状态
mWakefulness = WAKEFULNESS_AWAKE;
//本地方法
nativeInit();//初始化
nativeSetAutoSuspend(false);//设置是否开启anto suspend模式
nativeSetInteractive(true);//设置是否处于交互模式
nativeSetFeature(POWER_FEATURE_DOUBLE_TAP_TO_WAKE, 0);
getPowerHintSceneIdConfig();
}
}
//SuspendBlocker是一种锁机制,只用于系统内部,上层申请的wakelock锁在PMS中都会反映为SuspendBlocker锁,这里获取的两个Suspend锁在申请wakelock时会用到,最后,调用了本地方法,这几个方法会通过JNI层调用到HAL层。

构造方法执行完后执行onstart()方法,代码如下:

1
2
3
4
5
6
7
8
9
10
11
//在该方法中,首先对服务进行Binder注册(使得其他模块可以通过Binder机制获取该实例)和本地注册(在System进程才能获取到该实例),最后设置Watchdog监听。
@Override
public void onStart() {
//发布到系统服务中
publishBinderService(Context.POWER_SERVICE, new BinderService());
//发布到本地服务
publishLocalService(PowerManagerInternal.class, new LocalService());
//设置Watchdog监听
Watchdog.getInstance().addMonitor(this);
Watchdog.getInstance().addThread(mHandler);
}

对服务进行远程注册,是通过Binder机制实现的,实际上,从代码中可以出,注册的并不是PMS本身,而是其内部类BinderService,BinderService继承自IPowerManager.Stub,IPowerManager.Stub继承自Binder并且实现了IPowerManager,因此可以知道,BinderService作为Binder的服务端,可以和客户端进行交互;注册的过程在ServiceManager中进行的,代码如下:

1
2
3
4
5
6
7
public static void addService(String name, IBinder service, boolean allowIsolated) {
try {
getIServiceManager().addService(name, service, allowIsolated);
} catch (RemoteException e) {
Log.e(TAG, "error in addService", e);
}
}

经ServiceManager注册后,就可以根据Context.POWER_SERVICE在其他服务中获取对应的IBinder了,以PMS为例,当从其他应用中获取了PMS服务后,就可以调用PMS.BinderService中的方法。所以,PMS中的BinderService相当于服务端,其中的方法可以供其他应用进行调用,从而完成和PMS的交互。

通过Binder进行注册是为了供其他应用或系统服务和PMS进行交互。同样的,本地注册表示只能在System进程内部调用,和BinderService一样,本地注册也并非注册的是PMS,而是另一个内部类LocalService,LocalService继承自PowerManagerInternal(带有Internal的类一般都在System进程内使用);Binder注册是在SystemManager中进行注册的,本地注册则是在LocalServices中进行注册,其注册方法如下:

1
2
3
4
5
6
7
8
public static <T> void addService(Class<T> type, T service) {
synchronized (sLocalServiceObjects) {
if (sLocalServiceObjects.containsKey(type)) {
throw new IllegalStateException("Overriding service registration");
}
sLocalServiceObjects.put(type, service);
}
}

本地注册完后,就可以在System进程内,通过PowerManagerInternal.class获取PMS.LocalService对象,从而完成交互了。

在远程注册和本地注册都完成以后,给PMS设置了watchDog监听,onStart()方法调用完毕。此时,继续回到SytemServer中,startBootstrapServices()方法中启动PMS部分执行完成了,然后根据SystemService的生命周期,会开始执行onBootPhase(),这个方法的功能是为所有的已启动的服务指定启动阶段,从而可以在指定的启动阶段来做指定的工作。源代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*Starts the specified boot phase for all system services that have been started   
* up to this point.
* @param phase The boot phase to start.*/
public void startBootPhase(final int phase) {
if (phase <= mCurrentPhase) {
throw new IllegalArgumentException("Next phase must be larger than previous");
}
mCurrentPhase = phase;
try {
final int serviceLen = mServices.size();
for (int i = 0; i < serviceLen; i++) {
final SystemService service = mServices.get(i);
try {
service.onBootPhase(mCurrentPhase);
} catch (Exception ex) {
}
}
}
}

在SystemServiceManager的startBootPhase()中,调用SystemService的onBootPhase(int)方法,此时每个SystemService都会执行其对应的onBootPhase()方法。通过在SystemServiceManager中传入不同的形参,回调所有SystemService的onBootPhase()方法,并根据形参的不同,在方法实现中完成不同的工作,在SystemService中定义了五个阶段:

  • SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY:这是一个依赖项,只在DisplayManagerService中进行了对应处理;
  • SystemService.PHASE_LOCK_SETTINGS_READY:经过这个引导阶段后,服务才可以接收到wakelock相关设置数据;
  • SystemService.PHASE_SYSTEM_SERVICES_READY:经过这个引导阶段后,服务才可以安全地使用核心系统服务;
  • SystemService.PHASE_ACTIVITY_MANAGER_READY:经过这个引导阶段后,服务可以发送广播
  • SystemService.PHASE_THIRD_PARTY_APPS_CAN_START:经过这个引导阶段后,服务可以启动第三方应用,第三方应用也可以通过Binder来调用服务。
  • SystemService.PHASE_BOOT_COMPLETED:经过这个引导阶段后,说明服务启动完成,这时用户就可以和设备进行交互。

因此,只要在其他模块中调用了SystemServiceManager.startBootPhase()方法,都会触发各自的onBootPhase()。PMS的onBootPhase()方法只对引导阶段的2个阶段做了处理,具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Override
public void onBootPhase(int phase) {
synchronized (mLock) {
if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
//统计启动的apk个数
incrementBootCount();
} else if (phase == PHASE_BOOT_COMPLETED) {
mBootCompleted = true;
PMSFactory.getInstance().createPowerManagerServiceUtils(mContext)
.setBootCompleted(true);
//mDirty置位,mDirty是一个二进制的标记位,用来表示电源状态哪一部分发生了改变,通过对其进行置位(|操作)、清零(~操作)得到二进制数各个位的值(0或1)。
mDirty |= DIRTY_BOOT_COMPLETED;
//更新用户活动时间
userActivityNoUpdateLocked(
now, PowerManager.USER_ACTIVITY_EVENT_OTHER,
0, Process.SYSTEM_UID);
//更新电源状态信息
updatePowerStateLocked();
......
}
}
}

onBootPhase()方法执行完,生命周期方法也执行完毕,引导服务也启动完成。

对于PMS,在SystemServer.startOtherServices()中还进行了一步操作:

1
mPowerManagerService.systemReady(mActivityManagerService.getAppOpsService());

即PMS依次执行完构造方法、onStart()onBootPhase()(会调用多次),之后执行systemReady()方法。

systemReady方法的作用:

1、获取各类本地服务和远程服务,如屏保(DreamManagerService)、窗口(PhoneWindowManager)、电池状态监听服务(BatteryService)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
synchronized (mLock) {
mSystemReady = true;
mAppOps = appOps;
//和DreamManagerService交互
mDreamManager = getLocalService(DreamManagerInternal.class);
//和DisplayManagerService交互
mDisplayManagerInternal = getLocalService(DisplayManagerInternal.class);
//和WindowManagerService交互
mPolicy = getLocalService(WindowManagerPolicy.class);
//和BatteryService交互
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());
//获取BatteryStatsService
mBatteryStats = BatteryStatsService.getService();
//mNotifier用于PMS和其他系统服务间的交互,以及广播的发送
mNotifier = new Notifier(Looper.getMainLooper(), mContext, mBatteryStats,
mAppOps,
createSuspendBlockerLocked("PowerManagerService.Broadcasts"),
mPolicy);
//无线充电相关
mWirelessChargerDetector = new WirelessChargerDetector(sensorManager,
createSuspendBlockerLocked
("PowerManagerService.WirelessChargerDetector"),
mHandler);
//监听Stetings中值的变化
mSettingsObserver = new SettingsObserver(mHandler);
//和LightsManager交互
mLightsManager = getLocalService(LightsManager.class);
mAttentionLight =
mLightsManager.getLight(LightsManager.LIGHT_ID_ATTENTION);
//mDisplayPowerCallbacks提供PMS和Display的接口,当DisplayPowerController发生改变,通过该接口回调PMS中的实现
//initPowerManagement()方法中实例化了DisplayPowerController,
//DPC是和显示有关,如亮灭屏、背光调节
mDisplayManagerInternal.initPowerManagement(mDisplayPowerCallbacks, mHandler, sensorManager);

2、注册用于和其他System交互的广播。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Register for broadcasts from other components of the system.
// 注册BatteryService中ACTION_BATTERY_CHANGED广播
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
mContext.registerReceiver(new BatteryReceiver(), filter, null, mHandler);
//Dream相关
filter = new IntentFilter();
filter.addAction(Intent.ACTION_DREAMING_STARTED);
filter.addAction(Intent.ACTION_DREAMING_STOPPED);
mContext.registerReceiver(new DreamReceiver(), filter, null, mHandler);
//
filter = new IntentFilter();
filter.addAction(Intent.ACTION_USER_SWITCHED);
mContext.registerReceiver(new UserSwitchedReceiver(), filter, null, mHandler);
//Dock相关
filter = new IntentFilter();
filter.addAction(Intent.ACTION_DOCK_EVENT);
mContext.registerReceiver(new DockReceiver(), filter, null, mHandler);

3、调用updateSettingsLocked()方法更新Setting中值的变化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
private void updateSettingsLocked() {
final ContentResolver resolver = mContext.getContentResolver();
//屏保是否支持
mDreamsEnabledSetting = (Settings.Secure.getIntForUser(resolver,
Settings.Secure.SCREENSAVER_ENABLED,
mDreamsEnabledByDefaultConfig ? 1 : 0,
UserHandle.USER_CURRENT) != 0);
//休眠时是否启用屏保
mDreamsActivateOnSleepSetting = (Settings.Secure.getIntForUser(resolver,
Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP,
mDreamsActivatedOnSleepByDefaultConfig ? 1 : 0,
UserHandle.USER_CURRENT) != 0);
//插入基座时屏保是否激活
mDreamsActivateOnDockSetting = (Settings.Secure.getIntForUser(resolver,
Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
mDreamsActivatedOnDockByDefaultConfig ? 1 : 0,
UserHandle.USER_CURRENT) != 0);
//设备在一段时间不活动后进入休眠或者屏保状态的时间,15*1000ms
mScreenOffTimeoutSetting = Settings.System.getIntForUser(resolver,
Settings.System.SCREEN_OFF_TIMEOUT,
DEFAULT_SCREEN_OFF_TIMEOUT,
UserHandle.USER_CURRENT);
/*设备在一段时间不活动后完全进入休眠状态之前的超时时间,
该值必须大于SCREEN_OFF_TIMEOUT,否则设置了屏保后来不及显示屏保就sleep*/
mSleepTimeoutSetting = Settings.Secure.getIntForUser(resolver,
Settings.Secure.SLEEP_TIMEOUT, DEFAULT_SLEEP_TIMEOUT,
UserHandle.USER_CURRENT);
//充电时屏幕一直开启
mStayOnWhilePluggedInSetting = Settings.Global.getInt(resolver,
Settings.Global.STAY_ON_WHILE_PLUGGED_IN,
BatteryManager.BATTERY_PLUGGED_AC);
//是否支持剧院模式
mTheaterModeEnabled = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.THEATER_MODE_ON, 0) == 1;
//屏幕保持常亮
mAlwaysOnEnabled = mAmbientDisplayConfiguration.
alwaysOnEnabled(UserHandle.USER_CURRENT);
//双击唤醒屏幕设置
if (mSupportsDoubleTapWakeConfig) {
boolean doubleTapWakeEnabled = Settings.Secure.getIntForUser(resolver,
Settings.Secure.DOUBLE_TAP_TO_WAKE,
DEFAULT_DOUBLE_TAP_TO_WAKE,
UserHandle.USER_CURRENT) != 0;
if (doubleTapWakeEnabled != mDoubleTapWakeEnabled) {
mDoubleTapWakeEnabled = doubleTapWakeEnabled;
nativeSetFeature(POWER_FEATURE_DOUBLE_TAP_TO_WAKE,
mDoubleTapWakeEnabled ? 1 : 0);
}
}
final String retailDemoValue = UserManager.isDeviceInDemoMode(mContext) ?
"1" : "0";
......
//屏幕亮度
mScreenBrightnessSetting = Settings.System.getIntForUser(resolver,
Settings.System.SCREEN_BRIGHTNESS, mScreenBrightnessSettingDefault,
UserHandle.USER_CURRENT);
//自动调节亮度值(>0.0 <1.0)
final float oldScreenAutoBrightnessAdjustmentSetting =
mScreenAutoBrightnessAdjustmentSetting;
mScreenAutoBrightnessAdjustmentSetting =
Settings.System.getFloatForUser(resolver,
Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0.0f,
UserHandle.USER_CURRENT);
//重置临时亮度值
if (oldScreenBrightnessSetting != getCurrentBrightnessSettingLocked()) {
mTemporaryScreenBrightnessSettingOverride = -1;//临时亮度值
}
if (oldScreenAutoBrightnessAdjustmentSetting !=
mScreenAutoBrightnessAdjustmentSetting) {
mTemporaryScreenAutoBrightnessAdjustmentSettingOverride = Float.NaN;//临时自动亮度调节比例
}
//亮度调节模式,自动1,正常0
mScreenBrightnessModeSetting = Settings.System.getIntForUser(resolver,
Settings.System.SCREEN_BRIGHTNESS_MODE,
Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
UserHandle.USER_CURRENT);
//低电量模式是否可用,1表示true
final boolean lowPowerModeEnabled = Settings.Global.getInt(resolver,
Settings.Global.LOW_POWER_MODE, 0) != 0;
if (lowPowerModeEnabled != mLowPowerModeSetting
|| autoLowPowerModeConfigured != mAutoLowPowerModeConfigured) {
mLowPowerModeSetting = lowPowerModeEnabled;
mAutoLowPowerModeConfigured = autoLowPowerModeConfigured;
//更新低电量模式
updateLowPowerModeLocked();
}
//标志位置位
mDirty |= DIRTY_SETTINGS;
}

4、调用readConfigurationLocked()方法读取配置文件中的默认值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
private void readConfigurationLocked() {
final Resources resources = mContext.getResources();
/**
* auto_suspend模式是否和display分离
* 如果为false,则在亮屏前调用autosuspend_disable(),灭屏后调用
* autosuspend_enable();
* 如果为ture,则调用autosuspend_display()和autosuspend_enable()独立于display
* on/off.
*/
mDecoupleHalAutoSuspendModeFromDisplayConfig = resources.getBoolean(
com.android.internal.R.bool.
config_powerDecoupleAutoSuspendModeFromDisplay);
/**
* interactive模式是否和display分离
* 如果为false,则在亮屏前调用setInteractive(..., true),灭屏后调用
* setInteractive(...,false);
* 如果为ture,则调用setInteractive(...)独立于display on/off.
*/
mDecoupleHalInteractiveModeFromDisplayConfig = resources.getBoolean(
com.android.internal.R.bool
.config_powerDecoupleInteractiveModeFromDisplay);
//插拔USB是否亮屏
mWakeUpWhenPluggedOrUnpluggedConfig = resources.getBoolean(
com.android.internal.R.bool.config_unplugTurnsOnScreen);
//设备处于剧院模式时,插拔USB是否亮屏
mWakeUpWhenPluggedOrUnpluggedInTheaterModeConfig = resources.getBoolean(
com.android.internal.R.bool.config_allowTheaterModeWakeFromUnplug);
//是否允许设备由于接近传感器而关闭屏幕时CPU挂起,进入suspend状态
mSuspendWhenScreenOffDueToProximityConfig = resources.getBoolean(
com.android.internal.R.bool.
config_suspendWhenScreenOffDueToProximity);
//是否支持屏保
mDreamsSupportedConfig = resources.getBoolean(
com.android.internal.R.bool.config_dreamsSupported);
//是否屏保默认打开--false
mDreamsEnabledByDefaultConfig = resources.getBoolean(
com.android.internal.R.bool.config_dreamsEnabledByDefault);
//充电和睡眠时屏保是否激活
mDreamsActivatedOnSleepByDefaultConfig = resources.getBoolean(
com.android.internal.R.bool.config_dreamsActivatedOnSleepByDefault);
//Dock时屏保是否激活
mDreamsActivatedOnDockByDefaultConfig = resources.getBoolean(
com.android.internal.R.bool.config_dreamsActivatedOnDockByDefault);
//放电时是否允许进入屏保
mDreamsEnabledOnBatteryConfig = resources.getBoolean(
com.android.internal.R.bool.config_dreamsEnabledOnBattery);
//充电时允许屏保的最低电量,使用-1禁用此功能
mDreamsBatteryLevelMinimumWhenPoweredConfig = resources.getInteger(
com.android.internal.R.integer.
config_dreamsBatteryLevelMinimumWhenPowered);
//放电时允许屏保的最低电量,使用-1禁用此功能,默认15
mDreamsBatteryLevelMinimumWhenNotPoweredConfig = resources.getInteger(
com.android.internal.R.integer.
config_dreamsBatteryLevelMinimumWhenNotPowered);
//电亮下降到该百分点,当用户活动超时后不进入屏保,默认5
mDreamsBatteryLevelDrainCutoffConfig = resources.getInteger(
com.android.internal.R.integer.config_dreamsBatteryLevelDrainCutoff);
//如果为true,则直到关闭屏幕并执行屏幕关闭动画之后,才开始Doze,默认false
mDozeAfterScreenOffConfig = resources.getBoolean(
com.android.internal.R.bool.config_dozeAfterScreenOff);
//用户活动超时的最小时间,默认10000ms,必须大于0
mMinimumScreenOffTimeoutConfig = resources.getInteger(
com.android.internal.R.integer.config_minimumScreenOffTimeout);
//用户活动超时进入且关闭屏幕前屏幕变暗的最大时间,默认7000ms,必须大于0
mMaximumScreenDimDurationConfig = resources.getInteger(
com.android.internal.R.integer.config_maximumScreenDimDuration);
//屏幕变暗的时长比例,如果用于超时时间过短,则在7000ms的基础上按还比例减少,默认20%
mMaximumScreenDimRatioConfig = resources.getFraction(
com.android.internal.R.fraction.config_maximumScreenDimRatio, 1, 1);
//是否支持双击唤醒屏幕
mSupportsDoubleTapWakeConfig = resources.getBoolean(
com.android.internal.R.bool.config_supportDoubleTapWake);
}

5、注册SettingsObserver监听

1
2
3
4
5
6
7
8
9
10
11
12
13
// Register for settings changes.
resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.SCREENSAVER_ENABLED),
false, mSettingsObserver, UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP),
false, mSettingsObserver, UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK),
false, mSettingsObserver, UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.System.getUriFor(
Settings.System.SCREEN_OFF_TIMEOUT),
.......

至此,PMS启动过程分析完毕,相关时序图如下所示:

1.1、核心方法

updatePowerStateLocked()

updatePowerStateLocked()方法是PMS中的核心方法,用以更新电源状态的改变,并进行重新计算。PMS中使用一个int值mDirty作为标志位判断电源状态是否发生改变,当发生亮灭屏、电池状态改变、暗屏、WakeLock锁申请/释放等都会调用该方法,在该方法中调用其他同级方法进行更新。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
private void updatePowerStateLocked() {
if (!mSystemReady || mDirty == 0) {
return;
}
try {
// 第一步:更新基本状态
updateIsPoweredLocked(mDirty);//更新电池信息
updateStayOnLocked(mDirty);//更新是否常亮状态
updateScreenBrightnessBoostLocked(mDirty);//更新亮度是否需要增强

// 第二步: 更新wakelock和用户活动
final long now = SystemClock.uptimeMillis();//记录当前时间
int dirtyPhase2 = 0;
for (;;) {
int dirtyPhase1 = mDirty;
dirtyPhase2 |= dirtyPhase1;
mDirty = 0;

updateWakeLockSummaryLocked(dirtyPhase1);//更新统计wakelock的标记值mWakeLockSummary
updateUserActivitySummaryLocked(now, dirtyPhase1);//更新统计userActivity的标记值mUserActivitySummary和休眠到达时间
if (!updateWakefulnessLocked(dirtyPhase1)) {//更新屏幕唤醒状态,状态改变返回true
break;
}
}

// 第三步:更新display power state
boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);

// 第四步:更新屏保dream state
updateDreamLocked(dirtyPhase2, displayBecameReady);

// 第五步:如果wakefulness改变,做最后的收尾工作。
finishWakefulnessChangeIfNeededLocked();

//第六步:更新Suspend锁
updateSuspendBlockerLocked();
}finally{
Trace.tranceEnd(Trace.TRACE_TAG_POWER);
}
}

下面对上述相关方法进行具体叙述:

updateIsPoweredLocked()

功能:(1)USB插拔亮屏入口点;(2)更新低电量模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/**
* Updates the value of mIsPowered.
* Sets DIRTY_IS_POWERED if a change occurred.
*/
private void updateIsPoweredLocked(int dirty) {
if ((dirty & DIRTY_BATTERY_STATE) != 0) {
final boolean wasPowered = mIsPowered;//是否充电
final int oldPlugType = mPlugType;//充电类型
final boolean oldLevelLow = mBatteryLevelLow;//是否处于低电量
/*---------------------BatteryService交互Begin-----------------------------*/
//通过BatteryService的本地服务BatteryManagerInternal和BatteryService进行交互,刷新电池信息,并记录上次的电池数据。
mIsPowered = mBatteryManagerInternal.isPowered(BatteryManager.
BATTERY_PLUGGED_ANY);
mPlugType = mBatteryManagerInternal.getPlugType();
mBatteryLevel = mBatteryManagerInternal.getBatteryLevel();
mBatteryLevelLow = mBatteryManagerInternal.getBatteryLevelLow();
/*---------------------BatteryService交互 End-----------------------------*/
//充电器插拔事件或者充电器类型改变,则设置 DIRTY_IS_POWERED 标志位
if (wasPowered != mIsPowered || oldPlugType != mPlugType) {
mDirty |= DIRTY_IS_POWERED;
//是否连接无线充电
final boolean dockedOnWirelessCharger =
mWirelessChargerDetector.update(
mIsPowered, mPlugType, mBatteryLevel);
final long now = SystemClock.uptimeMillis();
//插拔充电线是否唤醒屏幕
if (shouldWakeUpWhenPluggedOrUnpluggedLocked(wasPowered,
oldPlugType, dockedOnWirelessCharger)) {
//屏幕唤醒
wakeUpNoUpdateLocked(now,
"android.server.power:POWER", Process.SYSTEM_UID,
mContext.getOpPackageName(), Process.SYSTEM_UID);
}
//更新用户活动
userActivityNoUpdateLocked(
now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0,
Process.SYSTEM_UID);
//当无线充电器开始充电时给出提示音,在 mNotifier 中进行处理
if (dockedOnWirelessCharger) {
mNotifier.onWirelessChargingStarted();
}
}
//如果电源发生插拔时或者低电量标志位发生变化
if (wasPowered != mIsPowered || oldLevelLow != mBatteryLevelLow) {
if (oldLevelLow != mBatteryLevelLow && !mBatteryLevelLow) {
//当设备从低电量转换为非低电量,则设置自动打盹为 false
mAutoLowPowerModeSnoozing = false;
}
//更新低电量模式
updateLowPowerModeLocked();
}
}
}

从上述代码中可知在满足mDirty&DIRTY_BATTERY_STATE != 0时才会执行该方法,满足此条件的情况有两处:

  1. 在调用systemReady()方法中。

    1
    2
    3
    4
    5
    6
    public void systemReady(IAppOpsService appOps) {
    ....
    mDirty |= DIRTY_BATTERY_STATE;
    updatePowerStateLocked();
    ....
    }
  2. 在监听电量状态改变的广播中。

1
2
3
4
5
6
7
8
9
10
//监听ACTION_BATTERY_CHANGED
private final class BatteryReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
synchronized (mLock) {
//设置mDirty |= DIRTY_BATTERY_STAT
handleBatteryStateChangedLocked();
}
}
}

总结来说,该方法在电池状态发生变化时将被调用执行。

updateStayOnLocked()

该方法主要用于判断系统是否在Settings中设置了充电时保持屏幕亮屏后,根据是否充电来决定亮屏与否。方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private void updateStayOnLocked(int dirty) {
if ((dirty & (DIRTY_BATTERY_STATE | DIRTY_SETTINGS)) != 0) {
final boolean wasStayOn = mStayOn;
//充电时亮屏&&DevicePolicyManager中未设置最大关闭时间
//mStayOnWhilePluggedInSetting是从SettingsProvider中读取的值,表示是否设置了充电时保持屏幕常亮。若要使mStayOn为true,其先决条件是mStayOnWhilePluggedInSetting为true,同时DevicePolicyManager没有进行最大超时时间的约束,若符合则设备在充电时mStayOn为true。
if (mStayOnWhilePluggedInSetting != 0 &&
!isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked()) {
//保持亮屏取决于是否充电
mStayOn =
mBatteryManagerInternal.isPowered(mStayOnWhilePluggedInSetting);
} else {
mStayOn = false;
}
if (mStayOn != wasStayOn) {
//如果mStayOn值改变,mDirty置位
mDirty |= DIRTY_STAY_ON;
}
}
}

updateScreenBrightnessBoostLocked()

该方法在PhoneWindowManager中触发,和亮度增强有关。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
private void updateScreenBrightnessBoostLocked(int dirty) {
if ((dirty & DIRTY_SCREEN_BRIGHTNESS_BOOST) != 0) {
if (mScreenBrightnessBoostInProgress) {
final long now = SystemClock.uptimeMillis();
//删除屏幕亮度提升超时广播
mHandler.removeMessages(MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT);
if (mLastScreenBrightnessBoostTime > mLastSleepTime) {
final long boostTimeout = mLastScreenBrightnessBoostTime +
SCREEN_BRIGHTNESS_BOOST_TIMEOUT;
//如果超时还没有发生,则重新发送广播
if (boostTimeout > now) {
Message msg = mHandler.obtainMessage(MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, boostTimeout);
return;
}
}
//进行到这里有两个条件
//mLastScreenBrightnessBoostTime <= mLastSleepTime 说明还在睡眠中
//boostTimeout <= now 说明亮度提升超时发生
mScreenBrightnessBoostInProgress = false;
mNotifier.onScreenBrightnessBoostChanged();
userActivityNoUpdateLocked(now,
PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
}
}
}

updateWakeLockSummaryLocked()

该方法会对所有的WakeLock锁进行统计,过滤所有的wakelock锁状态,并更新mWakeLockSummary的值以汇总所有活动的唤醒锁的状态。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
private void updateWakeLockSummaryLocked(int dirty) {
if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_WAKEFULNESS)) != 0) {
//mWakeLockSummary是一个用来记录所有WakeLock锁状态的标识值,该值在请求Display状时会用到。
mWakeLockSummary = 0;
//numWakeLocks 保存了用户创建的所有 wakelock
final int numWakeLocks = mWakeLocks.size();
//在waklock集合中遍历wakelock
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.
//如果存在PARTIAL_WAKE_LOCK并且该wakelock可用,
//通过置位进行记录,下同
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.
/**
* 设备不处于DOZE状态时,通过置位操作忽略相关类型wakelock
* PowerManager.DOZE_WAKE_LOCK和WAKE_LOCK_DRAW锁仅仅
* 在Doze状态下有效
*/
if (mWakefulness != WAKEFULNESS_DOZING) {
mWakeLockSummary &= ~(WAKE_LOCK_DOZE | WAKE_LOCK_DRAW);
}
/**
* 如果处于Doze状态,忽略三类Wakelock.
* 如果处于睡眠状态,忽略四类wakelock.
*/
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;
}
}
//根据当前状态推断必要的wakelock
//处于awake或dream(不处于asleep/doze)
if ((mWakeLockSummary & (WAKE_LOCK_SCREEN_BRIGHT |
WAKE_LOCK_SCREEN_DIM)) != 0) {
//处于awake状态,WAKE_LOCK_STAY_AWAKE只用于awake状态时
if (mWakefulness == WAKEFULNESS_AWAKE) {
mWakeLockSummary |= WAKE_LOCK_CPU |
WAKE_LOCK_STAY_AWAKE;
//处于屏保状态(dream)
} else if (mWakefulness == WAKEFULNESS_DREAMING) {
mWakeLockSummary |= WAKE_LOCK_CPU;
}
}
if ((mWakeLockSummary & WAKE_LOCK_DRAW) != 0) {
mWakeLockSummary |= WAKE_LOCK_CPU;
}
}
}

updateUserActivitySummaryLocked()

该方法用来更新用户活动时间,当设备和用户有交互时,会根据当前时间和休眠时长、Dim时长、所处状态来计算下次休眠的时间,从而完成用户活动超时时的操作。关键代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
private void updateUserActivitySummaryLocked(long now, int dirty) {
// Update the status of the user activity timeout timer.
if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY
| DIRTY_WAKEFULNESS | DIRTY_SETTINGS)) != 0) {
mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT);
long nextTimeout = 0;
//如果处于休眠状态,则不会执行该方法
if (mWakefulness == WAKEFULNESS_AWAKE
|| mWakefulness == WAKEFULNESS_DREAMING
|| mWakefulness == WAKEFULNESS_DOZING) {
//设备完全进入休眠所需时间,该值为-1表示禁用此值,默认-1
final int sleepTimeout = getSleepTimeoutLocked();
//用户超时时间,既经过一段时间不活动进入休眠或屏保的时间,特殊情况外,该值为Settings中的休眠时长
final int screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout);
//Dim(暗淡)时长,即亮屏不操作,变暗多久休眠
final int screenDimDuration =
getScreenDimDurationLocked(screenOffTimeout);
//通过WindowManager的用户交互
final boolean userInactiveOverride =
mUserInactiveOverrideFromWindowManager;
mUserActivitySummary = 0;
//1.亮屏;2.亮屏后进行用户活动
if (mLastUserActivityTime >= mLastWakeTime) {
//下次睡眠时间=上次用户活动时间+休眠时间-Dim时间
nextTimeout = mLastUserActivityTime
+ screenOffTimeout - screenDimDuration;
//如果满足当前时间<下次屏幕超时时间,说明此时设备为亮屏状态,则将用户活动状态置为表示亮屏的USER_ACTIVITY_SCREEN_BRIGHT
if (now < nextTimeout) {
mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;
} else {
//如果当前时间>下次活动时间,此时应有两种情况:已经休眠和Dim
nextTimeout = mLastUserActivityTime + screenOffTimeout;
//如果当前时间<上次活动时间+屏幕超时时间,这个值约为3s,说明此时设备为Dim状态,则将用户活动状态置为表示Dim的USER_ACTIVITY_SCREEN_DIM
if (now < nextTimeout) {
mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;
}
}
.....
//发送定时Handler,到达时间后再次进行updatePowerStateLocked()
if (mUserActivitySummary != 0 && nextTimeout >= 0) {
Message msg =
mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, nextTimeout);
}
} else {
mUserActivitySummary = 0;
}
}
}

updateWakefulnessLocked()

在updatePowerStateLocked()方法中,设置了一个死循环,并且上述分析的两个方法都在死循环中执行。

1
2
3
4
5
6
7
8
9
10
for (;;) {
int dirtyPhase1 = mDirty;
dirtyPhase2 |= dirtyPhase1;
mDirty = 0;
updateWakeLockSummaryLocked(dirtyPhase1);//更新统计wakelock的标记值mWakeLockSummary
updateUserActivitySummaryLocked(now, dirtyPhase1);//更新统计userActivity的标记值mUserActivitySummary和休眠到达时间
if (!updateWakefulnessLocked(dirtyPhase1)) {//更新屏幕唤醒状态,状态改变返回true
break;
}
}

updateWakefulnessLocked()方法是退出循环的关键,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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) {
//当前屏幕保持唤醒&&设备将要退出唤醒状态(睡眠or屏保)
if (mWakefulness == WAKEFULNESS_AWAKE && isItBedTimeYetLocked()) {
//isItBedTimeYetLocked()方法判断当前设备是否将要进入睡眠状态。
Slog.d(TAG, "updateWakefulnessLocked: Bed time...");
final long time = SystemClock.uptimeMillis();
//是否在休眠时启用屏保
if (shouldNapAtBedTimeLocked()) {
//进入屏保,返回true
changed = napNoUpdateLocked(time, Process.SYSTEM_UID);
} else {
//进入睡眠,返回true
changed = goToSleepNoUpdateLocked(time,
PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0,
Process.SYSTEM_UID);
}
}
}
return changed;
}

该方法用于更新设备的wakefulness,同时,这个方法是亮屏到屏保/睡眠的决策点。wakefulness是用来表示当前设备状态的一个值,系统定义的wakefulness值共有四种,分别表示不同的状态:

1
2
3
4
5
6
7
8
//睡眠状态,此时灭屏
public static final int WAKEFULNESS_ASLEEP = 0;
//屏幕亮
public static final int WAKEFULNESS_AWAKE = 1;
//屏保
public static final int WAKEFULNESS_DREAMING = 2;
//处于DOZE模式时
public static final int WAKEFULNESS_DOZING = 3;

isItBedTimeYetLocked()方法,该方法判断当前设备是否将要进入睡眠状态,返回值为对isBeKeptAwakeLocke()方法返回值取反,由mStayOn(是否屏幕常亮)、wakelockSummary、userActivitySummary、mProximityPositive等决定,只要满足其中之一为ture,则说明无法进入睡眠,也就说,要满足进入睡眠,相关属性值都为false。isBeKeptAwakeLocke()如下:

1
2
3
4
5
6
7
8
9
10
private boolean isBeingKeptAwakeLocked() {
return mStayOn//屏幕是否保持常亮
|| mProximityPositive//接近传感器接近屏幕时为true
//处于awake状态
|| (mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) != 0
//屏幕处于亮屏或者dim状态
|| (mUserActivitySummary & (USER_ACTIVITY_SCREEN_BRIGHT
| USER_ACTIVITY_SCREEN_DIM)) != 0
|| mScreenBrightnessBoostInProgress;//处于亮度增强中
}

shoudNapAtBedTimeLocked()方法用来判断设备是否进入屏保模式,相关代码如下:

1
2
3
4
5
6
private boolean shouldNapAtBedTimeLocked() {
//屏保是否开启
return mDreamsActivateOnSleepSetting //屏保是否开启
|| (mDreamsActivateOnDockSetting //插入基座时是否开启屏保
&& mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED);
}

综上看来,之所以将updateWakeLockSummaryLocked()updateUserActivitySummaryLocked()updateWakefulnessLocked()三个方法放入for(;;)循环中,是因为它们共同决定了设备的状态,前两个方法是汇总状态,后一个方法是根据前两个方法汇总的值进行判断是否要改变当前的设备唤醒状态。

updateDisplayPowerStateLocked()

该方法用于更新设备显示状态,在这个方法中会计算出最终需要显示的亮度值和其他值,然后将这些值封装到DisplayPowerRequest对象中,向DisplayManagerService请求Display状态,完成屏幕亮度显示。

决定亮度的相关值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//WindowManager覆盖的亮度值,如播放视频时调节亮度,-1表示禁止使用(未发现使用到)
private int mScreenBrightnessOverrideFromWindowManager = -1;
//SystemUI中设置的临时亮度值,自动亮度时无效,该值之所以是临时的,是因为当调节亮度进度条时,会调用到updateDisplayPowerLocked(),这里给它赋值;当手指放开时,调用updateSettingLocked(),这里又将它置为-1
private int mTemporaryScreenBrightnessSettingOverride = -1;
//Settings.System.SCREEN_BRIGHTNESS中的值,即反映给用户的值
private int mScreenBrightnessSetting;
//限定值,config.xml中配置
private int mScreenBrightnessSettingMinimum;//0
private int mScreenBrightnessSettingMaximum;//255
private int mScreenBrightnessSettingDefault;//102
private int mScreenBrightnessForVrSettingDefault;//86
//自动调节亮度调整值,-1~1
private float mScreenAutoBrightnessAdjustmentSetting;
//Settings中的默认值,一般和config.xml中的默认值相同,也可能不同
Settings.System.SCREEN_BRIGHTNESS

最终显示的亮度值和所处的状态有关,如在自动亮度调节打开时、VR模式时、或者从一个视频播放窗口中调节亮度时,都对应有不同的值。
updateDisplayPowerStateLocked()方法中,用到了一个DisplayPowerRequest类的对象,这个类是DisplayManageInternal类中的一个内部类,专门用于PowerManagerServiceDisplayPowerController交互。PMS中会将当前亮度、屏幕状态等多个值封装在这个对象中,然后调用requestPowerState()请求DisplayPowerController,从而完成显示更新。

DisplayPowerRequest中定义的属性如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 可以理解为Display的‘策略‘,该值非常重要,决定了请求后屏幕的状态,有四个值:off,doze,dim,bright.
public int policy;
// 如果为true,则PSensor会覆盖屏幕状态,当物体靠近时将其临时关闭直到物体移开。
public boolean useProximitySensor;
// 屏幕亮度
public int screenBrightness;
// 自动调节亮度值,-1(dimmer)至1(brighter)之间
public float screenAutoBrightnessAdjustment;
// 如果screenBrightness和screenAutoBrightnessAdjustment 由用户设置,则为true
public boolean brightnessSetByUser;
// 是否使用了自动调节亮度
public boolean useAutoBrightness;
// 是否使用了低电量模式,该模式下亮度会减半
public boolean lowPowerMode;
// 在低电量模式下调整屏幕亮度的系数,0(screen off)至1(no change)之间
public float screenLowPowerBrightnessFactor;
// 是否启动了亮度增强
public boolean boostScreenBrightness;
// 如果为true,则会在屏幕亮起时阻止屏幕完全亮起,窗口管理器策略在准备键盘保护程// 时阻止屏幕,以防止用户看到中间更新。
public boolean blockScreenOn;
// 设备处于Doze状态下时覆盖的屏幕亮度和屏幕状态
public int dozeScreenBrightness;
public int dozeScreenState;

具体来说,updateDisplayPowerStateLocked()方法会封装应该DisplayPowerRequest对象请求交给DisplayManagerService处理,关键代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private boolean updateDisplayPowerStateLocked(int dirty) {
final boolean oldDisplayReady = mDisplayReady;
mDisplayPowerRequest.policy = getDesiredScreenPolicyLocked();

//------------亮度值计算 -----------
......
// 封装到DisplayPowerRequest中
mDisplayPowerRequest.screenBrightness = screenBrightness;
......
// 传给DisplayManagerService中处理
mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest,
mRequestWaitForNegativeProximity);
....
return mDisplayReady && !oldDisplayReady;
}

getDesiredScreenPolicyLocked()方法:

在请求 DisplayManagerService 时,会将所有的信息封装到 DisplayPowerRequest 对象中,其中需要注意 policy 值。policy 作为 DisplayPowerRequset 的属性,有四种值,分别为 off、doze、dim、bright、vr。在向 DisplayManagerService 请求时,会根据当前 PowerManagerService 中的唤醒状态和统计的 wakelock 来决定要请求的 Display 状态。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@VisibleForTesting
int getDesiredScreenPolicyLocked() {
//asleep时,policy值为0
if (mWakefulness == WAKEFULNESS_ASLEEP || sQuiescent) {
return DisplayPowerRequest.POLICY_OFF;//0
}
if (mWakefulness == WAKEFULNESS_DOZING) {
if ((mWakeLockSummary & WAKE_LOCK_DOZE) != 0) {
return DisplayPowerRequest.POLICY_DOZE;//1
}
if (mDozeAfterScreenOffConfig) {
return DisplayPowerRequest.POLICY_OFF;//2
}
}
if ((mWakeLockSummary & WAKE_LOCK_SCREEN_BRIGHT) != 0
|| (mUserActivitySummary & USER_ACTIVITY_SCREEN_BRIGHT) != 0
|| !mBootCompleted
|| mScreenBrightnessBoostInProgress) {
return DisplayPowerRequest.POLICY_BRIGHT;//3
}

return DisplayPowerRequest.POLICY_DIM;
}

requestPowerState()方法:

1
2
3
4
5
6
7
8
//frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java

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

DisplayPowerController.requestPowerState()方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java

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)) {
//如果该次请求和上次请求不同,说明已经改变,需要更新 Display
mPendingRequestLocked.copyFrom(request);
changed = true;
}
/**
* changed 为 true,说明有改变发生,这个改变交给 Handler 异步去处理,此时说
* 明显示没有准备好,mDisplayReadyLocked = false
* 直到改变处理成功,mDisplayReadyLocked 又被置为 true,
*/
if (changed) {
mDisplayReadyLocked = false;
}
//mPendingRequestChangedLocked:用于标识电源请求状态或者 PSensor 标签是否改变
if (changed && !mPendingRequestChangedLocked) {
mPendingRequestChangedLocked = true;
sendUpdatePowerStateLocked();
}

return mDisplayReadyLocked;
}
}

在该方法中,会判断请求时携带的DisplayPowerRequest对象是否和上一次请求的request对象相同,如果相同,则返回值mDisplayReadyLocked为true,如果不同则表示发生了改变,会异步请求新的Display状态,并返回false,表示Display状态正在更新中,直到更新完成mDisplayReadyLocked置为true。之后调用PMS.onStateChange()方法通知PMS Display状态更新完成。

sendUpdatePowerStateLocked()方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private void sendUpdatePowerStateLocked() {
if (!mPendingUpdatePowerStateLocked) {
mPendingUpdatePowerStateLocked = true;
//发送更新电源状态消息
Message msg = mHandler.obtainMessage(MSG_UPDATE_POWER_STATE);
mHandler.sendMessage(msg);
}
}

public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_UPDATE_POWER_STATE:
updatePowerState();
break;

updateDreamLocked()

该方法用来更新Dream(屏保)状态,比如是否继续屏保、Doze或者休眠。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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) {//mDisplayReady为上个方法请求Display时的返回值,表示Display是否就绪。
//通过Handler异步发送一个消息
scheduleSandmanLocked();
}
}
}

scheduleSandmanLocked()方法:

1
2
3
4
5
6
7
8
9
private void scheduleSandmanLocked() {
if (!mSandmanScheduled) {
//由于是异步处理,因此表示是否已经调用该方法且没有被handler处理,如果为true就不会进入该方法了
mSandmanScheduled = true;
Message msg = mHandler.obtainMessage(MSG_SANDMAN);
msg.setAsynchronous(true);
mHandler.sendMessage(msg);
}
}
1
2
3
case MSG_SANDMAN:
handleSandman();
break;

handleSandman()方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
private void handleSandman() { // runs on handler thread
//是否开始进入屏保
final boolean startDreaming;
final int wakefulness;
synchronized (mLock) {
//为false后下次updateDreamLocked()可处理
mSandmanScheduled = false;
wakefulness = mWakefulness;
//在进入asleep状态后该值为true,用于判断是否处于Dream状态
if (mSandmanSummoned && mDisplayReady) {
//当前状态能否进入Dream || 当前wakefulness状态为Doze
startDreaming = canDreamLocked() || canDozeLocked();
mSandmanSummoned = false;
} else {
startDreaming = false;
}
}
//表示是否正在屏保
final boolean isDreaming;
if (mDreamManager != null) {
//重启屏保
if (startDreaming) {
mDreamManager.stopDream(false /*immediate*/);
mDreamManager.startDream(wakefulness == WAKEFULNESS_DOZING);
}
isDreaming = mDreamManager.isDreaming();
} else {
isDreaming = false;
}
synchronized (mLock) {
//记录进入屏保时的电池电量
if (startDreaming && isDreaming) {
mBatteryLevelWhenDreamStarted = mBatteryLevel;
if (wakefulness == WAKEFULNESS_DOZING) {
Slog.i(TAG, "Dozing...");
} else {
Slog.i(TAG, "Dreaming...");
}
}
//如果mSandmanSummoned改变或者wakefulness状态改变,则return等待下次处理
if (mSandmanSummoned || mWakefulness != wakefulness) {
return; // wait for next cycle
}
//决定是否继续Dream
if (wakefulness == WAKEFULNESS_DREAMING) {
if (isDreaming && canDreamLocked()) {
//表示从开启屏保开始电池电量下降这个值就退出屏保,-1表示禁用该值
if (mDreamsBatteryLevelDrainCutoffConfig >= 0
&& mBatteryLevel < mBatteryLevelWhenDreamStarted
- mDreamsBatteryLevelDrainCutoffConfig
&& !isBeingKeptAwakeLocked()) {
} else {
return; // continue dreaming
}
}
//退出屏保,进入Doze状态
if (isItBedTimeYetLocked()) {
goToSleepNoUpdateLocked(SystemClock.uptimeMillis(),
PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0,
Process.SYSTEM_UID);
updatePowerStateLocked();
} else {
//唤醒设备,reason为android.server.power:DREAM
wakeUpNoUpdateLocked(SystemClock.uptimeMillis(),
"android.server.power:DREAM",
Process.SYSTEM_UID, mContext.getOpPackageName(),
Process.SYSTEM_UID);
updatePowerStateLocked();
}
//如果处于Doze状态,在power键灭屏时,首次会将wakefulness设置为该值
} else if (wakefulness == WAKEFULNESS_DOZING) {
if (isDreaming) {
return; // continue dozing
}
//进入asleep状态
reallyGoToSleepNoUpdateLocked(SystemClock.uptimeMillis(),
Process.SYSTEM_UID);
updatePowerStateLocked();
}
}
//如果正处在Dream,则只要触发updatePowerStateLocked(),立即退出Dream
if (isDreaming) {
mDreamManager.stopDream(false /*immediate*/);
}
}

finishWakefulnessChangeIfNeededLocked()

该方法主要做updateWakefulnessLocked()方法的结束工作,当屏幕状态改变后,才会执行该方法。

**屏幕状态:**唤醒(awake)、休眠(asleep)、屏保(dream)、打盹(doze)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private void finishWakefulnessChangeIfNeededLocked() {
if (mWakefulnessChanging && mDisplayReady) {
//如果当前处于Doze状态,不进行处理
if (mWakefulness == WAKEFULNESS_DOZING
&& (mWakeLockSummary & WAKE_LOCK_DOZE) == 0) {
return; // wait until dream has enabled dozing
}
if (mWakefulness == WAKEFULNESS_DOZING || mWakefulness ==
WAKEFULNESS_ASLEEP) {
logSleepTimeoutRecapturedLocked();
}
if (mWakefulness == WAKEFULNESS_AWAKE) {
logScreenOn();//打印整个亮屏流程的耗时
}
mWakefulnessChanging = false;
//通过Notifier进行wakefulness改变后的处理
mNotifier.onWakefulnessChangeFinished();
}
}

updateSuspendBlockerLocked()

该方法用以更新SuspendBlocker锁的状态。通过Suspend锁向Hal层写入节点,Kernal层读取节点,从而唤醒或休眠CPU。