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