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