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图

com_android_server_input_InputManagerService com_android_server_power_PowerManagerService PowerManagerService pokeUserActivity userActivityFromNative userActivityInternal userActivityNoUpdateLocked updatePowerStateLocked updateUserActivitySummaryLocked handleUserActivityTimeout updatePowerStateLocked updateWakefulnessLocked isItBedTimeYetLocked isBeingKeptAwakeLocked com_android_server_input_InputManagerService com_android_server_power_PowerManagerService PowerManagerService

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 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灭屏超时流程-初识_第3张图片

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

你可能感兴趣的:(安卓系统,PMS,电池管理,超时灭屏,灭屏)