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