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