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