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