屏幕超时休眠-Android13

1、设置界面

在这里插入图片描述
packages/apps/Settings/src/com/android/settings/display/ScreenTimeoutSettings.java
packages/apps/Settings/res/xml/screen_timeout_settings.xml

12-16 12:13:54.707  7976  7976 D SettingsActivity: Switching to fragment com.android.settings.display.ScreenTimeoutSettings

1.2 属性值

Settings.System.SCREEN_OFF_TIMEOUT

adb shell settings get System screen_off_timeout

packages/apps/Settings/res/values/arrays.xml

    <!-- Display settings.  The delay in inactivity before the screen is turned off. These are shown in a list dialog. -->
    <string-array name="screen_timeout_entries">
        <item>15 seconds</item>
        <item>30 seconds</item>
        <item>1 minute</item>
        <item>2 minutes</item>
        <item>5 minutes</item>
        <item>10 minutes</item>
        <item>30 minutes</item>
    </string-array>

    <!-- Do not translate. -->
    <string-array name="screen_timeout_values" translatable="false">
        <!-- Do not translate. -->
        <item>15000</item>
        <!-- Do not translate. -->
        <item>30000</item>
        <!-- Do not translate. -->
        <item>60000</item>
        <!-- Do not translate. -->
        <item>120000</item>
        <!-- Do not translate. -->
        <item>300000</item>
        <!-- Do not translate. -->
        <item>600000</item>
        <!-- Do not translate. -->
        <item>1800000</item>
    </string-array>

1.2.1 默认值

def_screen_off_timeout : frameworks/base/packages/SettingsProvider/res/values/defaults.xml

frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java

    private void loadSystemSettings(SQLiteDatabase db) {
        SQLiteStatement stmt = null;
        try {
            stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
                    + " VALUES(?,?);");

            loadBooleanSetting(stmt, Settings.System.DIM_SCREEN,
                    R.bool.def_dim_screen);
            loadIntegerSetting(stmt, Settings.System.SCREEN_OFF_TIMEOUT,
                    R.integer.def_screen_off_timeout);

            // Set default cdma DTMF type
            loadSetting(stmt, Settings.System.DTMF_TONE_TYPE_WHEN_DIALING, 0);

            // Set default hearing aid
            loadSetting(stmt, Settings.System.HEARING_AID, 0);

            // Set default tty mode
            loadSetting(stmt, Settings.System.TTY_MODE, 0);

            loadIntegerSetting(stmt, Settings.System.SCREEN_BRIGHTNESS,
                    R.integer.def_screen_brightness);

            loadIntegerSetting(stmt, Settings.System.SCREEN_BRIGHTNESS_FOR_VR,
                    com.android.internal.R.integer.config_screenBrightnessForVrSettingDefault);

            loadBooleanSetting(stmt, Settings.System.SCREEN_BRIGHTNESS_MODE,
                    R.bool.def_screen_brightness_automatic_mode);

            loadBooleanSetting(stmt, Settings.System.ACCELEROMETER_ROTATION,
                    R.bool.def_accelerometer_rotation);

            loadIntegerSetting(stmt, Settings.System.USER_ROTATION, R.integer.def_user_rotation);

            loadDefaultHapticSettings(stmt);

            loadBooleanSetting(stmt, Settings.System.NOTIFICATION_LIGHT_PULSE,
                    R.bool.def_notification_pulse);

            loadUISoundEffectsSettings(stmt);

            loadIntegerSetting(stmt, Settings.System.POINTER_SPEED,
                    R.integer.def_pointer_speed);

            /*
             * IMPORTANT: Do not add any more upgrade steps here as the global,
             * secure, and system settings are no longer stored in a database
             * but are kept in memory and persisted to XML.
             *
             * See: SettingsProvider.UpgradeController#onUpgradeLocked
             */
        } finally {
            if (stmt != null) stmt.close();
        }
    }

frameworks/base/packages/SettingsProvider/res/values/defaults.xml

<integer name="def_screen_off_timeout">60000</integer>

1.2.2 最小值限制

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

mMinimumScreenOffTimeoutConfig = resources.getInteger(com.android.internal.R.integer.config_minimumScreenOffTimeout);
Math.max(timeout, mMinimumScreenOffTimeoutConfig);

1.3 属性值疑问 Settings.System.SCREEN_OFF_TIMEOUT

在设置屏幕超时代码代码中,最大值可以为“Long.MAX_VALUE”,属性设置Settings.System.putLong(context.getContentResolver(), SCREEN_OFF_TIMEOUT, value);,但是实质最大值只能是Integer.MAX_VALUE(2147483647);该属性实质在fwk中是Integer保存,获取方式mScreenOffTimeoutSetting = Settings.System.getIntForUser(resolver, Settings.System.SCREEN_OFF_TIMEOUT, DEFAULT_SCREEN_OFF_TIMEOUT, UserHandle.USER_CURRENT);
在这里插入图片描述

frameworks/base/packages/SettingsProvider/src/android/provider/settings/validators/SettingsValidators.javaNON_NEGATIVE_INTEGER_VALIDATOR 检查非法值
在这里插入图片描述

    private Long getMaxScreenTimeout(Context context) {
        if (context == null) {
            return Long.MAX_VALUE;
        }
        final DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
        if (dpm == null) {
            return Long.MAX_VALUE;
        }
        mAdmin = RestrictedLockUtilsInternal.checkIfMaximumTimeToLockIsSet(context);
        if (mAdmin != null) {
            return dpm.getMaximumTimeToLock(null /* admin */, UserHandle.myUserId());
        }
        return Long.MAX_VALUE;
    }

    private String getCurrentSystemScreenTimeout(Context context) {
        if (context == null) {
            return Long.toString(FALLBACK_SCREEN_TIMEOUT_VALUE);
        } else {
            return Long.toString(Settings.System.getLong(context.getContentResolver(),
                    SCREEN_OFF_TIMEOUT, FALLBACK_SCREEN_TIMEOUT_VALUE));
        }
    }

    private void setCurrentSystemScreenTimeout(Context context, String key) {
        try {
            if (context != null) {
                final long value = Long.parseLong(key);
                mMetricsFeatureProvider.action(context, SettingsEnums.ACTION_SCREEN_TIMEOUT_CHANGED,
                        (int) value);
                Settings.System.putLong(context.getContentResolver(), SCREEN_OFF_TIMEOUT, value);
            }
        } catch (NumberFormatException e) {
            Log.e(TAG, "could not persist screen timeout setting", e);
        }
    }

2、超时灭屏

2.1 锁定屏幕的超时

更新延时 mLockScreenTimeout 执行 mScreenLockTimeout

frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java

mLockScreenTimeout = Settings.System.getIntForUser(resolver,Settings.System.SCREEN_OFF_TIMEOUT, 0, UserHandle.USER_CURRENT);
mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);

    class ScreenLockTimeout implements Runnable {
        Bundle options;

        @Override
        public void run() {
            synchronized (this) {
                if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
                if (mKeyguardDelegate != null) {
                    mKeyguardDelegate.doKeyguardTimeout(options);
                }
                mLockScreenTimerActive = false;
                mLockNowPending = false;
                options = null;
            }
        }

        public void setLockOptions(Bundle options) {
            this.options = options;
        }
    }

2.2 屏幕灭屏的超时

updateUserActivitySummaryLocked更新mUserActivitySummary的值,用户活动超时时调用updateUserActivitySummaryLocked,这里获取getScreenOffTimeoutLocked状态更新

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

mScreenOffTimeoutSetting = Settings.System.getIntForUser(resolver, Settings.System.SCREEN_OFF_TIMEOUT, DEFAULT_SCREEN_OFF_TIMEOUT, UserHandle.USER_CURRENT);

    @GuardedBy("mLock")
    private long getScreenOffTimeoutLocked(long sleepTimeout, long attentiveTimeout) {
        long timeout = mScreenOffTimeoutSetting;
        if (isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked()) {
            timeout = Math.min(timeout, mMaximumScreenOffTimeoutFromDeviceAdmin);
        }
        if (mUserActivityTimeoutOverrideFromWindowManager >= 0) {
            timeout = Math.min(timeout, mUserActivityTimeoutOverrideFromWindowManager);
        }
        if (sleepTimeout >= 0) {
            timeout = Math.min(timeout, sleepTimeout);
        }
        if (attentiveTimeout >= 0) {
            timeout = Math.min(timeout, attentiveTimeout);
        }
        return Math.max(timeout, mMinimumScreenOffTimeoutConfig);
    }

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

            mDirty |= DIRTY_USER_ACTIVITY;
            updatePowerStateLocked();
        }
    }

    /**
     * Updates the value of mUserActivitySummary to summarize the user requested
     * state of the system such as whether the screen should be bright or dim.
     * Note that user activity is ignored when the system is asleep.
     *
     * This function must have no other side-effects.
     */
    @GuardedBy("mLock")
    private void updateUserActivitySummaryLocked(long now, int dirty) {
        // Update the status of the user activity timeout timer.
        if ((dirty & (DIRTY_DISPLAY_GROUP_WAKEFULNESS | DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY
                | DIRTY_WAKEFULNESS | DIRTY_SETTINGS | DIRTY_ATTENTIVE)) == 0) {
            return;
        }
        mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT);

        final long attentiveTimeout = getAttentiveTimeoutLocked();
        final long sleepTimeout = getSleepTimeoutLocked(attentiveTimeout);
        long screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout,
                attentiveTimeout);
        final long screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);
        screenOffTimeout =
                getScreenOffTimeoutWithFaceDownLocked(screenOffTimeout, screenDimDuration);
        final boolean userInactiveOverride = mUserInactiveOverrideFromWindowManager;
        long nextTimeout = -1;
        boolean hasUserActivitySummary = false;
        for (int idx = 0; idx < mPowerGroups.size(); idx++) {
            int groupUserActivitySummary = 0;
            long groupNextTimeout = 0;
            final PowerGroup powerGroup = mPowerGroups.valueAt(idx);
            final int wakefulness = powerGroup.getWakefulnessLocked();
            if (wakefulness != WAKEFULNESS_ASLEEP) {
                final long lastUserActivityTime = powerGroup.getLastUserActivityTimeLocked();
                final long lastUserActivityTimeNoChangeLights =
                        powerGroup.getLastUserActivityTimeNoChangeLightsLocked();
                if (lastUserActivityTime >= powerGroup.getLastWakeTimeLocked()) {
                    groupNextTimeout = lastUserActivityTime + screenOffTimeout - screenDimDuration;
                    if (now < groupNextTimeout) {
                        groupUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;
                    } else {
                        groupNextTimeout = lastUserActivityTime + screenOffTimeout;
                        if (now < groupNextTimeout) {
                            groupUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;
                        }
                    }
                }
                if (groupUserActivitySummary == 0 && lastUserActivityTimeNoChangeLights
                        >= powerGroup.getLastWakeTimeLocked()) {
                    groupNextTimeout = lastUserActivityTimeNoChangeLights + screenOffTimeout;
                    if (now < groupNextTimeout) {
                        if (powerGroup.isPolicyBrightLocked() || powerGroup.isPolicyVrLocked()) {
                            groupUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;
                        } else if (powerGroup.isPolicyDimLocked()) {
                            groupUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;
                        }
                    }
                }

                if (groupUserActivitySummary == 0) {
                    if (sleepTimeout >= 0) {
                        final long anyUserActivity = Math.max(lastUserActivityTime,
                                lastUserActivityTimeNoChangeLights);
                        if (anyUserActivity >= powerGroup.getLastWakeTimeLocked()) {
                            groupNextTimeout = anyUserActivity + sleepTimeout;
                            if (now < groupNextTimeout) {
                                groupUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;
                            }
                        }
                    } else {
                        groupUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;
                        groupNextTimeout = -1;
                    }
                }

                if (groupUserActivitySummary != USER_ACTIVITY_SCREEN_DREAM
                        && userInactiveOverride) {
                    if ((groupUserActivitySummary &
                            (USER_ACTIVITY_SCREEN_BRIGHT | USER_ACTIVITY_SCREEN_DIM)) != 0) {
                        // Device is being kept awake by recent user activity
                        if (mOverriddenTimeout == -1) {
                            // Save when the next timeout would have occurred
                            mOverriddenTimeout = groupNextTimeout;
                        }
                    }
                    groupUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;
                    groupNextTimeout = -1;
                }

                if ((groupUserActivitySummary & USER_ACTIVITY_SCREEN_BRIGHT) != 0
                        && (powerGroup.getWakeLockSummaryLocked()
                        & WAKE_LOCK_STAY_AWAKE) == 0) {
                    groupNextTimeout = mAttentionDetector.updateUserActivity(groupNextTimeout,
                            screenDimDuration);
                }

                if (isAttentiveTimeoutExpired(powerGroup, now)) {
                    groupUserActivitySummary = 0;
                    groupNextTimeout = -1;
                }

                hasUserActivitySummary |= groupUserActivitySummary != 0;

                if (nextTimeout == -1) {
                    nextTimeout = groupNextTimeout;
                } else if (groupNextTimeout != -1) {
                    nextTimeout = Math.min(nextTimeout, groupNextTimeout);
                }
            }

            powerGroup.setUserActivitySummaryLocked(groupUserActivitySummary);

            if (DEBUG_SPEW) {
                Slog.d(TAG, "updateUserActivitySummaryLocked: groupId=" + powerGroup.getGroupId()
                        + ", mWakefulness=" + wakefulnessToString(wakefulness)
                        + ", mUserActivitySummary=0x" + Integer.toHexString(
                        groupUserActivitySummary)
                        + ", nextTimeout=" + TimeUtils.formatUptime(groupNextTimeout));
            }
        }

        final long nextProfileTimeout = getNextProfileTimeoutLocked(now);
        if (nextProfileTimeout > 0) {
            nextTimeout = Math.min(nextTimeout, nextProfileTimeout);
        }

        if (hasUserActivitySummary && nextTimeout >= 0) {
            scheduleUserInactivityTimeout(nextTimeout);
        }
    }

    private void scheduleUserInactivityTimeout(long timeMs) {
        final Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT);
        msg.setAsynchronous(true);
        mHandler.sendMessageAtTime(msg, timeMs);
    }

3、永不休眠

    1. PowerManagerServicePhoneWindowManager 处理
    1. 直接配置 Settings.System.SCREEN_OFF_TIMEOUTInteger.MAX_VALUE2147483647 = 24.855 天 一般没有这么长时间亮屏待机 ),设置更长时间替换 Settings.System.SCREEN_OFF_TIMEOUT属性 VALIDATORS.put(System.SCREEN_OFF_TIMEOUT, NON_NEGATIVE_INTEGER_VALIDATOR)NON_NEGATIVE_INTEGER_VALIDATOR检测为NONE_NEGATIVE_LONG_VALIDATOR

* 关键日志

SettingsActivity:|SubSettings: Launching fragment|start u|ScreenTimeout:|sysui_multi_action: \[757,1754|screen_toggled:|sysui_multi_action:.*screen_timeout|power_screen_state:|PowerManagerService: Waking up|PowerManagerService: Going to sleep

sysui_multi_action: [757,1754,758,4,759,15000]
sysui_multi_action: [757,1754,758,4,759,30000]
sysui_multi_action: [757,1754,758,4,759,60000]
sysui_multi_action: [757,1754,758,4,759,120000]
sysui_multi_action: [757,1754,758,4,759,300000]
sysui_multi_action: [757,1754,758,4,759,600000]
sysui_multi_action: [757,1754,758,4,759,1800000]

12-17 07:13:37.536   645   678 I ActivityTaskManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000100 cmp=com.google.android.apps.nexuslauncher/.NexusLauncherActivity (has extras)} from uid 0
12-17 07:13:40.128   645  2427 I ActivityTaskManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.settings/.Settings bnds=[581,351][858,771]} from uid 10149
12-17 07:13:46.309   645  2510 I ActivityTaskManager: START u0 {act=android.intent.action.MAIN cmp=com.android.settings/.SubSettings (has extras)} from uid 1000
12-17 07:13:46.408  7976  7976 D SettingsActivity: Switching to fragment com.android.settings.DisplaySettings
12-17 07:13:46.409  7976  7976 D SubSettings: Launching fragment com.android.settings.DisplaySettings
12-17 07:13:48.942  7976  7976 I sysui_multi_action: [757,830,758,4,833,0,854,screen_timeout,1089,0]
12-17 07:13:48.948   645  1716 I ActivityTaskManager: START u0 {act=android.intent.action.MAIN cmp=com.android.settings/.SubSettings (has extras)} from uid 1000
12-17 07:13:49.036  7976  7976 D SettingsActivity: Switching to fragment com.android.settings.display.ScreenTimeoutSettings
12-17 07:13:49.037  7976  7976 D SubSettings: Launching fragment com.android.settings.display.ScreenTimeoutSettings
12-17 07:13:50.690  7976  7976 I sysui_multi_action: [757,1754,758,4,759,15000]
12-17 07:13:52.884  7976  7976 I sysui_multi_action: [757,1754,758,4,759,30000]
12-17 07:13:54.152  7976  7976 I sysui_multi_action: [757,1754,758,4,759,60000]
12-17 07:13:55.559  7976  7976 I sysui_multi_action: [757,1754,758,4,759,120000]
12-17 07:13:57.041  7976  7976 I sysui_multi_action: [757,1754,758,4,759,300000]
12-17 07:13:58.400  7976  7976 I sysui_multi_action: [757,1754,758,4,759,600000]
12-17 07:13:59.653  7976  7976 I sysui_multi_action: [757,1754,758,4,759,1800000]
12-17 07:14:01.446  7976  7976 I sysui_multi_action: [757,1754,758,4,759,15000]
12-17 07:14:16.400   645   708 I PowerManagerService: Going to sleep due to timeout (uid 1000)...
12-17 07:14:17.032   645   645 I power_screen_state: [0,3,0,0,628]
12-17 07:14:17.032   645   645 I screen_toggled: 0
12-17 07:14:17.032   645   645 I sysui_multi_action: [757,804,799,screen_timeout,801,15,802,1]
12-17 07:14:28.765   645   793 I PowerManagerService: Waking up from Asleep (uid=1000, reason=WAKE_REASON_POWER_BUTTON, details=android.policy:POWER)...
12-17 07:14:28.770   645   645 I screen_toggled: 1
12-17 07:14:28.905   645   645 I power_screen_state: [1,0,0,0,110]