• 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 com.android.internal.app.IBatteryStats;
20 import com.android.server.EventLogTags;
21 
22 import android.app.ActivityManagerNative;
23 import android.content.BroadcastReceiver;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.media.AudioManager;
27 import android.media.Ringtone;
28 import android.media.RingtoneManager;
29 import android.net.Uri;
30 import android.os.BatteryStats;
31 import android.os.Handler;
32 import android.os.Looper;
33 import android.os.Message;
34 import android.os.PowerManager;
35 import android.os.RemoteException;
36 import android.os.SystemClock;
37 import android.os.UserHandle;
38 import android.os.WorkSource;
39 import android.provider.Settings;
40 import android.util.EventLog;
41 import android.util.Slog;
42 import android.view.WindowManagerPolicy;
43 
44 /**
45  * Sends broadcasts about important power state changes.
46  * <p>
47  * This methods of this class may be called by the power manager service while
48  * its lock is being held.  Internally it takes care of sending broadcasts to
49  * notify other components of the system or applications asynchronously.
50  * </p><p>
51  * The notifier is designed to collapse unnecessary broadcasts when it is not
52  * possible for the system to have observed an intermediate state.
53  * </p><p>
54  * For example, if the device wakes up, goes to sleep, wakes up again and goes to
55  * sleep again before the wake up notification is sent, then the system will
56  * be told about only one wake up and sleep.  However, we always notify the
57  * fact that at least one transition occurred.  It is especially important to
58  * tell the system when we go to sleep so that it can lock the keyguard if needed.
59  * </p>
60  */
61 final class Notifier {
62     private static final String TAG = "PowerManagerNotifier";
63 
64     private static final boolean DEBUG = false;
65 
66     private static final int POWER_STATE_UNKNOWN = 0;
67     private static final int POWER_STATE_AWAKE = 1;
68     private static final int POWER_STATE_ASLEEP = 2;
69 
70     private static final int MSG_USER_ACTIVITY = 1;
71     private static final int MSG_BROADCAST = 2;
72     private static final int MSG_WIRELESS_CHARGING_STARTED = 3;
73 
74     private final Object mLock = new Object();
75 
76     private final Context mContext;
77     private final IBatteryStats mBatteryStats;
78     private final SuspendBlocker mSuspendBlocker;
79     private final ScreenOnBlocker mScreenOnBlocker;
80     private final WindowManagerPolicy mPolicy;
81 
82     private final NotifierHandler mHandler;
83     private final Intent mScreenOnIntent;
84     private final Intent mScreenOffIntent;
85 
86     // The current power state.
87     private int mActualPowerState;
88     private int mLastGoToSleepReason;
89 
90     // True if there is a pending transition that needs to be reported.
91     private boolean mPendingWakeUpBroadcast;
92     private boolean mPendingGoToSleepBroadcast;
93 
94     // The currently broadcasted power state.  This reflects what other parts of the
95     // system have observed.
96     private int mBroadcastedPowerState;
97     private boolean mBroadcastInProgress;
98     private long mBroadcastStartTime;
99 
100     // True if a user activity message should be sent.
101     private boolean mUserActivityPending;
102 
103     // True if the screen on blocker has been acquired.
104     private boolean mScreenOnBlockerAcquired;
105 
Notifier(Looper looper, Context context, IBatteryStats batteryStats, SuspendBlocker suspendBlocker, ScreenOnBlocker screenOnBlocker, WindowManagerPolicy policy)106     public Notifier(Looper looper, Context context, IBatteryStats batteryStats,
107             SuspendBlocker suspendBlocker, ScreenOnBlocker screenOnBlocker,
108             WindowManagerPolicy policy) {
109         mContext = context;
110         mBatteryStats = batteryStats;
111         mSuspendBlocker = suspendBlocker;
112         mScreenOnBlocker = screenOnBlocker;
113         mPolicy = policy;
114 
115         mHandler = new NotifierHandler(looper);
116         mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);
117         mScreenOnIntent.addFlags(
118                 Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
119         mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF);
120         mScreenOffIntent.addFlags(
121                 Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
122     }
123 
124     /**
125      * Called when a wake lock is acquired.
126      */
onWakeLockAcquired(int flags, String tag, int ownerUid, int ownerPid, WorkSource workSource)127     public void onWakeLockAcquired(int flags, String tag, int ownerUid, int ownerPid,
128             WorkSource workSource) {
129         if (DEBUG) {
130             Slog.d(TAG, "onWakeLockAcquired: flags=" + flags + ", tag=\"" + tag
131                     + "\", ownerUid=" + ownerUid + ", ownerPid=" + ownerPid
132                     + ", workSource=" + workSource);
133         }
134 
135         try {
136             final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
137             if (workSource != null) {
138                 mBatteryStats.noteStartWakelockFromSource(workSource, ownerPid, tag, monitorType);
139             } else {
140                 mBatteryStats.noteStartWakelock(ownerUid, ownerPid, tag, monitorType);
141             }
142         } catch (RemoteException ex) {
143             // Ignore
144         }
145     }
146 
147     /**
148      * Called when a wake lock is released.
149      */
onWakeLockReleased(int flags, String tag, int ownerUid, int ownerPid, WorkSource workSource)150     public void onWakeLockReleased(int flags, String tag, int ownerUid, int ownerPid,
151             WorkSource workSource) {
152         if (DEBUG) {
153             Slog.d(TAG, "onWakeLockReleased: flags=" + flags + ", tag=\"" + tag
154                     + "\", ownerUid=" + ownerUid + ", ownerPid=" + ownerPid
155                     + ", workSource=" + workSource);
156         }
157 
158         try {
159             final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
160             if (workSource != null) {
161                 mBatteryStats.noteStopWakelockFromSource(workSource, ownerPid, tag, monitorType);
162             } else {
163                 mBatteryStats.noteStopWakelock(ownerUid, ownerPid, tag, monitorType);
164             }
165         } catch (RemoteException ex) {
166             // Ignore
167         }
168     }
169 
getBatteryStatsWakeLockMonitorType(int flags)170     private static int getBatteryStatsWakeLockMonitorType(int flags) {
171         switch (flags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
172             case PowerManager.PARTIAL_WAKE_LOCK:
173             case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
174                 return BatteryStats.WAKE_TYPE_PARTIAL;
175             default:
176                 return BatteryStats.WAKE_TYPE_FULL;
177         }
178     }
179 
180     /**
181      * Called when the screen is turned on.
182      */
onScreenOn()183     public void onScreenOn() {
184         if (DEBUG) {
185             Slog.d(TAG, "onScreenOn");
186         }
187 
188         try {
189             mBatteryStats.noteScreenOn();
190         } catch (RemoteException ex) {
191             // Ignore
192         }
193     }
194 
195     /**
196      * Called when the screen is turned off.
197      */
onScreenOff()198     public void onScreenOff() {
199         if (DEBUG) {
200             Slog.d(TAG, "onScreenOff");
201         }
202 
203         try {
204             mBatteryStats.noteScreenOff();
205         } catch (RemoteException ex) {
206             // Ignore
207         }
208     }
209 
210     /**
211      * Called when the screen changes brightness.
212      */
onScreenBrightness(int brightness)213     public void onScreenBrightness(int brightness) {
214         if (DEBUG) {
215             Slog.d(TAG, "onScreenBrightness: brightness=" + brightness);
216         }
217 
218         try {
219             mBatteryStats.noteScreenBrightness(brightness);
220         } catch (RemoteException ex) {
221             // Ignore
222         }
223     }
224 
225     /**
226      * Called when the device is waking up from sleep and the
227      * display is about to be turned on.
228      */
onWakeUpStarted()229     public void onWakeUpStarted() {
230         if (DEBUG) {
231             Slog.d(TAG, "onWakeUpStarted");
232         }
233 
234         synchronized (mLock) {
235             if (mActualPowerState != POWER_STATE_AWAKE) {
236                 mActualPowerState = POWER_STATE_AWAKE;
237                 mPendingWakeUpBroadcast = true;
238                 if (!mScreenOnBlockerAcquired) {
239                     mScreenOnBlockerAcquired = true;
240                     mScreenOnBlocker.acquire();
241                 }
242                 updatePendingBroadcastLocked();
243             }
244         }
245     }
246 
247     /**
248      * Called when the device has finished waking up from sleep
249      * and the display has been turned on.
250      */
onWakeUpFinished()251     public void onWakeUpFinished() {
252         if (DEBUG) {
253             Slog.d(TAG, "onWakeUpFinished");
254         }
255     }
256 
257     /**
258      * Called when the device is going to sleep.
259      */
onGoToSleepStarted(int reason)260     public void onGoToSleepStarted(int reason) {
261         if (DEBUG) {
262             Slog.d(TAG, "onGoToSleepStarted");
263         }
264 
265         synchronized (mLock) {
266             mLastGoToSleepReason = reason;
267         }
268     }
269 
270     /**
271      * Called when the device has finished going to sleep and the
272      * display has been turned off.
273      *
274      * This is a good time to make transitions that we don't want the user to see,
275      * such as bringing the key guard to focus.  There's no guarantee for this,
276      * however because the user could turn the device on again at any time.
277      * Some things may need to be protected by other mechanisms that defer screen on.
278      */
onGoToSleepFinished()279     public void onGoToSleepFinished() {
280         if (DEBUG) {
281             Slog.d(TAG, "onGoToSleepFinished");
282         }
283 
284         synchronized (mLock) {
285             if (mActualPowerState != POWER_STATE_ASLEEP) {
286                 mActualPowerState = POWER_STATE_ASLEEP;
287                 mPendingGoToSleepBroadcast = true;
288                 if (mUserActivityPending) {
289                     mUserActivityPending = false;
290                     mHandler.removeMessages(MSG_USER_ACTIVITY);
291                 }
292                 updatePendingBroadcastLocked();
293             }
294         }
295     }
296 
297     /**
298      * Called when there has been user activity.
299      */
onUserActivity(int event, int uid)300     public void onUserActivity(int event, int uid) {
301         if (DEBUG) {
302             Slog.d(TAG, "onUserActivity: event=" + event + ", uid=" + uid);
303         }
304 
305         try {
306             mBatteryStats.noteUserActivity(uid, event);
307         } catch (RemoteException ex) {
308             // Ignore
309         }
310 
311         synchronized (mLock) {
312             if (!mUserActivityPending) {
313                 mUserActivityPending = true;
314                 Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY);
315                 msg.setAsynchronous(true);
316                 mHandler.sendMessage(msg);
317             }
318         }
319     }
320 
321     /**
322      * Called when wireless charging has started so as to provide user feedback.
323      */
onWirelessChargingStarted()324     public void onWirelessChargingStarted() {
325         if (DEBUG) {
326             Slog.d(TAG, "onWirelessChargingStarted");
327         }
328 
329         mSuspendBlocker.acquire();
330         Message msg = mHandler.obtainMessage(MSG_WIRELESS_CHARGING_STARTED);
331         msg.setAsynchronous(true);
332         mHandler.sendMessage(msg);
333     }
334 
updatePendingBroadcastLocked()335     private void updatePendingBroadcastLocked() {
336         if (!mBroadcastInProgress
337                 && mActualPowerState != POWER_STATE_UNKNOWN
338                 && (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
339                         || mActualPowerState != mBroadcastedPowerState)) {
340             mBroadcastInProgress = true;
341             mSuspendBlocker.acquire();
342             Message msg = mHandler.obtainMessage(MSG_BROADCAST);
343             msg.setAsynchronous(true);
344             mHandler.sendMessage(msg);
345         }
346     }
347 
finishPendingBroadcastLocked()348     private void finishPendingBroadcastLocked() {
349         mBroadcastInProgress = false;
350         mSuspendBlocker.release();
351     }
352 
sendUserActivity()353     private void sendUserActivity() {
354         synchronized (mLock) {
355             if (!mUserActivityPending) {
356                 return;
357             }
358             mUserActivityPending = false;
359         }
360 
361         mPolicy.userActivity();
362     }
363 
sendNextBroadcast()364     private void sendNextBroadcast() {
365         final int powerState;
366         final int goToSleepReason;
367         synchronized (mLock) {
368             if (mBroadcastedPowerState == POWER_STATE_UNKNOWN) {
369                 // Broadcasted power state is unknown.  Send wake up.
370                 mPendingWakeUpBroadcast = false;
371                 mBroadcastedPowerState = POWER_STATE_AWAKE;
372             } else if (mBroadcastedPowerState == POWER_STATE_AWAKE) {
373                 // Broadcasted power state is awake.  Send asleep if needed.
374                 if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
375                         || mActualPowerState == POWER_STATE_ASLEEP) {
376                     mPendingGoToSleepBroadcast = false;
377                     mBroadcastedPowerState = POWER_STATE_ASLEEP;
378                 } else {
379                     finishPendingBroadcastLocked();
380                     return;
381                 }
382             } else {
383                 // Broadcasted power state is asleep.  Send awake if needed.
384                 if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
385                         || mActualPowerState == POWER_STATE_AWAKE) {
386                     mPendingWakeUpBroadcast = false;
387                     mBroadcastedPowerState = POWER_STATE_AWAKE;
388                 } else {
389                     finishPendingBroadcastLocked();
390                     return;
391                 }
392             }
393 
394             mBroadcastStartTime = SystemClock.uptimeMillis();
395             powerState = mBroadcastedPowerState;
396             goToSleepReason = mLastGoToSleepReason;
397         }
398 
399         EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_SEND, 1);
400 
401         if (powerState == POWER_STATE_AWAKE) {
402             sendWakeUpBroadcast();
403         } else {
404             sendGoToSleepBroadcast(goToSleepReason);
405         }
406     }
407 
sendWakeUpBroadcast()408     private void sendWakeUpBroadcast() {
409         if (DEBUG) {
410             Slog.d(TAG, "Sending wake up broadcast.");
411         }
412 
413         EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, 0, 0, 0);
414 
415         mPolicy.screenTurningOn(mScreenOnListener);
416 
417         try {
418             ActivityManagerNative.getDefault().wakingUp();
419         } catch (RemoteException e) {
420             // ignore it
421         }
422 
423         if (ActivityManagerNative.isSystemReady()) {
424             mContext.sendOrderedBroadcastAsUser(mScreenOnIntent, UserHandle.ALL, null,
425                     mWakeUpBroadcastDone, mHandler, 0, null, null);
426         } else {
427             EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 2, 1);
428             sendNextBroadcast();
429         }
430     }
431 
432     private final WindowManagerPolicy.ScreenOnListener mScreenOnListener =
433             new WindowManagerPolicy.ScreenOnListener() {
434         @Override
435         public void onScreenOn() {
436             synchronized (mLock) {
437                 if (mScreenOnBlockerAcquired && !mPendingWakeUpBroadcast) {
438                     mScreenOnBlockerAcquired = false;
439                     mScreenOnBlocker.release();
440                 }
441             }
442         }
443     };
444 
445     private final BroadcastReceiver mWakeUpBroadcastDone = new BroadcastReceiver() {
446         @Override
447         public void onReceive(Context context, Intent intent) {
448             EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 1,
449                     SystemClock.uptimeMillis() - mBroadcastStartTime, 1);
450             sendNextBroadcast();
451         }
452     };
453 
sendGoToSleepBroadcast(int reason)454     private void sendGoToSleepBroadcast(int reason) {
455         if (DEBUG) {
456             Slog.d(TAG, "Sending go to sleep broadcast.");
457         }
458 
459         int why = WindowManagerPolicy.OFF_BECAUSE_OF_USER;
460         switch (reason) {
461             case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN:
462                 why = WindowManagerPolicy.OFF_BECAUSE_OF_ADMIN;
463                 break;
464             case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT:
465                 why = WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT;
466                 break;
467         }
468 
469         EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0, why, 0, 0);
470 
471         mPolicy.screenTurnedOff(why);
472         try {
473             ActivityManagerNative.getDefault().goingToSleep();
474         } catch (RemoteException e) {
475             // ignore it.
476         }
477 
478         if (ActivityManagerNative.isSystemReady()) {
479             mContext.sendOrderedBroadcastAsUser(mScreenOffIntent, UserHandle.ALL, null,
480                     mGoToSleepBroadcastDone, mHandler, 0, null, null);
481         } else {
482             EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 3, 1);
483             sendNextBroadcast();
484         }
485     }
486 
487     private final BroadcastReceiver mGoToSleepBroadcastDone = new BroadcastReceiver() {
488         @Override
489         public void onReceive(Context context, Intent intent) {
490             EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 0,
491                     SystemClock.uptimeMillis() - mBroadcastStartTime, 1);
492             sendNextBroadcast();
493         }
494     };
495 
playWirelessChargingStartedSound()496     private void playWirelessChargingStartedSound() {
497         final String soundPath = Settings.Global.getString(mContext.getContentResolver(),
498                 Settings.Global.WIRELESS_CHARGING_STARTED_SOUND);
499         if (soundPath != null) {
500             final Uri soundUri = Uri.parse("file://" + soundPath);
501             if (soundUri != null) {
502                 final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
503                 if (sfx != null) {
504                     sfx.setStreamType(AudioManager.STREAM_SYSTEM);
505                     sfx.play();
506                 }
507             }
508         }
509 
510         mSuspendBlocker.release();
511     }
512 
513     private final class NotifierHandler extends Handler {
NotifierHandler(Looper looper)514         public NotifierHandler(Looper looper) {
515             super(looper, null, true /*async*/);
516         }
517 
518         @Override
handleMessage(Message msg)519         public void handleMessage(Message msg) {
520             switch (msg.what) {
521                 case MSG_USER_ACTIVITY:
522                     sendUserActivity();
523                     break;
524 
525                 case MSG_BROADCAST:
526                     sendNextBroadcast();
527                     break;
528 
529                 case MSG_WIRELESS_CHARGING_STARTED:
530                     playWirelessChargingStartedSound();
531                     break;
532             }
533         }
534     }
535 }
536