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.app.ActivityManagerInternal;
20 import android.app.AppOpsManager;
21 
22 import com.android.internal.app.IAppOpsService;
23 import com.android.internal.app.IBatteryStats;
24 import com.android.server.EventLogTags;
25 import com.android.server.LocalServices;
26 
27 import android.app.ActivityManagerNative;
28 import android.content.BroadcastReceiver;
29 import android.content.Context;
30 import android.content.Intent;
31 import android.hardware.input.InputManagerInternal;
32 import android.media.AudioManager;
33 import android.media.Ringtone;
34 import android.media.RingtoneManager;
35 import android.net.Uri;
36 import android.os.BatteryStats;
37 import android.os.Handler;
38 import android.os.Looper;
39 import android.os.Message;
40 import android.os.PowerManager;
41 import android.os.PowerManagerInternal;
42 import android.os.Process;
43 import android.os.RemoteException;
44 import android.os.SystemClock;
45 import android.os.UserHandle;
46 import android.os.WorkSource;
47 import android.provider.Settings;
48 import android.util.EventLog;
49 import android.util.Slog;
50 import android.view.WindowManagerPolicy;
51 import android.view.inputmethod.InputMethodManagerInternal;
52 
53 /**
54  * Sends broadcasts about important power state changes.
55  * <p>
56  * This methods of this class may be called by the power manager service while
57  * its lock is being held.  Internally it takes care of sending broadcasts to
58  * notify other components of the system or applications asynchronously.
59  * </p><p>
60  * The notifier is designed to collapse unnecessary broadcasts when it is not
61  * possible for the system to have observed an intermediate state.
62  * </p><p>
63  * For example, if the device wakes up, goes to sleep, wakes up again and goes to
64  * sleep again before the wake up notification is sent, then the system will
65  * be told about only one wake up and sleep.  However, we always notify the
66  * fact that at least one transition occurred.  It is especially important to
67  * tell the system when we go to sleep so that it can lock the keyguard if needed.
68  * </p>
69  */
70 final class Notifier {
71     private static final String TAG = "PowerManagerNotifier";
72 
73     private static final boolean DEBUG = false;
74 
75     private static final int INTERACTIVE_STATE_UNKNOWN = 0;
76     private static final int INTERACTIVE_STATE_AWAKE = 1;
77     private static final int INTERACTIVE_STATE_ASLEEP = 2;
78 
79     private static final int MSG_USER_ACTIVITY = 1;
80     private static final int MSG_BROADCAST = 2;
81     private static final int MSG_WIRELESS_CHARGING_STARTED = 3;
82     private static final int MSG_SCREEN_BRIGHTNESS_BOOST_CHANGED = 4;
83 
84     private final Object mLock = new Object();
85 
86     private final Context mContext;
87     private final IBatteryStats mBatteryStats;
88     private final IAppOpsService mAppOps;
89     private final SuspendBlocker mSuspendBlocker;
90     private final WindowManagerPolicy mPolicy;
91     private final ActivityManagerInternal mActivityManagerInternal;
92     private final InputManagerInternal mInputManagerInternal;
93     private final InputMethodManagerInternal mInputMethodManagerInternal;
94 
95     private final NotifierHandler mHandler;
96     private final Intent mScreenOnIntent;
97     private final Intent mScreenOffIntent;
98     private final Intent mScreenBrightnessBoostIntent;
99 
100     // True if the device should suspend when the screen is off due to proximity.
101     private final boolean mSuspendWhenScreenOffDueToProximityConfig;
102 
103     // The current interactive state.  This is set as soon as an interactive state
104     // transition begins so as to capture the reason that it happened.  At some point
105     // this state will propagate to the pending state then eventually to the
106     // broadcasted state over the course of reporting the transition asynchronously.
107     private boolean mInteractive = true;
108     private int mInteractiveChangeReason;
109     private boolean mInteractiveChanging;
110 
111     // The pending interactive state that we will eventually want to broadcast.
112     // This is designed so that we can collapse redundant sequences of awake/sleep
113     // transition pairs while still guaranteeing that at least one transition is observed
114     // whenever this happens.
115     private int mPendingInteractiveState;
116     private boolean mPendingWakeUpBroadcast;
117     private boolean mPendingGoToSleepBroadcast;
118 
119     // The currently broadcasted interactive state.  This reflects what other parts of the
120     // system have observed.
121     private int mBroadcastedInteractiveState;
122     private boolean mBroadcastInProgress;
123     private long mBroadcastStartTime;
124 
125     // True if a user activity message should be sent.
126     private boolean mUserActivityPending;
127 
Notifier(Looper looper, Context context, IBatteryStats batteryStats, IAppOpsService appOps, SuspendBlocker suspendBlocker, WindowManagerPolicy policy)128     public Notifier(Looper looper, Context context, IBatteryStats batteryStats,
129             IAppOpsService appOps, SuspendBlocker suspendBlocker,
130             WindowManagerPolicy policy) {
131         mContext = context;
132         mBatteryStats = batteryStats;
133         mAppOps = appOps;
134         mSuspendBlocker = suspendBlocker;
135         mPolicy = policy;
136         mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
137         mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
138         mInputMethodManagerInternal = LocalServices.getService(InputMethodManagerInternal.class);
139 
140         mHandler = new NotifierHandler(looper);
141         mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);
142         mScreenOnIntent.addFlags(
143                 Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
144         mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF);
145         mScreenOffIntent.addFlags(
146                 Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
147         mScreenBrightnessBoostIntent =
148                 new Intent(PowerManager.ACTION_SCREEN_BRIGHTNESS_BOOST_CHANGED);
149         mScreenBrightnessBoostIntent.addFlags(
150                 Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
151 
152         mSuspendWhenScreenOffDueToProximityConfig = context.getResources().getBoolean(
153                 com.android.internal.R.bool.config_suspendWhenScreenOffDueToProximity);
154 
155         // Initialize interactive state for battery stats.
156         try {
157             mBatteryStats.noteInteractive(true);
158         } catch (RemoteException ex) { }
159     }
160 
161     /**
162      * Called when a wake lock is acquired.
163      */
onWakeLockAcquired(int flags, String tag, String packageName, int ownerUid, int ownerPid, WorkSource workSource, String historyTag)164     public void onWakeLockAcquired(int flags, String tag, String packageName,
165             int ownerUid, int ownerPid, WorkSource workSource, String historyTag) {
166         if (DEBUG) {
167             Slog.d(TAG, "onWakeLockAcquired: flags=" + flags + ", tag=\"" + tag
168                     + "\", packageName=" + packageName
169                     + ", ownerUid=" + ownerUid + ", ownerPid=" + ownerPid
170                     + ", workSource=" + workSource);
171         }
172 
173         final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
174         if (monitorType >= 0) {
175             try {
176                 final boolean unimportantForLogging = ownerUid == Process.SYSTEM_UID
177                         && (flags & PowerManager.UNIMPORTANT_FOR_LOGGING) != 0;
178                 if (workSource != null) {
179                     mBatteryStats.noteStartWakelockFromSource(workSource, ownerPid, tag,
180                             historyTag, monitorType, unimportantForLogging);
181                 } else {
182                     mBatteryStats.noteStartWakelock(ownerUid, ownerPid, tag, historyTag,
183                             monitorType, unimportantForLogging);
184                     // XXX need to deal with disabled operations.
185                     mAppOps.startOperation(AppOpsManager.getToken(mAppOps),
186                             AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName);
187                 }
188             } catch (RemoteException ex) {
189                 // Ignore
190             }
191         }
192     }
193 
194     /**
195      * Called when a wake lock is changing.
196      */
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)197     public void onWakeLockChanging(int flags, String tag, String packageName,
198             int ownerUid, int ownerPid, WorkSource workSource, String historyTag,
199             int newFlags, String newTag, String newPackageName, int newOwnerUid,
200             int newOwnerPid, WorkSource newWorkSource, String newHistoryTag) {
201 
202         final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
203         final int newMonitorType = getBatteryStatsWakeLockMonitorType(newFlags);
204         if (workSource != null && newWorkSource != null
205                 && monitorType >= 0 && newMonitorType >= 0) {
206             if (DEBUG) {
207                 Slog.d(TAG, "onWakeLockChanging: flags=" + newFlags + ", tag=\"" + newTag
208                         + "\", packageName=" + newPackageName
209                         + ", ownerUid=" + newOwnerUid + ", ownerPid=" + newOwnerPid
210                         + ", workSource=" + newWorkSource);
211             }
212 
213             final boolean unimportantForLogging = newOwnerUid == Process.SYSTEM_UID
214                     && (newFlags & PowerManager.UNIMPORTANT_FOR_LOGGING) != 0;
215             try {
216                 mBatteryStats.noteChangeWakelockFromSource(workSource, ownerPid, tag, historyTag,
217                         monitorType, newWorkSource, newOwnerPid, newTag, newHistoryTag,
218                         newMonitorType, unimportantForLogging);
219             } catch (RemoteException ex) {
220                 // Ignore
221             }
222         } else {
223             onWakeLockReleased(flags, tag, packageName, ownerUid, ownerPid, workSource, historyTag);
224             onWakeLockAcquired(newFlags, newTag, newPackageName, newOwnerUid, newOwnerPid,
225                     newWorkSource, newHistoryTag);
226         }
227     }
228 
229     /**
230      * Called when a wake lock is released.
231      */
onWakeLockReleased(int flags, String tag, String packageName, int ownerUid, int ownerPid, WorkSource workSource, String historyTag)232     public void onWakeLockReleased(int flags, String tag, String packageName,
233             int ownerUid, int ownerPid, WorkSource workSource, String historyTag) {
234         if (DEBUG) {
235             Slog.d(TAG, "onWakeLockReleased: flags=" + flags + ", tag=\"" + tag
236                     + "\", packageName=" + packageName
237                     + ", ownerUid=" + ownerUid + ", ownerPid=" + ownerPid
238                     + ", workSource=" + workSource);
239         }
240 
241         final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
242         if (monitorType >= 0) {
243             try {
244                 if (workSource != null) {
245                     mBatteryStats.noteStopWakelockFromSource(workSource, ownerPid, tag,
246                             historyTag, monitorType);
247                 } else {
248                     mBatteryStats.noteStopWakelock(ownerUid, ownerPid, tag,
249                             historyTag, monitorType);
250                     mAppOps.finishOperation(AppOpsManager.getToken(mAppOps),
251                             AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName);
252                 }
253             } catch (RemoteException ex) {
254                 // Ignore
255             }
256         }
257     }
258 
getBatteryStatsWakeLockMonitorType(int flags)259     private int getBatteryStatsWakeLockMonitorType(int flags) {
260         switch (flags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
261             case PowerManager.PARTIAL_WAKE_LOCK:
262                 return BatteryStats.WAKE_TYPE_PARTIAL;
263 
264             case PowerManager.SCREEN_DIM_WAKE_LOCK:
265             case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
266                 return BatteryStats.WAKE_TYPE_FULL;
267 
268             case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
269                 if (mSuspendWhenScreenOffDueToProximityConfig) {
270                     return -1;
271                 }
272                 return BatteryStats.WAKE_TYPE_PARTIAL;
273 
274             case PowerManager.DRAW_WAKE_LOCK:
275                 return BatteryStats.WAKE_TYPE_DRAW;
276 
277             case PowerManager.DOZE_WAKE_LOCK:
278                 // Doze wake locks are an internal implementation detail of the
279                 // communication between dream manager service and power manager
280                 // service.  They have no additive battery impact.
281                 return -1;
282 
283             default:
284                 return -1;
285         }
286     }
287 
288     /**
289      * Notifies that the device is changing wakefulness.
290      * This function may be called even if the previous change hasn't finished in
291      * which case it will assume that the state did not fully converge before the
292      * next transition began and will recover accordingly.
293      */
onWakefulnessChangeStarted(final int wakefulness, int reason)294     public void onWakefulnessChangeStarted(final int wakefulness, int reason) {
295         final boolean interactive = PowerManagerInternal.isInteractive(wakefulness);
296         if (DEBUG) {
297             Slog.d(TAG, "onWakefulnessChangeStarted: wakefulness=" + wakefulness
298                     + ", reason=" + reason + ", interactive=" + interactive);
299         }
300 
301         // Tell the activity manager about changes in wakefulness, not just interactivity.
302         // It needs more granularity than other components.
303         mHandler.post(new Runnable() {
304             @Override
305             public void run() {
306                 mActivityManagerInternal.onWakefulnessChanged(wakefulness);
307             }
308         });
309 
310         // Handle any early interactive state changes.
311         // Finish pending incomplete ones from a previous cycle.
312         if (mInteractive != interactive) {
313             // Finish up late behaviors if needed.
314             if (mInteractiveChanging) {
315                 handleLateInteractiveChange();
316             }
317 
318             // Start input as soon as we start waking up or going to sleep.
319             mInputManagerInternal.setInteractive(interactive);
320             mInputMethodManagerInternal.setInteractive(interactive);
321 
322             // Notify battery stats.
323             try {
324                 mBatteryStats.noteInteractive(interactive);
325             } catch (RemoteException ex) { }
326 
327             // Handle early behaviors.
328             mInteractive = interactive;
329             mInteractiveChangeReason = reason;
330             mInteractiveChanging = true;
331             handleEarlyInteractiveChange();
332         }
333     }
334 
335     /**
336      * Notifies that the device has finished changing wakefulness.
337      */
onWakefulnessChangeFinished()338     public void onWakefulnessChangeFinished() {
339         if (DEBUG) {
340             Slog.d(TAG, "onWakefulnessChangeFinished");
341         }
342 
343         if (mInteractiveChanging) {
344             mInteractiveChanging = false;
345             handleLateInteractiveChange();
346         }
347     }
348 
349     /**
350      * Handle early interactive state changes such as getting applications or the lock
351      * screen running and ready for the user to see (such as when turning on the screen).
352      */
handleEarlyInteractiveChange()353     private void handleEarlyInteractiveChange() {
354         synchronized (mLock) {
355             if (mInteractive) {
356                 // Waking up...
357                 mHandler.post(new Runnable() {
358                     @Override
359                     public void run() {
360                         EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, 0, 0, 0);
361                         mPolicy.startedWakingUp();
362                     }
363                 });
364 
365                 // Send interactive broadcast.
366                 mPendingInteractiveState = INTERACTIVE_STATE_AWAKE;
367                 mPendingWakeUpBroadcast = true;
368                 updatePendingBroadcastLocked();
369             } else {
370                 // Going to sleep...
371                 // Tell the policy that we started going to sleep.
372                 final int why = translateOffReason(mInteractiveChangeReason);
373                 mHandler.post(new Runnable() {
374                     @Override
375                     public void run() {
376                         mPolicy.startedGoingToSleep(why);
377                     }
378                 });
379             }
380         }
381     }
382 
383     /**
384      * Handle late interactive state changes once they are finished so that the system can
385      * finish pending transitions (such as turning the screen off) before causing
386      * applications to change state visibly.
387      */
handleLateInteractiveChange()388     private void handleLateInteractiveChange() {
389         synchronized (mLock) {
390             if (mInteractive) {
391                 // Finished waking up...
392                 mHandler.post(new Runnable() {
393                     @Override
394                     public void run() {
395                         mPolicy.finishedWakingUp();
396                     }
397                 });
398             } else {
399                 // Finished going to sleep...
400                 // This is a good time to make transitions that we don't want the user to see,
401                 // such as bringing the key guard to focus.  There's no guarantee for this
402                 // however because the user could turn the device on again at any time.
403                 // Some things may need to be protected by other mechanisms that defer screen on.
404 
405                 // Cancel pending user activity.
406                 if (mUserActivityPending) {
407                     mUserActivityPending = false;
408                     mHandler.removeMessages(MSG_USER_ACTIVITY);
409                 }
410 
411                 // Tell the policy we finished going to sleep.
412                 final int why = translateOffReason(mInteractiveChangeReason);
413                 mHandler.post(new Runnable() {
414                     @Override
415                     public void run() {
416                         EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0, why, 0, 0);
417                         mPolicy.finishedGoingToSleep(why);
418                     }
419                 });
420 
421                 // Send non-interactive broadcast.
422                 mPendingInteractiveState = INTERACTIVE_STATE_ASLEEP;
423                 mPendingGoToSleepBroadcast = true;
424                 updatePendingBroadcastLocked();
425             }
426         }
427     }
428 
translateOffReason(int reason)429     private static int translateOffReason(int reason) {
430         switch (reason) {
431             case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN:
432                 return WindowManagerPolicy.OFF_BECAUSE_OF_ADMIN;
433             case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT:
434                 return WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT;
435             default:
436                 return WindowManagerPolicy.OFF_BECAUSE_OF_USER;
437         }
438     }
439 
440     /**
441      * Called when screen brightness boost begins or ends.
442      */
onScreenBrightnessBoostChanged()443     public void onScreenBrightnessBoostChanged() {
444         if (DEBUG) {
445             Slog.d(TAG, "onScreenBrightnessBoostChanged");
446         }
447 
448         mSuspendBlocker.acquire();
449         Message msg = mHandler.obtainMessage(MSG_SCREEN_BRIGHTNESS_BOOST_CHANGED);
450         msg.setAsynchronous(true);
451         mHandler.sendMessage(msg);
452     }
453 
454     /**
455      * Called when there has been user activity.
456      */
onUserActivity(int event, int uid)457     public void onUserActivity(int event, int uid) {
458         if (DEBUG) {
459             Slog.d(TAG, "onUserActivity: event=" + event + ", uid=" + uid);
460         }
461 
462         try {
463             mBatteryStats.noteUserActivity(uid, event);
464         } catch (RemoteException ex) {
465             // Ignore
466         }
467 
468         synchronized (mLock) {
469             if (!mUserActivityPending) {
470                 mUserActivityPending = true;
471                 Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY);
472                 msg.setAsynchronous(true);
473                 mHandler.sendMessage(msg);
474             }
475         }
476     }
477 
478     /**
479      * Called when the screen has turned on.
480      */
onWakeUp(String reason, int reasonUid, String opPackageName, int opUid)481     public void onWakeUp(String reason, int reasonUid, String opPackageName, int opUid) {
482         if (DEBUG) {
483             Slog.d(TAG, "onWakeUp: event=" + reason + ", reasonUid=" + reasonUid
484                     + " opPackageName=" + opPackageName + " opUid=" + opUid);
485         }
486 
487         try {
488             mBatteryStats.noteWakeUp(reason, reasonUid);
489             if (opPackageName != null) {
490                 mAppOps.noteOperation(AppOpsManager.OP_TURN_SCREEN_ON, opUid, opPackageName);
491             }
492         } catch (RemoteException ex) {
493             // Ignore
494         }
495 
496     }
497 
498     /**
499      * Called when wireless charging has started so as to provide user feedback.
500      */
onWirelessChargingStarted()501     public void onWirelessChargingStarted() {
502         if (DEBUG) {
503             Slog.d(TAG, "onWirelessChargingStarted");
504         }
505 
506         mSuspendBlocker.acquire();
507         Message msg = mHandler.obtainMessage(MSG_WIRELESS_CHARGING_STARTED);
508         msg.setAsynchronous(true);
509         mHandler.sendMessage(msg);
510     }
511 
updatePendingBroadcastLocked()512     private void updatePendingBroadcastLocked() {
513         if (!mBroadcastInProgress
514                 && mPendingInteractiveState != INTERACTIVE_STATE_UNKNOWN
515                 && (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
516                         || mPendingInteractiveState != mBroadcastedInteractiveState)) {
517             mBroadcastInProgress = true;
518             mSuspendBlocker.acquire();
519             Message msg = mHandler.obtainMessage(MSG_BROADCAST);
520             msg.setAsynchronous(true);
521             mHandler.sendMessage(msg);
522         }
523     }
524 
finishPendingBroadcastLocked()525     private void finishPendingBroadcastLocked() {
526         mBroadcastInProgress = false;
527         mSuspendBlocker.release();
528     }
529 
sendUserActivity()530     private void sendUserActivity() {
531         synchronized (mLock) {
532             if (!mUserActivityPending) {
533                 return;
534             }
535             mUserActivityPending = false;
536         }
537 
538         mPolicy.userActivity();
539     }
540 
sendNextBroadcast()541     private void sendNextBroadcast() {
542         final int powerState;
543         synchronized (mLock) {
544             if (mBroadcastedInteractiveState == INTERACTIVE_STATE_UNKNOWN) {
545                 // Broadcasted power state is unknown.  Send wake up.
546                 mPendingWakeUpBroadcast = false;
547                 mBroadcastedInteractiveState = INTERACTIVE_STATE_AWAKE;
548             } else if (mBroadcastedInteractiveState == INTERACTIVE_STATE_AWAKE) {
549                 // Broadcasted power state is awake.  Send asleep if needed.
550                 if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
551                         || mPendingInteractiveState == INTERACTIVE_STATE_ASLEEP) {
552                     mPendingGoToSleepBroadcast = false;
553                     mBroadcastedInteractiveState = INTERACTIVE_STATE_ASLEEP;
554                 } else {
555                     finishPendingBroadcastLocked();
556                     return;
557                 }
558             } else {
559                 // Broadcasted power state is asleep.  Send awake if needed.
560                 if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
561                         || mPendingInteractiveState == INTERACTIVE_STATE_AWAKE) {
562                     mPendingWakeUpBroadcast = false;
563                     mBroadcastedInteractiveState = INTERACTIVE_STATE_AWAKE;
564                 } else {
565                     finishPendingBroadcastLocked();
566                     return;
567                 }
568             }
569 
570             mBroadcastStartTime = SystemClock.uptimeMillis();
571             powerState = mBroadcastedInteractiveState;
572         }
573 
574         EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_SEND, 1);
575 
576         if (powerState == INTERACTIVE_STATE_AWAKE) {
577             sendWakeUpBroadcast();
578         } else {
579             sendGoToSleepBroadcast();
580         }
581     }
582 
sendBrightnessBoostChangedBroadcast()583     private void sendBrightnessBoostChangedBroadcast() {
584         if (DEBUG) {
585             Slog.d(TAG, "Sending brightness boost changed broadcast.");
586         }
587 
588         mContext.sendOrderedBroadcastAsUser(mScreenBrightnessBoostIntent, UserHandle.ALL, null,
589                 mScreeBrightnessBoostChangedDone, mHandler, 0, null, null);
590     }
591 
592     private final BroadcastReceiver mScreeBrightnessBoostChangedDone = new BroadcastReceiver() {
593         @Override
594         public void onReceive(Context context, Intent intent) {
595             mSuspendBlocker.release();
596         }
597     };
598 
sendWakeUpBroadcast()599     private void sendWakeUpBroadcast() {
600         if (DEBUG) {
601             Slog.d(TAG, "Sending wake up broadcast.");
602         }
603 
604         if (ActivityManagerNative.isSystemReady()) {
605             mContext.sendOrderedBroadcastAsUser(mScreenOnIntent, UserHandle.ALL, null,
606                     mWakeUpBroadcastDone, mHandler, 0, null, null);
607         } else {
608             EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 2, 1);
609             sendNextBroadcast();
610         }
611     }
612 
613     private final BroadcastReceiver mWakeUpBroadcastDone = new BroadcastReceiver() {
614         @Override
615         public void onReceive(Context context, Intent intent) {
616             EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 1,
617                     SystemClock.uptimeMillis() - mBroadcastStartTime, 1);
618             sendNextBroadcast();
619         }
620     };
621 
sendGoToSleepBroadcast()622     private void sendGoToSleepBroadcast() {
623         if (DEBUG) {
624             Slog.d(TAG, "Sending go to sleep broadcast.");
625         }
626 
627         if (ActivityManagerNative.isSystemReady()) {
628             mContext.sendOrderedBroadcastAsUser(mScreenOffIntent, UserHandle.ALL, null,
629                     mGoToSleepBroadcastDone, mHandler, 0, null, null);
630         } else {
631             EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 3, 1);
632             sendNextBroadcast();
633         }
634     }
635 
636     private final BroadcastReceiver mGoToSleepBroadcastDone = new BroadcastReceiver() {
637         @Override
638         public void onReceive(Context context, Intent intent) {
639             EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 0,
640                     SystemClock.uptimeMillis() - mBroadcastStartTime, 1);
641             sendNextBroadcast();
642         }
643     };
644 
playWirelessChargingStartedSound()645     private void playWirelessChargingStartedSound() {
646         final boolean enabled = Settings.Global.getInt(mContext.getContentResolver(),
647                 Settings.Global.CHARGING_SOUNDS_ENABLED, 1) != 0;
648         final String soundPath = Settings.Global.getString(mContext.getContentResolver(),
649                 Settings.Global.WIRELESS_CHARGING_STARTED_SOUND);
650         if (enabled && soundPath != null) {
651             final Uri soundUri = Uri.parse("file://" + soundPath);
652             if (soundUri != null) {
653                 final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
654                 if (sfx != null) {
655                     sfx.setStreamType(AudioManager.STREAM_SYSTEM);
656                     sfx.play();
657                 }
658             }
659         }
660 
661         mSuspendBlocker.release();
662     }
663 
664     private final class NotifierHandler extends Handler {
NotifierHandler(Looper looper)665         public NotifierHandler(Looper looper) {
666             super(looper, null, true /*async*/);
667         }
668 
669         @Override
handleMessage(Message msg)670         public void handleMessage(Message msg) {
671             switch (msg.what) {
672                 case MSG_USER_ACTIVITY:
673                     sendUserActivity();
674                     break;
675 
676                 case MSG_BROADCAST:
677                     sendNextBroadcast();
678                     break;
679 
680                 case MSG_WIRELESS_CHARGING_STARTED:
681                     playWirelessChargingStartedSound();
682                     break;
683                 case MSG_SCREEN_BRIGHTNESS_BOOST_CHANGED:
684                     sendBrightnessBoostChangedBroadcast();
685                     break;
686             }
687         }
688     }
689 }
690