PowerManagerService灭屏超时流程

文章参考
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
摘要
日常使用手机过程中,如果不去可以设置屏幕常亮,超过手机设置中的默认超时时长,无任何使用状态下进入灭屏。这个过程就叫超时灭屏。
PowerManagerService灭屏超时流程_第1张图片
PowerManagerService灭屏超时流程_第2张图片
isBeingKeptAwakeLocked 定义不可灭屏的条件:屏幕常亮、Psensor靠近、持高亮屏wakeLock、屏幕依然是亮屏或DIM状态、正在增强亮度

  1. 超时灭屏UML图
  2. PowerManagerService灭屏超时流程_第3张图片
  3. PowerManagerService灭屏超时流程_第4张图片

1.1 com_android_server_input_InputManagerService->com_android_server_power_PowerManagerService:pokeUserActivity
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);
}
1
2
3
4
1.2 com_android_server_power_PowerManagerService->PowerManagerService:userActivityFromNative
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”);

}

1.3 PowerManagerService->PowerManagerService:userActivityInternal
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();
    }
    ....
}

1.4 PowerManagerService->PowerManagerService:userActivityNoUpdateLocked
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;
        }
        ...
}

1.5 PowerManagerService->PowerManagerService:updatePowerStateLocked
我们不去触发任何的UserActivity,放弃wake_lock,自然,过了超时时间,就可以跳出死循环,必然进入sleep
PowerManagerService灭屏超时流程_第5张图片
private void updatePowerStateLocked() {
for (; {

// 计算当前系统中的wakeLock数量
updateWakeLockSummaryLocked(dirtyPhase1);
// 计算用户活动时间,并计算灭屏时间
updateUserActivitySummaryLocked(now, dirtyPhase1);
updateAttentiveStateLocked(now, dirtyPhase1);
if (!updateWakefulnessLocked(dirtyPhase1)) {
break;
}

}
}

1.6 PowerManagerService->PowerManagerService:updateUserActivitySummaryLocked
用来更新用户活动时间,当设备和用户有交互时,都会根据当前时间和休眠时长、Dim时长、所处状态而计算下次休眠的时间,从而完成用户活动超时时的操作。如由亮屏进入Dim的时长、Dim到灭屏的时长、亮屏到屏保的时长,就是在这里计算的。

重点看:影响 MSG_USER_ACTIVITY_TIMEOUT 发出的2个逻辑:hasUserActivitySummary和nextTimeout

hasUserActivitySummary为true的条件:需要进行完整的灭屏流程且为ASLEEP状态
取决groupUserActivitySummary是否为0
正常灭屏过程,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;
    ...
}

1.7 PowerManagerService->PowerManagerService:handleUserActivityTimeout
不断发出timeout阻止灭屏

private void handleUserActivityTimeout() { // runs on handler thread
    synchronized (mLock) {
        if (DEBUG_SPEW) {
            Slog.d(TAG, "handleUserActivityTimeout");
        }

        mDirty |= DIRTY_USER_ACTIVITY;
        updatePowerStateLocked();
    }
}

1.8 PowerManagerService->PowerManagerService:updatePowerStateLocked
在updatePowerStateLocked中执行完 updateUserActivitySummaryLocked,接下来就是判断是否需要跳出死循环的 updateWakefulnessLocked

private void updatePowerStateLocked() {
    for (;;) {
        ...
        //更新统计wakelock的标记值mWakeLockSummary
        updateWakeLockSummaryLocked(dirtyPhase1);
        //更新统计userActivity的标记值mUserActivitySummary和休眠到达时间
        updateUserActivitySummaryLocked(now, dirtyPhase1);
        updateAttentiveStateLocked(now, dirtyPhase1);
        if (!updateWakefulnessLocked(dirtyPhase1)) {
            break;
        }
        ...
    }
}

1.9 PowerManagerService->PowerManagerService:updateWakefulnessLocked
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);
}

}

1.10 PowerManagerService->PowerManagerService:isItBedTimeYetLocked
// 判断当前设备是否将要进入睡眠状态
private boolean isItBedTimeYetLocked(int groupId) {
if (!mBootCompleted) {
return false;
}

    long now = mClock.uptimeMillis();
    if (isAttentiveTimeoutExpired(groupId, now)) {
        return !isBeingKeptFromInattentiveSleepLocked(groupId);
    } else {
        return !isBeingKeptAwakeLocked(groupId);
    }
}

1.11 PowerManagerService->PowerManagerService:isBeingKeptAwakeLocked
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; //是否正在增强亮度
}

你可能感兴趣的:(android电源,android)