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