• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.power;
18 
19 import static android.os.PowerManagerInternal.WAKEFULNESS_AWAKE;
20 
21 import static com.android.server.power.PowerManagerService.WAKE_LOCK_BUTTON_BRIGHT;
22 import static com.android.server.power.PowerManagerService.WAKE_LOCK_SCREEN_BRIGHT;
23 import static com.android.server.power.PowerManagerService.WAKE_LOCK_SCREEN_DIM;
24 import static com.android.server.power.PowerManagerService.WAKE_LOCK_SCREEN_TIMEOUT_OVERRIDE;
25 
26 import android.annotation.IntDef;
27 import android.content.Context;
28 import android.os.PowerManager;
29 import android.util.IndentingPrintWriter;
30 import android.util.Slog;
31 
32 import com.android.internal.annotations.VisibleForTesting;
33 
34 import java.io.PrintWriter;
35 import java.lang.annotation.Retention;
36 import java.lang.annotation.RetentionPolicy;
37 
38 /**
39   * Policy that handle the screen timeout override wake lock behavior.
40   */
41 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
42 final class ScreenTimeoutOverridePolicy {
43     private static final String TAG = "ScreenTimeoutOverridePolicy";
44 
45     /**
46      * Release reason code: The wake lock is never acquired.
47      */
48     public static final int RELEASE_REASON_UNKNOWN = -1;
49 
50     /**
51      * Release reason code: The wake lock can't be acquired because of screen off.
52      */
53     public static final int RELEASE_REASON_NON_INTERACTIVE = 1;
54 
55     /**
56      * Release reason code: Release because a screen lock is acquired.
57      */
58     public static final int RELEASE_REASON_SCREEN_LOCK = 2;
59 
60     /**
61      * Release reason code: Release because user activity attention occurs.
62      */
63     public static final int RELEASE_REASON_USER_ACTIVITY_ATTENTION = 3;
64 
65     /**
66      * Release reason code: Release because user activity other occurs.
67      */
68     public static final int RELEASE_REASON_USER_ACTIVITY_OTHER = 4;
69 
70     /**
71      * Release reason code: Release because user activity button occurs.
72      */
73     public static final int RELEASE_REASON_USER_ACTIVITY_BUTTON = 5;
74 
75     /**
76      * Release reason code: Release because user activity touch occurs.
77      */
78     public static final int RELEASE_REASON_USER_ACTIVITY_TOUCH = 6;
79 
80     /**
81      * Release reason code: Release because user activity accessibility occurs.
82      */
83     public static final int RELEASE_REASON_USER_ACTIVITY_ACCESSIBILITY = 7;
84 
85     /**
86      * Release reason code: Release because wakelock dies.
87      */
88     public static final int RELEASE_REASON_WAKE_LOCK_DEATH = 8;
89 
90     /**
91      * @hide
92      */
93     @IntDef(prefix = { "RELEASE_REASON_" }, value = {
94             RELEASE_REASON_UNKNOWN,
95             RELEASE_REASON_NON_INTERACTIVE,
96             RELEASE_REASON_SCREEN_LOCK,
97             RELEASE_REASON_USER_ACTIVITY_ATTENTION,
98             RELEASE_REASON_USER_ACTIVITY_OTHER,
99             RELEASE_REASON_USER_ACTIVITY_BUTTON,
100             RELEASE_REASON_USER_ACTIVITY_TOUCH,
101             RELEASE_REASON_USER_ACTIVITY_ACCESSIBILITY,
102             RELEASE_REASON_WAKE_LOCK_DEATH
103     })
104     @Retention(RetentionPolicy.SOURCE)
105     public @interface ReleaseReason{}
106 
107     // The screen timeout override config in milliseconds.
108     private long mScreenTimeoutOverrideConfig;
109 
110     // The last reason that wake locks had been released by service.
111     private @ReleaseReason int mLastAutoReleaseReason = RELEASE_REASON_UNKNOWN;
112 
113     interface PolicyCallback {
114         /**
115          * Notify {@link PowerManagerService} to release all override wake locks.
116          */
releaseAllScreenTimeoutOverrideWakelocks(@eleaseReason int reason)117         void releaseAllScreenTimeoutOverrideWakelocks(@ReleaseReason int reason);
118     }
119     private PolicyCallback mPolicyCallback;
120 
ScreenTimeoutOverridePolicy(Context context, long minimumScreenOffTimeoutConfig, PolicyCallback callback)121     ScreenTimeoutOverridePolicy(Context context, long minimumScreenOffTimeoutConfig,
122             PolicyCallback callback) {
123         mScreenTimeoutOverrideConfig = context.getResources().getInteger(
124                 com.android.internal.R.integer.config_screenTimeoutOverride);
125         if (mScreenTimeoutOverrideConfig < minimumScreenOffTimeoutConfig) {
126             Slog.w(TAG, "Screen timeout override is smaller than the minimum timeout : "
127                     + mScreenTimeoutOverrideConfig);
128             mScreenTimeoutOverrideConfig = -1;
129         }
130         mPolicyCallback = callback;
131     }
132 
133     /**
134      * Return the valid screen timeout override value.
135      */
getScreenTimeoutOverrideLocked(int wakeLockSummary, long screenOffTimeout)136     long getScreenTimeoutOverrideLocked(int wakeLockSummary, long screenOffTimeout) {
137         if (!isWakeLockAcquired(wakeLockSummary)) {
138             return screenOffTimeout;
139         }
140 
141         if (mScreenTimeoutOverrideConfig < 0) {
142             return screenOffTimeout;
143         }
144 
145         // If screen timeout overlay wake lock is acquired, return the policy timeout.
146         return Math.min(mScreenTimeoutOverrideConfig, screenOffTimeout);
147     }
148 
149     /**
150      * Called when the policy have to release all wake lock when user activity occurred.
151      */
onUserActivity(int wakeLockSummary, @PowerManager.UserActivityEvent int event)152     void onUserActivity(int wakeLockSummary, @PowerManager.UserActivityEvent int event) {
153         if (!isWakeLockAcquired(wakeLockSummary)) {
154             return;
155         }
156 
157         switch (event) {
158             case PowerManager.USER_ACTIVITY_EVENT_ATTENTION:
159                 releaseAllWakeLocks(RELEASE_REASON_USER_ACTIVITY_ATTENTION);
160                 return;
161             case PowerManager.USER_ACTIVITY_EVENT_OTHER:
162                 releaseAllWakeLocks(RELEASE_REASON_USER_ACTIVITY_OTHER);
163                 return;
164             case PowerManager.USER_ACTIVITY_EVENT_BUTTON:
165                 releaseAllWakeLocks(RELEASE_REASON_USER_ACTIVITY_BUTTON);
166                 return;
167             case PowerManager.USER_ACTIVITY_EVENT_TOUCH:
168                 releaseAllWakeLocks(RELEASE_REASON_USER_ACTIVITY_TOUCH);
169                 return;
170             case PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY:
171                 releaseAllWakeLocks(RELEASE_REASON_USER_ACTIVITY_ACCESSIBILITY);
172                 return;
173         }
174     }
175 
176     /**
177      * Check the summary whether a screen wake lock acquired .
178      */
checkScreenWakeLock(int wakeLockSummary)179     void checkScreenWakeLock(int wakeLockSummary) {
180         if (!isWakeLockAcquired(wakeLockSummary)) {
181             return;
182         }
183 
184         if ((wakeLockSummary & (WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM
185                 | WAKE_LOCK_BUTTON_BRIGHT)) != 0) {
186             releaseAllWakeLocks(RELEASE_REASON_SCREEN_LOCK);
187         }
188     }
189 
190     /**
191      * Check the device is in non-interactive
192      */
onWakefulnessChange(int wakeLockSummary, int globalWakefulness)193     void onWakefulnessChange(int wakeLockSummary, int globalWakefulness) {
194         if (!isWakeLockAcquired(wakeLockSummary)) {
195             return;
196         }
197 
198         if (globalWakefulness != WAKEFULNESS_AWAKE) {
199             releaseAllWakeLocks(RELEASE_REASON_NON_INTERACTIVE);
200         }
201     }
202 
isWakeLockAcquired(int wakeLockSummary)203     private boolean isWakeLockAcquired(int wakeLockSummary) {
204         return (wakeLockSummary & WAKE_LOCK_SCREEN_TIMEOUT_OVERRIDE) != 0;
205     }
206 
logReleaseReason()207     private void logReleaseReason() {
208         Slog.i(TAG, "Releasing all screen timeout override wake lock."
209                 + " (reason=" + mLastAutoReleaseReason + ")");
210     }
211 
releaseAllWakeLocks(@eleaseReason int reason)212     private void releaseAllWakeLocks(@ReleaseReason int reason) {
213         mPolicyCallback.releaseAllScreenTimeoutOverrideWakelocks(reason);
214         mLastAutoReleaseReason = reason;
215         logReleaseReason();
216     }
217 
dump(PrintWriter pw)218     void dump(PrintWriter pw) {
219         final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
220 
221         ipw.println();
222         ipw.println("ScreenTimeoutOverridePolicy:");
223         ipw.increaseIndent();
224 
225         ipw.println("mScreenTimeoutOverrideConfig=" + mScreenTimeoutOverrideConfig);
226         ipw.println("mLastAutoReleaseReason=" + mLastAutoReleaseReason);
227     }
228 }
229