• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 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 android.annotation.Nullable;
20 import android.annotation.UserIdInt;
21 import android.app.ActivityManagerInternal;
22 import android.app.AppOpsManager;
23 import android.app.trust.TrustManager;
24 import android.content.BroadcastReceiver;
25 import android.content.Context;
26 import android.content.Intent;
27 import android.hardware.display.DisplayManagerInternal;
28 import android.hardware.input.InputManagerInternal;
29 import android.media.AudioManager;
30 import android.media.Ringtone;
31 import android.media.RingtoneManager;
32 import android.metrics.LogMaker;
33 import android.net.Uri;
34 import android.os.BatteryStats;
35 import android.os.Handler;
36 import android.os.IWakeLockCallback;
37 import android.os.Looper;
38 import android.os.Message;
39 import android.os.PowerManager;
40 import android.os.PowerManagerInternal;
41 import android.os.Process;
42 import android.os.RemoteException;
43 import android.os.SystemClock;
44 import android.os.UserHandle;
45 import android.os.VibrationAttributes;
46 import android.os.VibrationEffect;
47 import android.os.Vibrator;
48 import android.os.WorkSource;
49 import android.provider.Settings;
50 import android.telephony.TelephonyManager;
51 import android.util.EventLog;
52 import android.util.Slog;
53 import android.view.WindowManagerPolicyConstants;
54 
55 import com.android.internal.annotations.VisibleForTesting;
56 import com.android.internal.app.IBatteryStats;
57 import com.android.internal.logging.MetricsLogger;
58 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
59 import com.android.internal.util.FrameworkStatsLog;
60 import com.android.server.EventLogTags;
61 import com.android.server.LocalServices;
62 import com.android.server.inputmethod.InputMethodManagerInternal;
63 import com.android.server.policy.WindowManagerPolicy;
64 import com.android.server.statusbar.StatusBarManagerInternal;
65 
66 import java.io.PrintWriter;
67 import java.util.concurrent.Executor;
68 import java.util.concurrent.atomic.AtomicBoolean;
69 
70 /**
71  * Sends broadcasts about important power state changes.
72  * <p>
73  * This methods of this class may be called by the power manager service while
74  * its lock is being held.  Internally it takes care of sending broadcasts to
75  * notify other components of the system or applications asynchronously.
76  * </p><p>
77  * The notifier is designed to collapse unnecessary broadcasts when it is not
78  * possible for the system to have observed an intermediate state.
79  * </p><p>
80  * For example, if the device wakes up, goes to sleep, wakes up again and goes to
81  * sleep again before the wake up notification is sent, then the system will
82  * be told about only one wake up and sleep.  However, we always notify the
83  * fact that at least one transition occurred.  It is especially important to
84  * tell the system when we go to sleep so that it can lock the keyguard if needed.
85  * </p>
86  */
87 @VisibleForTesting
88 public class Notifier {
89     private static final String TAG = "PowerManagerNotifier";
90 
91     private static final boolean DEBUG = false;
92 
93     private static final int INTERACTIVE_STATE_UNKNOWN = 0;
94     private static final int INTERACTIVE_STATE_AWAKE = 1;
95     private static final int INTERACTIVE_STATE_ASLEEP = 2;
96 
97     private static final int MSG_USER_ACTIVITY = 1;
98     private static final int MSG_BROADCAST = 2;
99     private static final int MSG_WIRELESS_CHARGING_STARTED = 3;
100     private static final int MSG_BROADCAST_ENHANCED_PREDICTION = 4;
101     private static final int MSG_PROFILE_TIMED_OUT = 5;
102     private static final int MSG_WIRED_CHARGING_STARTED = 6;
103     private static final int MSG_SCREEN_POLICY = 7;
104 
105     private static final long[] CHARGING_VIBRATION_TIME = {
106             40, 40, 40, 40, 40, 40, 40, 40, 40, // ramp-up sampling rate = 40ms
107             40, 40, 40, 40, 40, 40, 40 // ramp-down sampling rate = 40ms
108     };
109     private static final int[] CHARGING_VIBRATION_AMPLITUDE = {
110             1, 4, 11, 25, 44, 67, 91, 114, 123, // ramp-up amplitude (from 0 to 50%)
111             103, 79, 55, 34, 17, 7, 2 // ramp-up amplitude
112     };
113     private static final VibrationEffect CHARGING_VIBRATION_EFFECT =
114             VibrationEffect.createWaveform(CHARGING_VIBRATION_TIME, CHARGING_VIBRATION_AMPLITUDE,
115                     -1);
116     private static final VibrationAttributes HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES =
117             VibrationAttributes.createForUsage(VibrationAttributes.USAGE_HARDWARE_FEEDBACK);
118 
119     private final Object mLock = new Object();
120 
121     private final Context mContext;
122     private final IBatteryStats mBatteryStats;
123     private final AppOpsManager mAppOps;
124     private final SuspendBlocker mSuspendBlocker;
125     private final WindowManagerPolicy mPolicy;
126     private final FaceDownDetector mFaceDownDetector;
127     private final ScreenUndimDetector mScreenUndimDetector;
128     private final ActivityManagerInternal mActivityManagerInternal;
129     private final InputManagerInternal mInputManagerInternal;
130     private final InputMethodManagerInternal mInputMethodManagerInternal;
131     @Nullable private final StatusBarManagerInternal mStatusBarManagerInternal;
132     private final TrustManager mTrustManager;
133     private final Vibrator mVibrator;
134     private final WakeLockLog mWakeLockLog;
135     private final DisplayManagerInternal mDisplayManagerInternal;
136 
137     private final NotifierHandler mHandler;
138     private final Executor mBackgroundExecutor;
139     private final Intent mScreenOnIntent;
140     private final Intent mScreenOffIntent;
141 
142     // True if the device should suspend when the screen is off due to proximity.
143     private final boolean mSuspendWhenScreenOffDueToProximityConfig;
144 
145     // True if the device should show the wireless charging animation when the device
146     // begins charging wirelessly
147     private final boolean mShowWirelessChargingAnimationConfig;
148 
149     // The current interactive state.  This is set as soon as an interactive state
150     // transition begins so as to capture the reason that it happened.  At some point
151     // this state will propagate to the pending state then eventually to the
152     // broadcasted state over the course of reporting the transition asynchronously.
153     private boolean mInteractive = true;
154     private int mInteractiveChangeReason;
155     private long mInteractiveChangeStartTime; // In SystemClock.uptimeMillis()
156     private boolean mInteractiveChanging;
157 
158     // The pending interactive state that we will eventually want to broadcast.
159     // This is designed so that we can collapse redundant sequences of awake/sleep
160     // transition pairs while still guaranteeing that at least one transition is observed
161     // whenever this happens.
162     private int mPendingInteractiveState;
163     private boolean mPendingWakeUpBroadcast;
164     private boolean mPendingGoToSleepBroadcast;
165 
166     // The currently broadcasted interactive state.  This reflects what other parts of the
167     // system have observed.
168     private int mBroadcastedInteractiveState;
169     private boolean mBroadcastInProgress;
170     private long mBroadcastStartTime;
171 
172     // True if a user activity message should be sent.
173     private boolean mUserActivityPending;
174 
175     private final AtomicBoolean mIsPlayingChargingStartedFeedback = new AtomicBoolean(false);
176 
Notifier(Looper looper, Context context, IBatteryStats batteryStats, SuspendBlocker suspendBlocker, WindowManagerPolicy policy, FaceDownDetector faceDownDetector, ScreenUndimDetector screenUndimDetector, Executor backgroundExecutor)177     public Notifier(Looper looper, Context context, IBatteryStats batteryStats,
178             SuspendBlocker suspendBlocker, WindowManagerPolicy policy,
179             FaceDownDetector faceDownDetector, ScreenUndimDetector screenUndimDetector,
180             Executor backgroundExecutor) {
181         mContext = context;
182         mBatteryStats = batteryStats;
183         mAppOps = mContext.getSystemService(AppOpsManager.class);
184         mSuspendBlocker = suspendBlocker;
185         mPolicy = policy;
186         mFaceDownDetector = faceDownDetector;
187         mScreenUndimDetector = screenUndimDetector;
188         mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
189         mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
190         mInputMethodManagerInternal = LocalServices.getService(InputMethodManagerInternal.class);
191         mStatusBarManagerInternal = LocalServices.getService(StatusBarManagerInternal.class);
192         mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
193         mTrustManager = mContext.getSystemService(TrustManager.class);
194         mVibrator = mContext.getSystemService(Vibrator.class);
195 
196         mHandler = new NotifierHandler(looper);
197         mBackgroundExecutor = backgroundExecutor;
198         mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);
199         mScreenOnIntent.addFlags(
200                 Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND
201                 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
202         mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF);
203         mScreenOffIntent.addFlags(
204                 Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND
205                 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
206 
207         mSuspendWhenScreenOffDueToProximityConfig = context.getResources().getBoolean(
208                 com.android.internal.R.bool.config_suspendWhenScreenOffDueToProximity);
209         mShowWirelessChargingAnimationConfig = context.getResources().getBoolean(
210                 com.android.internal.R.bool.config_showBuiltinWirelessChargingAnim);
211 
212         mWakeLockLog = new WakeLockLog();
213 
214         // Initialize interactive state for battery stats.
215         try {
216             mBatteryStats.noteInteractive(true);
217         } catch (RemoteException ex) { }
218         FrameworkStatsLog.write(FrameworkStatsLog.INTERACTIVE_STATE_CHANGED,
219                 FrameworkStatsLog.INTERACTIVE_STATE_CHANGED__STATE__ON);
220     }
221 
222     /**
223      * Called when a wake lock is acquired.
224      */
onWakeLockAcquired(int flags, String tag, String packageName, int ownerUid, int ownerPid, WorkSource workSource, String historyTag, IWakeLockCallback callback)225     public void onWakeLockAcquired(int flags, String tag, String packageName,
226             int ownerUid, int ownerPid, WorkSource workSource, String historyTag,
227             IWakeLockCallback callback) {
228         if (DEBUG) {
229             Slog.d(TAG, "onWakeLockAcquired: flags=" + flags + ", tag=\"" + tag
230                     + "\", packageName=" + packageName
231                     + ", ownerUid=" + ownerUid + ", ownerPid=" + ownerPid
232                     + ", workSource=" + workSource);
233         }
234         notifyWakeLockListener(callback, true);
235         final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
236         if (monitorType >= 0) {
237             try {
238                 final boolean unimportantForLogging = ownerUid == Process.SYSTEM_UID
239                         && (flags & PowerManager.UNIMPORTANT_FOR_LOGGING) != 0;
240                 if (workSource != null) {
241                     mBatteryStats.noteStartWakelockFromSource(workSource, ownerPid, tag,
242                             historyTag, monitorType, unimportantForLogging);
243                 } else {
244                     mBatteryStats.noteStartWakelock(ownerUid, ownerPid, tag, historyTag,
245                             monitorType, unimportantForLogging);
246                     // XXX need to deal with disabled operations.
247                     mAppOps.startOpNoThrow(AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName);
248                 }
249             } catch (RemoteException ex) {
250                 // Ignore
251             }
252         }
253 
254         mWakeLockLog.onWakeLockAcquired(tag, ownerUid, flags);
255     }
256 
onLongPartialWakeLockStart(String tag, int ownerUid, WorkSource workSource, String historyTag)257     public void onLongPartialWakeLockStart(String tag, int ownerUid, WorkSource workSource,
258             String historyTag) {
259         if (DEBUG) {
260             Slog.d(TAG, "onLongPartialWakeLockStart: ownerUid=" + ownerUid
261                     + ", workSource=" + workSource);
262         }
263 
264         try {
265             if (workSource != null) {
266                 mBatteryStats.noteLongPartialWakelockStartFromSource(tag, historyTag, workSource);
267                 FrameworkStatsLog.write(FrameworkStatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED,
268                         workSource, tag, historyTag,
269                         FrameworkStatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__ON);
270             } else {
271                 mBatteryStats.noteLongPartialWakelockStart(tag, historyTag, ownerUid);
272                 FrameworkStatsLog.write_non_chained(
273                         FrameworkStatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED, ownerUid, null, tag,
274                         historyTag,
275                         FrameworkStatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__ON);
276             }
277         } catch (RemoteException ex) {
278             // Ignore
279         }
280     }
281 
onLongPartialWakeLockFinish(String tag, int ownerUid, WorkSource workSource, String historyTag)282     public void onLongPartialWakeLockFinish(String tag, int ownerUid, WorkSource workSource,
283             String historyTag) {
284         if (DEBUG) {
285             Slog.d(TAG, "onLongPartialWakeLockFinish: ownerUid=" + ownerUid
286                     + ", workSource=" + workSource);
287         }
288 
289         try {
290             if (workSource != null) {
291                 mBatteryStats.noteLongPartialWakelockFinishFromSource(tag, historyTag, workSource);
292                 FrameworkStatsLog.write(FrameworkStatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED,
293                         workSource, tag, historyTag,
294                         FrameworkStatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__OFF);
295             } else {
296                 mBatteryStats.noteLongPartialWakelockFinish(tag, historyTag, ownerUid);
297                 FrameworkStatsLog.write_non_chained(
298                         FrameworkStatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED, ownerUid, null, tag,
299                         historyTag,
300                         FrameworkStatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__OFF);
301             }
302         } catch (RemoteException ex) {
303             // Ignore
304         }
305     }
306 
307     /**
308      * Called when a wake lock is changing.
309      */
onWakeLockChanging(int flags, String tag, String packageName, int ownerUid, int ownerPid, WorkSource workSource, String historyTag, IWakeLockCallback callback, int newFlags, String newTag, String newPackageName, int newOwnerUid, int newOwnerPid, WorkSource newWorkSource, String newHistoryTag, IWakeLockCallback newCallback)310     public void onWakeLockChanging(int flags, String tag, String packageName,
311             int ownerUid, int ownerPid, WorkSource workSource, String historyTag,
312             IWakeLockCallback callback, int newFlags, String newTag, String newPackageName,
313             int newOwnerUid, int newOwnerPid, WorkSource newWorkSource, String newHistoryTag,
314             IWakeLockCallback newCallback) {
315 
316         final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
317         final int newMonitorType = getBatteryStatsWakeLockMonitorType(newFlags);
318         if (workSource != null && newWorkSource != null
319                 && monitorType >= 0 && newMonitorType >= 0) {
320             if (DEBUG) {
321                 Slog.d(TAG, "onWakeLockChanging: flags=" + newFlags + ", tag=\"" + newTag
322                         + "\", packageName=" + newPackageName
323                         + ", ownerUid=" + newOwnerUid + ", ownerPid=" + newOwnerPid
324                         + ", workSource=" + newWorkSource);
325             }
326 
327             final boolean unimportantForLogging = newOwnerUid == Process.SYSTEM_UID
328                     && (newFlags & PowerManager.UNIMPORTANT_FOR_LOGGING) != 0;
329             try {
330                 mBatteryStats.noteChangeWakelockFromSource(workSource, ownerPid, tag, historyTag,
331                         monitorType, newWorkSource, newOwnerPid, newTag, newHistoryTag,
332                         newMonitorType, unimportantForLogging);
333             } catch (RemoteException ex) {
334                 // Ignore
335             }
336         } else if (!PowerManagerService.isSameCallback(callback, newCallback)) {
337             onWakeLockReleased(flags, tag, packageName, ownerUid, ownerPid, workSource, historyTag,
338                     null /* Do not notify the old callback */);
339             onWakeLockAcquired(newFlags, newTag, newPackageName, newOwnerUid, newOwnerPid,
340                     newWorkSource, newHistoryTag, newCallback /* notify the new callback */);
341         } else {
342             onWakeLockReleased(flags, tag, packageName, ownerUid, ownerPid, workSource, historyTag,
343                     callback);
344             onWakeLockAcquired(newFlags, newTag, newPackageName, newOwnerUid, newOwnerPid,
345                     newWorkSource, newHistoryTag, newCallback);
346         }
347     }
348 
349     /**
350      * Called when a wake lock is released.
351      */
onWakeLockReleased(int flags, String tag, String packageName, int ownerUid, int ownerPid, WorkSource workSource, String historyTag, IWakeLockCallback callback)352     public void onWakeLockReleased(int flags, String tag, String packageName,
353             int ownerUid, int ownerPid, WorkSource workSource, String historyTag,
354             IWakeLockCallback callback) {
355         if (DEBUG) {
356             Slog.d(TAG, "onWakeLockReleased: flags=" + flags + ", tag=\"" + tag
357                     + "\", packageName=" + packageName
358                     + ", ownerUid=" + ownerUid + ", ownerPid=" + ownerPid
359                     + ", workSource=" + workSource);
360         }
361         notifyWakeLockListener(callback, false);
362         final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
363         if (monitorType >= 0) {
364             try {
365                 if (workSource != null) {
366                     mBatteryStats.noteStopWakelockFromSource(workSource, ownerPid, tag,
367                             historyTag, monitorType);
368                 } else {
369                     mBatteryStats.noteStopWakelock(ownerUid, ownerPid, tag,
370                             historyTag, monitorType);
371                     mAppOps.finishOp(AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName);
372                 }
373             } catch (RemoteException ex) {
374                 // Ignore
375             }
376         }
377         mWakeLockLog.onWakeLockReleased(tag, ownerUid);
378     }
379 
getBatteryStatsWakeLockMonitorType(int flags)380     private int getBatteryStatsWakeLockMonitorType(int flags) {
381         switch (flags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
382             case PowerManager.PARTIAL_WAKE_LOCK:
383                 return BatteryStats.WAKE_TYPE_PARTIAL;
384 
385             case PowerManager.SCREEN_DIM_WAKE_LOCK:
386             case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
387                 return BatteryStats.WAKE_TYPE_FULL;
388 
389             case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
390                 if (mSuspendWhenScreenOffDueToProximityConfig) {
391                     return -1;
392                 }
393                 return BatteryStats.WAKE_TYPE_PARTIAL;
394 
395             case PowerManager.DRAW_WAKE_LOCK:
396                 return BatteryStats.WAKE_TYPE_DRAW;
397 
398             case PowerManager.DOZE_WAKE_LOCK:
399                 // Doze wake locks are an internal implementation detail of the
400                 // communication between dream manager service and power manager
401                 // service.  They have no additive battery impact.
402                 return -1;
403 
404             default:
405                 return -1;
406         }
407     }
408 
409     /**
410      * Notifies that the device is changing wakefulness.
411      * This function may be called even if the previous change hasn't finished in
412      * which case it will assume that the state did not fully converge before the
413      * next transition began and will recover accordingly.
414      */
onWakefulnessChangeStarted(final int wakefulness, int reason, long eventTime)415     public void onWakefulnessChangeStarted(final int wakefulness, int reason, long eventTime) {
416         final boolean interactive = PowerManagerInternal.isInteractive(wakefulness);
417         if (DEBUG) {
418             Slog.d(TAG, "onWakefulnessChangeStarted: wakefulness=" + wakefulness
419                     + ", reason=" + reason + ", interactive=" + interactive);
420         }
421 
422         // Tell the activity manager about changes in wakefulness, not just interactivity.
423         // It needs more granularity than other components.
424         mHandler.post(new Runnable() {
425             @Override
426             public void run() {
427                 mActivityManagerInternal.onWakefulnessChanged(wakefulness);
428             }
429         });
430 
431         // Handle any early interactive state changes.
432         // Finish pending incomplete ones from a previous cycle.
433         if (mInteractive != interactive) {
434             // Finish up late behaviors if needed.
435             if (mInteractiveChanging) {
436                 handleLateInteractiveChange();
437             }
438 
439             // Start input as soon as we start waking up or going to sleep.
440             mInputManagerInternal.setInteractive(interactive);
441             mInputMethodManagerInternal.setInteractive(interactive);
442 
443             // Notify battery stats.
444             try {
445                 mBatteryStats.noteInteractive(interactive);
446             } catch (RemoteException ex) { }
447             FrameworkStatsLog.write(FrameworkStatsLog.INTERACTIVE_STATE_CHANGED,
448                     interactive ? FrameworkStatsLog.INTERACTIVE_STATE_CHANGED__STATE__ON :
449                             FrameworkStatsLog.INTERACTIVE_STATE_CHANGED__STATE__OFF);
450 
451             // Handle early behaviors.
452             mInteractive = interactive;
453             mInteractiveChangeReason = reason;
454             mInteractiveChangeStartTime = eventTime;
455             mInteractiveChanging = true;
456             handleEarlyInteractiveChange();
457         }
458     }
459 
460     /**
461      * Notifies that the device has finished changing wakefulness.
462      */
onWakefulnessChangeFinished()463     public void onWakefulnessChangeFinished() {
464         if (DEBUG) {
465             Slog.d(TAG, "onWakefulnessChangeFinished");
466         }
467 
468         if (mInteractiveChanging) {
469             mInteractiveChanging = false;
470             handleLateInteractiveChange();
471         }
472     }
473 
474     /**
475      * Handle early interactive state changes such as getting applications or the lock
476      * screen running and ready for the user to see (such as when turning on the screen).
477      */
handleEarlyInteractiveChange()478     private void handleEarlyInteractiveChange() {
479         synchronized (mLock) {
480             if (mInteractive) {
481                 // Waking up...
482                 mHandler.post(() -> {
483                     mPolicy.startedWakingUp(mInteractiveChangeReason);
484                     mDisplayManagerInternal.onEarlyInteractivityChange(true /*isInteractive*/);
485                 });
486 
487                 // Send interactive broadcast.
488                 mPendingInteractiveState = INTERACTIVE_STATE_AWAKE;
489                 mPendingWakeUpBroadcast = true;
490                 updatePendingBroadcastLocked();
491             } else {
492                 // Going to sleep...
493                 // Tell the policy that we started going to sleep.
494                 mHandler.post(() -> {
495                     mPolicy.startedGoingToSleep(mInteractiveChangeReason);
496                     mDisplayManagerInternal.onEarlyInteractivityChange(false /*isInteractive*/);
497                 });
498             }
499         }
500     }
501 
502     /**
503      * Handle late interactive state changes once they are finished so that the system can
504      * finish pending transitions (such as turning the screen off) before causing
505      * applications to change state visibly.
506      */
handleLateInteractiveChange()507     private void handleLateInteractiveChange() {
508         synchronized (mLock) {
509             final int interactiveChangeLatency =
510                     (int) (SystemClock.uptimeMillis() - mInteractiveChangeStartTime);
511             if (mInteractive) {
512                 // Finished waking up...
513                 mHandler.post(() -> {
514                     LogMaker log = new LogMaker(MetricsEvent.SCREEN);
515                     log.setType(MetricsEvent.TYPE_OPEN);
516                     log.setSubtype(WindowManagerPolicyConstants.translateWakeReasonToOnReason(
517                             mInteractiveChangeReason));
518                     log.setLatency(interactiveChangeLatency);
519                     log.addTaggedData(
520                             MetricsEvent.FIELD_SCREEN_WAKE_REASON, mInteractiveChangeReason);
521                     MetricsLogger.action(log);
522                     EventLogTags.writePowerScreenState(1, 0, 0, 0, interactiveChangeLatency);
523                     mPolicy.finishedWakingUp(mInteractiveChangeReason);
524                 });
525             } else {
526                 // Finished going to sleep...
527                 // This is a good time to make transitions that we don't want the user to see,
528                 // such as bringing the key guard to focus.  There's no guarantee for this
529                 // however because the user could turn the device on again at any time.
530                 // Some things may need to be protected by other mechanisms that defer screen on.
531 
532                 // Cancel pending user activity.
533                 if (mUserActivityPending) {
534                     mUserActivityPending = false;
535                     mHandler.removeMessages(MSG_USER_ACTIVITY);
536                 }
537 
538                 // Tell the policy we finished going to sleep.
539                 final int offReason = WindowManagerPolicyConstants.translateSleepReasonToOffReason(
540                         mInteractiveChangeReason);
541                 mHandler.post(() -> {
542                     LogMaker log = new LogMaker(MetricsEvent.SCREEN);
543                     log.setType(MetricsEvent.TYPE_CLOSE);
544                     log.setSubtype(offReason);
545                     log.setLatency(interactiveChangeLatency);
546                     log.addTaggedData(
547                             MetricsEvent.FIELD_SCREEN_SLEEP_REASON, mInteractiveChangeReason);
548                     MetricsLogger.action(log);
549                     EventLogTags.writePowerScreenState(
550                             0, offReason, 0, 0, interactiveChangeLatency);
551                     mPolicy.finishedGoingToSleep(mInteractiveChangeReason);
552                 });
553 
554                 // Send non-interactive broadcast.
555                 mPendingInteractiveState = INTERACTIVE_STATE_ASLEEP;
556                 mPendingGoToSleepBroadcast = true;
557                 updatePendingBroadcastLocked();
558             }
559         }
560     }
561 
562     /**
563      * Called when an individual PowerGroup changes wakefulness.
564      */
onPowerGroupWakefulnessChanged(int groupId, int groupWakefulness, int changeReason, int globalWakefulness)565     public void onPowerGroupWakefulnessChanged(int groupId, int groupWakefulness, int changeReason,
566             int globalWakefulness) {
567         mHandler.post(() -> mPolicy.onPowerGroupWakefulnessChanged(groupId, groupWakefulness,
568                 changeReason, globalWakefulness));
569     }
570 
571     /**
572      * Called when there has been user activity.
573      */
onUserActivity(int displayGroupId, @PowerManager.UserActivityEvent int event, int uid)574     public void onUserActivity(int displayGroupId, @PowerManager.UserActivityEvent int event,
575             int uid) {
576         if (DEBUG) {
577             Slog.d(TAG, "onUserActivity: event=" + event + ", uid=" + uid);
578         }
579 
580         try {
581             mBatteryStats.noteUserActivity(uid, event);
582         } catch (RemoteException ex) {
583             // Ignore
584         }
585 
586         synchronized (mLock) {
587             if (!mUserActivityPending) {
588                 mUserActivityPending = true;
589                 Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY);
590                 msg.arg1 = displayGroupId;
591                 msg.arg2 = event;
592                 msg.setAsynchronous(true);
593                 mHandler.sendMessage(msg);
594             }
595         }
596     }
597 
598     /**
599      * Called when the screen has turned on.
600      */
onWakeUp(int reason, String details, int reasonUid, String opPackageName, int opUid)601     public void onWakeUp(int reason, String details, int reasonUid, String opPackageName,
602             int opUid) {
603         if (DEBUG) {
604             Slog.d(TAG, "onWakeUp: reason=" + PowerManager.wakeReasonToString(reason)
605                     + ", details=" + details + ", reasonUid=" + reasonUid
606                     + " opPackageName=" + opPackageName + " opUid=" + opUid);
607         }
608 
609         try {
610             mBatteryStats.noteWakeUp(details, reasonUid);
611             if (opPackageName != null) {
612                 mAppOps.noteOpNoThrow(AppOpsManager.OP_TURN_SCREEN_ON, opUid, opPackageName);
613             }
614         } catch (RemoteException ex) {
615             // Ignore
616         }
617         FrameworkStatsLog.write(FrameworkStatsLog.DISPLAY_WAKE_REPORTED, reason);
618     }
619 
620     /**
621      * Called when profile screen lock timeout has expired.
622      */
onProfileTimeout(@serIdInt int userId)623     public void onProfileTimeout(@UserIdInt int userId) {
624         final Message msg = mHandler.obtainMessage(MSG_PROFILE_TIMED_OUT);
625         msg.setAsynchronous(true);
626         msg.arg1 = userId;
627         mHandler.sendMessage(msg);
628     }
629 
630     /**
631      * Called when wireless charging has started - to provide user feedback (sound and visual).
632      */
onWirelessChargingStarted(int batteryLevel, @UserIdInt int userId)633     public void onWirelessChargingStarted(int batteryLevel, @UserIdInt int userId) {
634         if (DEBUG) {
635             Slog.d(TAG, "onWirelessChargingStarted");
636         }
637 
638         mSuspendBlocker.acquire();
639         Message msg = mHandler.obtainMessage(MSG_WIRELESS_CHARGING_STARTED);
640         msg.setAsynchronous(true);
641         msg.arg1 = batteryLevel;
642         msg.arg2 = userId;
643         mHandler.sendMessage(msg);
644     }
645 
646     /**
647      * Called when wired charging has started - to provide user feedback
648      */
onWiredChargingStarted(@serIdInt int userId)649     public void onWiredChargingStarted(@UserIdInt int userId) {
650         if (DEBUG) {
651             Slog.d(TAG, "onWiredChargingStarted");
652         }
653 
654         mSuspendBlocker.acquire();
655         Message msg = mHandler.obtainMessage(MSG_WIRED_CHARGING_STARTED);
656         msg.setAsynchronous(true);
657         msg.arg1 = userId;
658         mHandler.sendMessage(msg);
659     }
660 
661     /**
662      * Called when the screen policy changes.
663      */
onScreenPolicyUpdate(int displayGroupId, int newPolicy)664     public void onScreenPolicyUpdate(int displayGroupId, int newPolicy) {
665         if (DEBUG) {
666             Slog.d(TAG, "onScreenPolicyUpdate: newPolicy=" + newPolicy);
667         }
668 
669         synchronized (mLock) {
670             Message msg = mHandler.obtainMessage(MSG_SCREEN_POLICY);
671             msg.arg1 = displayGroupId;
672             msg.arg2 = newPolicy;
673             msg.setAsynchronous(true);
674             mHandler.sendMessage(msg);
675         }
676     }
677 
678     /**
679      * Dumps data for bugreports.
680      *
681      * @param pw The stream to print to.
682      */
dump(PrintWriter pw)683     public void dump(PrintWriter pw) {
684         if (mWakeLockLog != null) {
685             mWakeLockLog.dump(pw);
686         }
687     }
688 
updatePendingBroadcastLocked()689     private void updatePendingBroadcastLocked() {
690         if (!mBroadcastInProgress
691                 && mPendingInteractiveState != INTERACTIVE_STATE_UNKNOWN
692                 && (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
693                         || mPendingInteractiveState != mBroadcastedInteractiveState)) {
694             mBroadcastInProgress = true;
695             mSuspendBlocker.acquire();
696             Message msg = mHandler.obtainMessage(MSG_BROADCAST);
697             msg.setAsynchronous(true);
698             mHandler.sendMessage(msg);
699         }
700     }
701 
finishPendingBroadcastLocked()702     private void finishPendingBroadcastLocked() {
703         mBroadcastInProgress = false;
704         mSuspendBlocker.release();
705     }
706 
sendUserActivity(int displayGroupId, int event)707     private void sendUserActivity(int displayGroupId, int event) {
708         synchronized (mLock) {
709             if (!mUserActivityPending) {
710                 return;
711             }
712             mUserActivityPending = false;
713         }
714         TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
715         tm.notifyUserActivity();
716         mPolicy.userActivity(displayGroupId, event);
717         mFaceDownDetector.userActivity(event);
718         mScreenUndimDetector.userActivity(displayGroupId);
719     }
720 
postEnhancedDischargePredictionBroadcast(long delayMs)721     void postEnhancedDischargePredictionBroadcast(long delayMs) {
722         mHandler.sendEmptyMessageDelayed(MSG_BROADCAST_ENHANCED_PREDICTION, delayMs);
723     }
724 
sendEnhancedDischargePredictionBroadcast()725     private void sendEnhancedDischargePredictionBroadcast() {
726         Intent intent = new Intent(PowerManager.ACTION_ENHANCED_DISCHARGE_PREDICTION_CHANGED)
727                 .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
728         mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
729     }
730 
sendNextBroadcast()731     private void sendNextBroadcast() {
732         final int powerState;
733         synchronized (mLock) {
734             if (mBroadcastedInteractiveState == INTERACTIVE_STATE_UNKNOWN) {
735                 // Broadcasted power state is unknown.
736                 // Send wake up or go to sleep.
737                 switch (mPendingInteractiveState) {
738                     case INTERACTIVE_STATE_ASLEEP:
739                         mPendingGoToSleepBroadcast = false;
740                         mBroadcastedInteractiveState = INTERACTIVE_STATE_ASLEEP;
741                         break;
742 
743                     case INTERACTIVE_STATE_AWAKE:
744                     default:
745                         mPendingWakeUpBroadcast = false;
746                         mBroadcastedInteractiveState = INTERACTIVE_STATE_AWAKE;
747                         break;
748                 }
749             } else if (mBroadcastedInteractiveState == INTERACTIVE_STATE_AWAKE) {
750                 // Broadcasted power state is awake.  Send asleep if needed.
751                 if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
752                         || mPendingInteractiveState == INTERACTIVE_STATE_ASLEEP) {
753                     mPendingGoToSleepBroadcast = false;
754                     mBroadcastedInteractiveState = INTERACTIVE_STATE_ASLEEP;
755                 } else {
756                     finishPendingBroadcastLocked();
757                     return;
758                 }
759             } else {
760                 // Broadcasted power state is asleep.  Send awake if needed.
761                 if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
762                         || mPendingInteractiveState == INTERACTIVE_STATE_AWAKE) {
763                     mPendingWakeUpBroadcast = false;
764                     mBroadcastedInteractiveState = INTERACTIVE_STATE_AWAKE;
765                 } else {
766                     finishPendingBroadcastLocked();
767                     return;
768                 }
769             }
770 
771             mBroadcastStartTime = SystemClock.uptimeMillis();
772             powerState = mBroadcastedInteractiveState;
773         }
774 
775         EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_SEND, 1);
776 
777         if (powerState == INTERACTIVE_STATE_AWAKE) {
778             sendWakeUpBroadcast();
779         } else {
780             sendGoToSleepBroadcast();
781         }
782     }
783 
sendWakeUpBroadcast()784     private void sendWakeUpBroadcast() {
785         if (DEBUG) {
786             Slog.d(TAG, "Sending wake up broadcast.");
787         }
788 
789         if (mActivityManagerInternal.isSystemReady()) {
790             mContext.sendOrderedBroadcastAsUser(mScreenOnIntent, UserHandle.ALL, null,
791                     mWakeUpBroadcastDone, mHandler, 0, null, null);
792         } else {
793             EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 2, 1);
794             sendNextBroadcast();
795         }
796     }
797 
798     private final BroadcastReceiver mWakeUpBroadcastDone = new BroadcastReceiver() {
799         @Override
800         public void onReceive(Context context, Intent intent) {
801             EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 1,
802                     SystemClock.uptimeMillis() - mBroadcastStartTime, 1);
803             sendNextBroadcast();
804         }
805     };
806 
sendGoToSleepBroadcast()807     private void sendGoToSleepBroadcast() {
808         if (DEBUG) {
809             Slog.d(TAG, "Sending go to sleep broadcast.");
810         }
811 
812         if (mActivityManagerInternal.isSystemReady()) {
813             mContext.sendOrderedBroadcastAsUser(mScreenOffIntent, UserHandle.ALL, null,
814                     mGoToSleepBroadcastDone, mHandler, 0, null, null);
815         } else {
816             EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 3, 1);
817             sendNextBroadcast();
818         }
819     }
820 
821     private final BroadcastReceiver mGoToSleepBroadcastDone = new BroadcastReceiver() {
822         @Override
823         public void onReceive(Context context, Intent intent) {
824             EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 0,
825                     SystemClock.uptimeMillis() - mBroadcastStartTime, 1);
826             sendNextBroadcast();
827         }
828     };
829 
playChargingStartedFeedback(@serIdInt int userId, boolean wireless)830     private void playChargingStartedFeedback(@UserIdInt int userId, boolean wireless) {
831         if (!isChargingFeedbackEnabled(userId)) {
832             return;
833         }
834 
835         if (!mIsPlayingChargingStartedFeedback.compareAndSet(false, true)) {
836             // there's already a charging started feedback Runnable scheduled to run on the
837             // background thread, so let's not execute another
838             return;
839         }
840 
841         // vibrate & play sound on a background thread
842         mBackgroundExecutor.execute(() -> {
843             // vibrate
844             final boolean vibrate = Settings.Secure.getIntForUser(mContext.getContentResolver(),
845                     Settings.Secure.CHARGING_VIBRATION_ENABLED, 1, userId) != 0;
846             if (vibrate) {
847                 mVibrator.vibrate(CHARGING_VIBRATION_EFFECT,
848                         HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES);
849             }
850 
851             // play sound
852             final String soundPath = Settings.Global.getString(mContext.getContentResolver(),
853                     wireless ? Settings.Global.WIRELESS_CHARGING_STARTED_SOUND
854                             : Settings.Global.CHARGING_STARTED_SOUND);
855             final Uri soundUri = Uri.parse("file://" + soundPath);
856             if (soundUri != null) {
857                 final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
858                 if (sfx != null) {
859                     sfx.setStreamType(AudioManager.STREAM_SYSTEM);
860                     sfx.play();
861                 }
862             }
863             mIsPlayingChargingStartedFeedback.set(false);
864         });
865     }
866 
showWirelessChargingStarted(int batteryLevel, @UserIdInt int userId)867     private void showWirelessChargingStarted(int batteryLevel, @UserIdInt int userId) {
868         // play sounds + haptics
869         playChargingStartedFeedback(userId, true /* wireless */);
870 
871         // show animation
872         if (mShowWirelessChargingAnimationConfig && mStatusBarManagerInternal != null) {
873             mStatusBarManagerInternal.showChargingAnimation(batteryLevel);
874         }
875         mSuspendBlocker.release();
876     }
877 
showWiredChargingStarted(@serIdInt int userId)878     private void showWiredChargingStarted(@UserIdInt int userId) {
879         playChargingStartedFeedback(userId, false /* wireless */);
880         mSuspendBlocker.release();
881     }
882 
screenPolicyChanging(int displayGroupId, int screenPolicy)883     private void screenPolicyChanging(int displayGroupId, int screenPolicy) {
884         mScreenUndimDetector.recordScreenPolicy(displayGroupId, screenPolicy);
885     }
886 
lockProfile(@serIdInt int userId)887     private void lockProfile(@UserIdInt int userId) {
888         mTrustManager.setDeviceLockedForUser(userId, true /*locked*/);
889     }
890 
isChargingFeedbackEnabled(@serIdInt int userId)891     private boolean isChargingFeedbackEnabled(@UserIdInt int userId) {
892         final boolean enabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
893                 Settings.Secure.CHARGING_SOUNDS_ENABLED, 1, userId) != 0;
894         final boolean dndOff = Settings.Global.getInt(mContext.getContentResolver(),
895                 Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS)
896                 == Settings.Global.ZEN_MODE_OFF;
897         return enabled && dndOff;
898     }
899 
notifyWakeLockListener(IWakeLockCallback callback, boolean isEnabled)900     private void notifyWakeLockListener(IWakeLockCallback callback, boolean isEnabled) {
901         if (callback != null) {
902             mHandler.post(() -> {
903                 try {
904                     callback.onStateChanged(isEnabled);
905                 } catch (RemoteException e) {
906                     throw new IllegalArgumentException("Wakelock.mCallback is already dead.", e);
907                 }
908             });
909         }
910     }
911 
912     private final class NotifierHandler extends Handler {
913 
NotifierHandler(Looper looper)914         public NotifierHandler(Looper looper) {
915             super(looper, null, true /*async*/);
916         }
917         @Override
handleMessage(Message msg)918         public void handleMessage(Message msg) {
919             switch (msg.what) {
920                 case MSG_USER_ACTIVITY:
921                     sendUserActivity(msg.arg1, msg.arg2);
922                     break;
923                 case MSG_BROADCAST:
924                     sendNextBroadcast();
925                     break;
926                 case MSG_WIRELESS_CHARGING_STARTED:
927                     showWirelessChargingStarted(msg.arg1, msg.arg2);
928                     break;
929                 case MSG_BROADCAST_ENHANCED_PREDICTION:
930                     removeMessages(MSG_BROADCAST_ENHANCED_PREDICTION);
931                     sendEnhancedDischargePredictionBroadcast();
932                     break;
933                 case MSG_PROFILE_TIMED_OUT:
934                     lockProfile(msg.arg1);
935                     break;
936                 case MSG_WIRED_CHARGING_STARTED:
937                     showWiredChargingStarted(msg.arg1);
938                     break;
939                 case MSG_SCREEN_POLICY:
940                     screenPolicyChanging(msg.arg1, msg.arg2);
941                     break;
942             }
943         }
944     }
945 }
946