OSDN Git Service

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