PowerManager学习笔记-Power键灭屏流程: https://juejin.cn/post/7041907301514477599
PowerManager学习笔记-Power键亮屏流程: https://juejin.cn/post/7037287967911575566
PowerManager学习笔记-Power键超时灭屏流程:https://juejin.cn/post/7049993817025413156
Android4.2之PowerManagerService设置亮度学习:http://www.doczj.com/doc/ae4136815.html
Android 8.1 PowerManagerService分析(二) ——updatePowerStateLocked()方法:https://blog.csdn.net/FightFightFight/article/details/80341728
日常使用手机过程中,如果不去可以设置屏幕常亮,超过手机设置中的默认超时时长,无任何使用状态下进入灭屏。这个过程就叫超时灭屏。
isBeingKeptAwakeLocked 定义不可灭屏的条件:屏幕常亮、Psensor靠近、持高亮屏wakeLock、屏幕依然是亮屏或DIM状态、正在增强亮度
frameworks/base/services/core/jni/com_android_server_power_PowerManagerService.cpp
void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType, int32_t displayId) {
ATRACE_CALL();
android_server_PowerManagerService_userActivity(eventTime, eventType, displayId);
}
Android_S_Mssi/frameworks/base/services/core/jni/com_android_server_power_PowerManagerService.cpp
重点看:userActivityFromNative
jclass clazz;
FIND_CLASS(clazz, "com/android/server/power/PowerManagerService");
GET_METHOD_ID(gPowerManagerServiceClassInfo.userActivityFromNative, clazz,
"userActivityFromNative", "(JIII)V");
void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType,
int32_t displayId) {
....
env->CallVoidMethod(gPowerManagerServiceObj,
gPowerManagerServiceClassInfo.userActivityFromNative,
nanoseconds_to_milliseconds(eventTime), eventType, displayId, 0);
checkAndClearExceptionFromCallback(env, "userActivityFromNative");
....
}
frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
// Called from native code.
private void userActivityFromNative(long eventTime, int event, int displayId, int flags) {
userActivityInternal(displayId, eventTime, event, flags, Process.SYSTEM_UID);
}
private void userActivityInternal(int displayId, long eventTime, int event, int flags,
int uid) {
....
// 更新用户活动时间
if (userActivityNoUpdateLocked(groupId, eventTime, event, flags, uid)) {
// 更新power状态
updatePowerStateLocked();
}
....
}
frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
根据Flag:PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS,使用后,会再次延长亮屏或者dim(半亮状态)时间
private boolean userActivityNoUpdateLocked(int groupId, long eventTime, int event, int flags,
int uid) {
...
if ((flags & PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS) != 0) {
if (eventTime
> mDisplayGroupPowerStateMapper.getLastUserActivityTimeNoChangeLightsLocked(
groupId)
&& eventTime > mDisplayGroupPowerStateMapper.getLastUserActivityTimeLocked(
groupId)) {
mDisplayGroupPowerStateMapper.setLastUserActivityTimeNoChangeLightsLocked(
groupId, eventTime);
mDirty |= DIRTY_USER_ACTIVITY;
if (event == PowerManager.USER_ACTIVITY_EVENT_BUTTON) {
mDirty |= DIRTY_QUIESCENT;
}
return true;
}
...
}
我们不去触发任何的UserActivity,放弃wake_lock,自然,过了超时时间,就可以跳出死循环,必然进入sleep
private void updatePowerStateLocked() {
for (;;) {
...
// 计算当前系统中的wakeLock数量
updateWakeLockSummaryLocked(dirtyPhase1);
// 计算用户活动时间,并计算灭屏时间
updateUserActivitySummaryLocked(now, dirtyPhase1);
updateAttentiveStateLocked(now, dirtyPhase1);
if (!updateWakefulnessLocked(dirtyPhase1)) {
break;
}
...
}
}
用来更新用户活动时间,当设备和用户有交互时,都会根据当前时间和休眠时长、Dim时长、所处状态而计算下次休眠的时间,从而完成用户活动超时时的操作。如由亮屏进入Dim的时长、Dim到灭屏的时长、亮屏到屏保的时长,就是在这里计算的。
重点看:影响 MSG_USER_ACTIVITY_TIMEOUT 发出的2个逻辑:hasUserActivitySummary和nextTimeout
正常灭屏过程,groupUserActivitySummary会经历USER_ACTIVITY_SCREEN_BRIGHT(亮屏)->USER_ACTIVITY_SCREEN_DIM(DIM)-> USER_ACTIVITY_SCREEN_DREAM(灭屏)变化,最终进入ASLEEP后,groupUserActivitySummary就会赋值为0。
即需要进行完整的灭屏流程且为ASLEEP状态
-下次超时时间 nextTimeout >= 0 的条件,:
取决于nextProfileTimeout > 0或 groupNextTimeout != -1
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) {
// 不断发出timeout阻止灭屏
Message msg =
mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, nextTimeout);
}
} else {
mUserActivitySummary = 0;
}
}
}
private void scheduleUserInactivityTimeout(long timeMs) {
final Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, timeMs);
}
private final class PowerManagerHandlerCallback implements Handler.Callback {
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case MSG_USER_ACTIVITY_TIMEOUT:
handleUserActivityTimeout();
break;
...
}
不断发出timeout阻止灭屏
private void handleUserActivityTimeout() { // runs on handler thread
synchronized (mLock) {
if (DEBUG_SPEW) {
Slog.d(TAG, "handleUserActivityTimeout");
}
mDirty |= DIRTY_USER_ACTIVITY;
updatePowerStateLocked();
}
}
在updatePowerStateLocked中执行完 updateUserActivitySummaryLocked,接下来就是判断是否需要跳出死循环的 updateWakefulnessLocked
private void updatePowerStateLocked() {
for (;;) {
...
//更新统计wakelock的标记值mWakeLockSummary
updateWakeLockSummaryLocked(dirtyPhase1);
//更新统计userActivity的标记值mUserActivitySummary和休眠到达时间
updateUserActivitySummaryLocked(now, dirtyPhase1);
updateAttentiveStateLocked(now, dirtyPhase1);
if (!updateWakefulnessLocked(dirtyPhase1)) {
break;
}
...
}
}
private boolean updateWakefulnessLocked(int dirty) {
...
for (int id : mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked()) {
if (mDisplayGroupPowerStateMapper.getWakefulnessLocked(id) == WAKEFULNESS_AWAKE
&& isItBedTimeYetLocked(id)) {
...
// 长时间亮屏灭屏请求,不能灭屏
if (isAttentiveTimeoutExpired(id, time)) {
changed = sleepDisplayGroupNoUpdateLocked(id, time,
PowerManager.GO_TO_SLEEP_REASON_TIMEOUT,
PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE, Process.SYSTEM_UID);
} else if (shouldNapAtBedTimeLocked()) {
//是否支持屏保
changed = dreamDisplayGroupNoUpdateLocked(id, time, Process.SYSTEM_UID);
} else {
// 正常灭屏,超时自动灭屏
changed = sleepDisplayGroupNoUpdateLocked(id, time,
PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, Process.SYSTEM_UID);
}
...
}
// 判断当前设备是否将要进入睡眠状态
private boolean isItBedTimeYetLocked(int groupId) {
if (!mBootCompleted) {
return false;
}
long now = mClock.uptimeMillis();
if (isAttentiveTimeoutExpired(groupId, now)) {
return !isBeingKeptFromInattentiveSleepLocked(groupId);
} else {
return !isBeingKeptAwakeLocked(groupId);
}
}
isBeingKeptAwakeLocked定义不可灭屏的条件:屏幕常亮、Psensor靠近、持高亮屏wakeLock、屏幕依然是亮屏或DIM状态、正在增强亮度
// 条件有任意条件是true,那么不可以进行灭屏
private boolean isBeingKeptAwakeLocked(int groupId) {
return mStayOn // 判断是否屏幕常亮
|| mProximityPositive// P sensor是否有靠近数据
|| (mDisplayGroupPowerStateMapper.getWakeLockSummaryLocked(groupId)
& WAKE_LOCK_STAY_AWAKE) != 0// 屏幕是否持有亮屏WAKE LOCK
|| (mDisplayGroupPowerStateMapper.getUserActivitySummaryLocked(groupId) & (
USER_ACTIVITY_SCREEN_BRIGHT | USER_ACTIVITY_SCREEN_DIM)) != 0// 屏幕是否依然是亮屏或者DIM状态
|| mScreenBrightnessBoostInProgress; //是否正在增强亮度
}