logo
Home 战力冲刺 Android PowerManagerService

Android PowerManagerService

  • 2025-12-04 05:50:19

本文转载自:Android R PowerManagerService模块(4) 灭屏流程

本文基于Android 11源码分析

前言

在《Android PowerManagerService--03:亮屏流程》中分析了PMS部分的亮屏流程。PMS模块中也提供了灭屏接口goTosleep(),方法给其他组件或应用来关闭屏幕,这里将对PMS部分涉及到的灭屏流程进行分析。

1.非自动灭屏流程

当系统其他组件发起灭屏时,将调用PowerManager#goTosleep()方法:

// frameworks/base/core/java/android/os/PowerManager.java

/**

* time: 开始灭屏时间

* reason: 灭屏原因

* flags: 灭屏可选标记值

*/

public void goToSleep(long time, int reason, int flags) {

try {

mService.goToSleep(time, reason, flags);

} catch (RemoteException e) {

throw e.rethrowFromSystemServer();

}

}

PowerManager中直接调用到PMS中,并在进行权限检查后,调用goToSleepInternal()进入PMS模块内部:

// frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java

private void goToSleepInternal(long eventTime, int reason, int flags, int uid) {

synchronized (mLock) {

// 灭屏成功返回true

if (goToSleepNoUpdateLocked(eventTime, reason, flags, uid)) {

updatePowerStateLocked();

}

}

}

首先将会调用goToSleepNoUpdateLocked()方法,并在该方法返回true后,调用updatePowerStateLocked()开始更新全局状态,完成整个灭屏流程。

1.1 goToSleepNoUpdateLocked()更新验证和灭屏状态更新

// frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java

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

......

try {

// 表示需要召唤"睡眠精灵",即请求进入Dreamland模式

mSandmanSummoned = true;

// 表示处于Doze过程中

mDozeStartInProgress = true;

// 设置唤醒状态为Dozing

setWakefulnessLocked(WAKEFULNESS_DOZING, reason, eventTime);

// 灭屏后屏幕相关WakeLock锁将失去意义,所以统计下清除锁的个数

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;

break;

}

}

// 如果带有GO_TO_SLEEP_FLAG_NO_DOZE标记,则不会经过Doze直接进入Asleep状态

if ((flags & PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE) != 0) {

reallyGoToSleepNoUpdateLocked(eventTime, uid);

}

}

return true;

}

首先,更新灭屏相关属性值,然后通过setWakefulnessLocked()方法,将唤醒状态mWakefulnessRaw值设置为Dozing;最后如果goToSleep()中还带有PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE标记,则将跳过Dozing状态,直接进入Asleep状态。

因此,如果goToSleep()不带PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE时,会先将唤醒状态设置为Dozing状态,再根据条件决定是否进入Asleep。

setWakefulnessLocked()方法在第三篇中也分析过了,会更新mWakefulnessRaw值,然后调用Notifier#onWakefulnessChangeStarted()做系统唤醒状态改变后的交互状态更新,然后执行handleEarlyInteractiveChange()方法。

1.2 Notifier#handleEarlyInteractiveChange()

看下该方法中灭屏流程相关逻辑:

// frameworks/base/services/core/java/com/android/server/power/Notifier.java

private void handleEarlyInteractiveChange() {

synchronized (mLock) {

if (mInteractive) {

......

} else {

// Going to sleep...

// 通知WMS开始灭屏

final int why = translateOffReason(mInteractiveChangeReason);

mHandler.post(new Runnable() {

@Override

public void run() {

// 调用PhoneWindowManager

mPolicy.startedGoingToSleep(why);

}

});

}

}

}

这里会通知WMS模块开始灭屏,WMS中会进一步通知给Keyguard等进行相应操作。

1.3 updatePowerStateLocked()

当上述方法执行完毕并返回后,开始执行updatePowerStateLocked()方法,在这里我们只看其中灭屏流程相关,有如下部分:

// 向DMS中发起灭屏请求,将亮度设置为0, Display状态设置为DOZE/OFF

boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);

//更新Dreamland状态

updateDreamLocked(dirtyPhase2, displayBecameReady);

// 收尾工作

finishWakefulnessChangeIfNeededLocked();

//释放锁

updateSuspendBlockerLocked();

下面逐个来看。

1.4 updateDisplayPowerStateLocked()请求DMS

该方法向DMS模块发起请求,DisplayPowerController中收到请求后,会将屏幕亮度设置为0,Display状态设置为Doze或者OFF。该方法详细分析见《Android PowerManagerService--01:启动流程和核心方法》。关于DMS中收到请求并设置亮度和Display状态的逻辑。

1.5 updateDreamLocked()更新Dream状态

该方法用来决定灭屏后是否会进入Dream状态或Doze状态,如屏保、AOD、FOD等功能就是在此状态下运行。当完成DMS请求且DMS返回请求结果后,才会执行该方法内容,并最终在handleSandman()方法中进行处理:

// frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java

private void handleSandman() { // runs on handler thread

.....

synchronized (mLock) {

mSandmanScheduled = false;

wakefulness = getWakefulnessLocked();

// 召唤睡眠精灵且Display状态准备完毕

if (mSandmanSummoned && mDisplayReady) {

// 确定是需要进入Dreamland

startDreaming = canDreamLocked() || canDozeLocked();

mSandmanSummoned = false; // 重置

} else {

startDreaming = false;

}

}

final boolean isDreaming;

if (mDreamManager != null) {

// 进入Dreamland状态

if (startDreaming) {

mDreamManager.stopDream(false /*immediate*/);

mDreamManager.startDream(wakefulness == WAKEFULNESS_DOZING);

}

// 确认是否完成Dreamland

isDreaming = mDreamManager.isDreaming();

} else {

isDreaming = false;

}

// 重置,表示完成Dozing过程

mDozeStartInProgress = false;

synchronized (mLock) {

......

if (wakefulness == WAKEFULNESS_DREAMING) {

......

} else if (wakefulness == WAKEFULNESS_DOZING) {

// 如果在进行Dreaming,则直接返回

if (isDreaming) {

return; // continue dozing

}

// 否则真正执行灭屏流程

reallyGoToSleepNoUpdateLocked(now, Process.SYSTEM_UID);

updatePowerStateLocked();

}

}

// Stop dream.

if (isDreaming) {

mDreamManager.stopDream(false /*immediate*/);

}

}

当mWakefulness变为WAKEFULNESS_DOZING后,执行到这里时,如果没有能够进入Dreamland,那么将通过reallyGoToSleepNoUpdateLocked()方法,开始进行真正的”休眠“。

1.6 reallyGoToSleepNoUpdateLocked()

该方法中,将mWakefulnessRaw值设置为WAKEFULNESS_ASLEEP,表示进入休眠状态:

// frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java

private boolean reallyGoToSleepNoUpdateLocked(long eventTime, int uid) {

......

try {

// 设置唤醒状态为ASLEEP

setWakefulnessLocked(WAKEFULNESS_ASLEEP, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT,

eventTime);

}

return true;

}

因此在灭屏过程中,系统唤醒状态会先设置为Dozing,并通过DreamManager去启动进入Dreamland状态。没有进入Dreamland时,才会将唤醒状态设置为Asleep。如果goToSleep()带有PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE标记,则直接进Asleep。

1.7 Notifier#handleLateInteractiveChange()

更新完Dreamland相关状态后,执行finishWakefulnessChangeIfNeededLocked()方法来做唤醒状态变化完成后的任务,并执行Notifier#handleLateInteractiveChange()方法,进行交互状态变化完成后的任务,这里看下灭屏流程部分:

// frameworks/base/services/core/java/com/android/server/power/Notifier.java

private void handleLateInteractiveChange() {

synchronized (mLock) {

final int interactiveChangeLatency =

(int) (SystemClock.uptimeMillis() - mInteractiveChangeStartTime);

if (mInteractive) {

// Finished waking up...

.......

} else {

......

mHandler.post(new Runnable() {

@Override

public void run() {

mPolicy.finishedGoingToSleep(why);

}

});

// 表示即将要发送广播状态为ASLEEP

mPendingInteractiveState = INTERACTIVE_STATE_ASLEEP;

// 表示即将要发送灭屏广播

mPendingGoToSleepBroadcast = true;

// 发送广播

updatePendingBroadcastLocked();

}

}

}

首先,通过mPolicy.finishedGoingToSleep()通知WMS模块已经完成灭屏,然后发送灭屏广播。

1.8 updatePendingBroadcastLocked()发送灭屏广播

updatePendingBroadcastLocked()方法在上一篇文章中已经分析过,当满足灭屏广播的发送条件时,将会进行灭屏广播的发送:

// frameworks/base/services/core/java/com/android/server/power/Notifier.java

private void sendGoToSleepBroadcast() {

if (mActivityManagerInternal.isSystemReady()) {

mContext.sendOrderedBroadcastAsUser(mScreenOffIntent, UserHandle.ALL, null,

mGoToSleepBroadcastDone, mHandler, 0, null, null);

} else {

EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 3, 1);

sendNextBroadcast();

}

}

1.9 updateSuspendBlockerLocked()

最后执行updateSuspendBlockerLocked()方法,灭屏后会释放掉mDisplaySuspendBlocker锁,如果此时没有PARTICAL_WAKE_LOCK、DOZE_WAKE_LOCK、DRAW_WAKE_LOCK这三类锁,mWakeLockSuspendBlocker也将会释放掉,CPU将会在适当时机进行休眠。

释放流程见《Android PowerManagerService--02:WakeLock机制》。

以上就是PMS部分非自动灭屏场景的整个流程,其时序图如下:

PMS05.png

2.自动灭屏流程

自动灭屏的影响因素主要有两个:

自动休眠时间:用户在Settings中设置的值;

用户活动时间:用户最后和设备进行交互的时间点。当用户在某时刻和设备有交互时,会记录该时间点,并以该时间为起始时间,到达"起始时间+自动休眠时间"这个时间点后,开始执行灭屏流程。

在前面几篇文章中多次提到了userActivityNoUpdateLocked()方法,但没有分析,这里正是分析它的最佳时机。因为就是这个方法,会在每一次有用户活动时更新最近一次的交互时间。

2.1 userActivityNoUpdateLocked()更新最近一次交互时间

当用户触摸屏幕、按键时,Input模块中在处理这些Key事件后,会通知PMS来更新用户活动时间:

// frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType) {

ATRACE_CALL();

android_server_PowerManagerService_userActivity(eventTime, eventType);

}

------------------------------------------

// frameworks/base/services/core/jni/com_android_server_power_PowerManagerService.cpp

void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType) {

if (gPowerManagerServiceObj) {

// ......

env->CallVoidMethod(gPowerManagerServiceObj,

gPowerManagerServiceClassInfo.userActivityFromNative,

nanoseconds_to_milliseconds(eventTime), eventType, 0);

}

}

input模块中通过JNI调用,进入PMS中:

// frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java

private void userActivityFromNative(long eventTime, int event, int flags) {

userActivityInternal(eventTime, event, flags, Process.SYSTEM_UID);

}

-------------------------------------------

private void userActivityInternal(long eventTime, int event, int flags, int uid) {

synchronized (mLock) {

// 更新用户活动时间

if (userActivityNoUpdateLocked(eventTime, event, flags, uid)) {

// 更新PMS全局状态

updatePowerStateLocked();

}

}

}

Native层代码调用userActivityFromNative()方法进入PMS中,在这个方法中,首先通过userActivityNoUpdateLocked()方法更新用户活动时间,然后updatePowerStateLocked()方法进行全局状态的更新。

userActivityNoUpdateLocked()方法如下:

// frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java

private boolean userActivityNoUpdateLocked(long eventTime, int event, int flags, int uid) {

// ......

// 通知Notifier更新用户活动状态

mNotifier.onUserActivity(event, uid);

mAttentionDetector.onUserActivity(eventTime, event);

// 重置,表示是否WMS覆盖了最长不交互时间阈值

if (mUserInactiveOverrideFromWindowManager) {

mUserInactiveOverrideFromWindowManager = false;

mOverriddenTimeout = -1;

}

// 已灭屏,或调用该方法带有USER_ACTIVITY_FLAG_INDIRECT,不会更新用户活动时间

if (mWakefulness == WAKEFULNESS_ASLEEP

|| mWakefulness == WAKEFULNESS_DOZING

|| (flags & PowerManager.USER_ACTIVITY_FLAG_INDIRECT) != 0) {

return false;

}

// 根据userid更新该user在PowerProfileState中记录的用户活动时间

maybeUpdateForegroundProfileLastActivityLocked(eventTime);

// 带有USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS标记时,会延长亮屏一会儿

if ((flags & PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS) != 0) {

if (eventTime > mLastUserActivityTimeNoChangeLights

&& eventTime > mLastUserActivityTime) {

// 更新最后一次活动时间给mLastUserActivityTimeNoChangeLights

mLastUserActivityTimeNoChangeLights = eventTime;

mDirty |= DIRTY_USER_ACTIVITY;

// ......

return true;

}

} else {

if (eventTime > mLastUserActivityTime) {

// 更新最后一次活动时间给mLastUserActivityTime

mLastUserActivityTime = eventTime;

mDirty |= DIRTY_USER_ACTIVITY;

// ......

return true;

}

}

} finally { }

return false;

}

以上方法中,如果调用时带有PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS标记,则将交互时间赋值给mLastUserActivityTimeNoChangeLights变量,否则将交互时间赋给mLastUserActivityTime变量。这个flag标志用于延长亮屏或Dim的时长一小会儿。在第二篇文章中说过,当在释放WakeLock锁时带有ON_AFTER_RELEASE标记,会延长超时灭屏时间,原理就是通过该Flag实现。

当执行完成后。mLastUserActivityTime或者mLastUserActivityTimeNoChangeLights的值得到了更新。接下来又会进入updatePowerStateLocked()方法,来更新PMS全局状态。

2.2 updatePowerStateLocked()更新PMS全局状态

在这个方法中,和自动灭屏相关的逻辑如下:

// frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java

private void updatePowerStateLocked() {

// ......

try {

for (;;) {

int dirtyPhase1 = mDirty;

dirtyPhase2 |= dirtyPhase1;

mDirty = 0;

updateWakeLockSummaryLocked(dirtyPhase1);

updateUserActivitySummaryLocked(now, dirtyPhase1);

if (!updateWakefulnessLocked(dirtyPhase1)) {

break;

}

}

// ......

} finally { }

}

updateWakeLockSummaryLocked()方法会将当前系统所有的WakeLock统计到mWakeLock变量上。 updateUserActivitySummaryLocked()方法会更新用户活动状态,并确认多久开始自动灭屏。

2.3 updateUserActivitySummaryLocked()

该方法用来更新用户活动状态:

// frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java

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;

// mWakefulnessRaw为Asleep时,不执行该流程

if (getWakefulnessLocked() == WAKEFULNESS_AWAKE

|| getWakefulnessLocked() == WAKEFULNESS_DREAMING

|| getWakefulnessLocked() == WAKEFULNESS_DOZING) {

// 获取细微模式超时时间

final long attentiveTimeout = getAttentiveTimeoutLocked();

// 获取彻底进入休眠超时时间

final long sleepTimeout = getSleepTimeoutLocked(attentiveTimeout);

// 获取自动灭屏超时时间

final long screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout,

attentiveTimeout);

// 获取进入Dim所需时间

final long screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);

// 是否WindowManager中覆盖了超时时间

final boolean userInactiveOverride = mUserInactiveOverrideFromWindowManager;

// DevicePolicy是否对于单用户设置了超时时间

final long nextProfileTimeout = getNextProfileTimeoutLocked(now);

// 重置统计值

mUserActivitySummary = 0;

// 最近一次用户活动时间>=最近一次唤醒时间

if (mLastUserActivityTime >= mLastWakeTime) {

// 如果最近一次用户活动时间 + 自动休眠设置 - Dim时间大于当前时间,则此时为亮屏状态,mUserActivitySummary状态设置为USER_ACTIVITY_SCREEN_BRIGHT

nextTimeout = mLastUserActivityTime

+ screenOffTimeout - screenDimDuration;

if (now < nextTimeout) {

mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;

} else {

// 如果最近一次用户活动时间 + 自动休眠时间 > 当前时间 > 最近一次用户活动时间+自动休眠设置-Dim时间,此时为Dim状态

// mUserActivitySummary状态设置为USER_ACTIVITY_SCREEN_DIM

nextTimeout = mLastUserActivityTime + screenOffTimeout;

if (now < nextTimeout) {

mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;

}

}

}

// 如果进该if块,说明不满足mLastUserActivityTime >= mLastWakeTime,那么就需要判断mLastUserActivityTimeNoChangeLights,

// mLastUserActivityTimeNoChangeLights是带有USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS标记的最近一次用户活动时间

if (mUserActivitySummary == 0

&& mLastUserActivityTimeNoChangeLights >= mLastWakeTime) {

// 如果当前时间 < 最近一次用户活动时间 + 自动休眠时间,说明要么亮屏,要么Dim,具体根据当前已处状态确认,从而做到延长亮屏或Dim的时长

nextTimeout = mLastUserActivityTimeNoChangeLights + screenOffTimeout;

if (now < nextTimeout) {

if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_BRIGHT

|| mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_VR) {

mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;

} else if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {

mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;

}

}

}

// 如果进该if块,说明当前时间 > 最近一次用户活动时间 + 自动休眠时间了,肯定将开始自动灭屏,mUserActivitySummary设置为USER_ACTIVITY_SCREEN_DREAM

if (mUserActivitySummary == 0) {

if (sleepTimeout >= 0) {

......

} else {

mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;

nextTimeout = -1;

}

}

......

// 发送定时消息

if (mUserActivitySummary != 0 && nextTimeout >= 0) {

scheduleUserInactivityTimeout(nextTimeout);

}

} else {

// 当唤醒状态为Asleep时,设置为0

mUserActivitySummary = 0;

}

}

}

此方法中逻辑比较多且碎,其中细节在代码中都进行了注释。总而言之,进入该方法后,会根据最近一次的用户活动时间和系统设置的自动休眠时间,一步步确定每个用户活动状态变化的时间点,然后通过scheduleUserInactivityTimeout()方法设置一个Msg,并在到达时间点后会再次更新。

最终,用户活动状态经过USER_ACTIVITY_SCREEN_BRIGHT -> USER_ACTIVITY_SCREEN_DIM -> USER_ACTIVITY_SCREEN_DREAM变化,对应亮屏 -> Dim -> 灭屏。如果系统状态进入Alseep,则mUserActivitySummary最终会变为0。

经过updateUserActivitySummaryLocked()方法后,得到了mUserActivitySummary。

2.4 updateWakefulnessLocked()

现在看下循环体中的updateWakefulnessLocked()方法,这个方法作为for循环的终止条件,下面看下其逻辑:

// frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java

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 | DIRTY_ATTENTIVE | DIRTY_SETTINGS

| DIRTY_SCREEN_BRIGHTNESS_BOOST)) != 0) {

// 当系统唤醒状态为Awake,且到达"睡觉"时间

if (getWakefulnessLocked() == WAKEFULNESS_AWAKE && isItBedTimeYetLocked()) {

final long time = mClock.uptimeMillis();

// 判断是否超过细微模式超时时间阈值

if (isAttentiveTimeoutExpired(time)) {

changed = goToSleepNoUpdateLocked(time, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT,

PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE, Process.SYSTEM_UID);

// 进入屏保,将系统状态设置为Dreaming

} else if (shouldNapAtBedTimeLocked()) {

changed = napNoUpdateLocked(time, Process.SYSTEM_UID);

} else {

// 否则灭屏

changed = goToSleepNoUpdateLocked(time,

PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, Process.SYSTEM_UID);

}

}

}

return changed;

}

首先根据isItBedTimeYetLocked()和mWakefulnessRaw来决定是否执行该方法;然后根据shouldNapAtBedTimeLocked()决定是要进入屏保还是直接灭屏。

不管进入哪个状态,都说明此时系统屏幕状态发生了改变,所以该方法会返回true,因此将不会跳出for循环,再次进行一次循环。因此,只有超时灭屏时for循环才会执行两次,其他情况下都会只执行一次for循环就退出。

isItBedTimeYetLocked()方法是判断是否要自动休眠的关键:

// frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java

private boolean isItBedTimeYetLocked() {

if (!mBootCompleted) {

return false;

}

long now = mClock.uptimeMillis();

// 到达细微模式时

if (isAttentiveTimeoutExpired(now)) {

return !isBeingKeptFromInattentiveSleepLocked();

} else {

return !isBeingKeptAwakeLocked();

}

}

该方法直接返回isBeingKeptAwakeLocked()方法:

// frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java

private boolean isBeingKeptAwakeLocked() {

return mStayOn // 是否开启了不锁定屏幕开关

|| mProximityPositive // 是否有PSensor靠近

|| (mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) != 0 // 是否持有屏幕相关WakeLock锁

|| (mUserActivitySummary & (USER_ACTIVITY_SCREEN_BRIGHT

| USER_ACTIVITY_SCREEN_DIM)) != 0 // 用户活动状态是否为Bright或Dim

|| mScreenBrightnessBoostInProgress; // 是否在进行亮度增强

}

如果isBeingKeptAwakeLocked()方法有任意一个条件为true,那么就不能进入休眠或者屏保状态,因此只有全部为false时,才会进行自动灭屏。其中条件包括mWakeLockSummary和mUserActivitySummary,所以前面流程中对这两个变量进行统计,就是用在这里起关键作用。

isItBedTimeYetLocked()返回后,将进入屏保或者灭屏,屏保这个功能已经几乎不使用了,就不分析它了。接下来将调用goToSleepNoUpdateLocked()方法,于是开始走灭屏流程,之后的逻辑和非自动灭屏流程一致。

至此,自动灭屏流程分析完毕。从以上流程可以看到,mWakeLockSummary和mUserActivitySummary对自动灭屏来说相当重要,平时如果存在到达自动灭屏时间后不灭屏问题,可以确认下这两个值的状态是否正常。

自动灭屏时序图如下:

PMS06.png

3.PSensor灭屏

日常使用场景中,还有一个常见灭屏,就是距离传感器灭屏。打电话、听语音时都会由Psensor灭屏,避免误触。

然而,虽然都是灭屏,但内部实现却是天差地别,实际上,PSensor的灭屏,只会改变Display模块中的屏幕亮度和Display状态,PM唤醒状态依然保持Awake(即mWakefulnessRaw = AWAKE,mUserActivitySummary = BRIGHT,....... ),这部分内容,在对DisplayManager模块分析时进行。

Previous Post
一、缘起:我认为苹果手机更贵啊…
Copyright © 2088 战力飙升活动特区 - 专属特权限时解锁 All Rights Reserved.
友情链接