blob: 09be3a8c2aae1e897f1b0853239c5b6a401bf3b4 [file] [log] [blame]
Jeff Brown96307042012-07-27 15:51:34 -07001/*
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
Dianne Hackborn713df152013-05-17 11:27:57 -070019import android.app.AppOpsManager;
20import com.android.internal.app.IAppOpsService;
Jeff Brown96307042012-07-27 15:51:34 -070021import 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;
Jeff Brown84e27562012-12-07 13:56:34 -080028import android.media.AudioManager;
29import android.media.Ringtone;
30import android.media.RingtoneManager;
31import android.net.Uri;
Jeff Brown96307042012-07-27 15:51:34 -070032import android.os.BatteryStats;
33import android.os.Handler;
34import android.os.Looper;
35import android.os.Message;
36import android.os.PowerManager;
Dianne Hackborn3d658bf2014-02-05 13:38:56 -080037import android.os.Process;
Jeff Brown96307042012-07-27 15:51:34 -070038import android.os.RemoteException;
39import android.os.SystemClock;
Dianne Hackborn5ac72a22012-08-29 18:32:08 -070040import android.os.UserHandle;
Jeff Brown96307042012-07-27 15:51:34 -070041import android.os.WorkSource;
Jeff Brown84e27562012-12-07 13:56:34 -080042import android.provider.Settings;
Jeff Brown96307042012-07-27 15:51:34 -070043import android.util.EventLog;
44import android.util.Slog;
45import android.view.WindowManagerPolicy;
Jeff Brown96307042012-07-27 15:51:34 -070046
47/**
48 * Sends broadcasts about important power state changes.
Jeff Brown54308352012-10-04 17:59:58 -070049 * <p>
Jeff Brown96307042012-07-27 15:51:34 -070050 * 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.
Jeff Brown54308352012-10-04 17:59:58 -070053 * </p><p>
Jeff Brown96307042012-07-27 15:51:34 -070054 * The notifier is designed to collapse unnecessary broadcasts when it is not
55 * possible for the system to have observed an intermediate state.
Jeff Brown54308352012-10-04 17:59:58 -070056 * </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>
Jeff Brown96307042012-07-27 15:51:34 -070063 */
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;
Jeff Brown84e27562012-12-07 13:56:34 -080075 private static final int MSG_WIRELESS_CHARGING_STARTED = 3;
Jeff Brown96307042012-07-27 15:51:34 -070076
77 private final Object mLock = new Object();
78
79 private final Context mContext;
80 private final IBatteryStats mBatteryStats;
Dianne Hackborn713df152013-05-17 11:27:57 -070081 private final IAppOpsService mAppOps;
Jeff Brown96307042012-07-27 15:51:34 -070082 private final SuspendBlocker mSuspendBlocker;
Jeff Brownc38c9be2012-10-04 13:16:19 -070083 private final ScreenOnBlocker mScreenOnBlocker;
Jeff Brown96307042012-07-27 15:51:34 -070084 private final WindowManagerPolicy mPolicy;
Jeff Brown96307042012-07-27 15:51:34 -070085
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
Jeff Brown54308352012-10-04 17:59:58 -070094 // True if there is a pending transition that needs to be reported.
95 private boolean mPendingWakeUpBroadcast;
96 private boolean mPendingGoToSleepBroadcast;
97
Jeff Brown96307042012-07-27 15:51:34 -070098 // 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
Jeff Brownc38c9be2012-10-04 13:16:19 -0700107 // True if the screen on blocker has been acquired.
108 private boolean mScreenOnBlockerAcquired;
109
Jeff Brown96307042012-07-27 15:51:34 -0700110 public Notifier(Looper looper, Context context, IBatteryStats batteryStats,
Dianne Hackborn713df152013-05-17 11:27:57 -0700111 IAppOpsService appOps, SuspendBlocker suspendBlocker, ScreenOnBlocker screenOnBlocker,
Jeff Brownc38c9be2012-10-04 13:16:19 -0700112 WindowManagerPolicy policy) {
Jeff Brown96307042012-07-27 15:51:34 -0700113 mContext = context;
114 mBatteryStats = batteryStats;
Dianne Hackborn713df152013-05-17 11:27:57 -0700115 mAppOps = appOps;
Jeff Brown96307042012-07-27 15:51:34 -0700116 mSuspendBlocker = suspendBlocker;
Jeff Brownc38c9be2012-10-04 13:16:19 -0700117 mScreenOnBlocker = screenOnBlocker;
Jeff Brown96307042012-07-27 15:51:34 -0700118 mPolicy = policy;
Jeff Brown96307042012-07-27 15:51:34 -0700119
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 */
Dianne Hackborn713df152013-05-17 11:27:57 -0700132 public void onWakeLockAcquired(int flags, String tag, String packageName,
133 int ownerUid, int ownerPid, WorkSource workSource) {
Jeff Brown96307042012-07-27 15:51:34 -0700134 if (DEBUG) {
135 Slog.d(TAG, "onWakeLockAcquired: flags=" + flags + ", tag=\"" + tag
Dianne Hackborn713df152013-05-17 11:27:57 -0700136 + "\", packageName=" + packageName
137 + ", ownerUid=" + ownerUid + ", ownerPid=" + ownerPid
Jeff Brown96307042012-07-27 15:51:34 -0700138 + ", workSource=" + workSource);
139 }
140
Craig Mautner259328c2012-08-21 19:30:58 -0700141 try {
142 final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800143 boolean unimportantForLogging = (flags&PowerManager.UNIMPORTANT_FOR_LOGGING) != 0
144 && ownerUid == Process.SYSTEM_UID;
Craig Mautner259328c2012-08-21 19:30:58 -0700145 if (workSource != null) {
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800146 mBatteryStats.noteStartWakelockFromSource(workSource, ownerPid, tag, monitorType,
147 unimportantForLogging);
Craig Mautner259328c2012-08-21 19:30:58 -0700148 } else {
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800149 mBatteryStats.noteStartWakelock(ownerUid, ownerPid, tag, monitorType,
150 unimportantForLogging);
Dianne Hackborn713df152013-05-17 11:27:57 -0700151 // XXX need to deal with disabled operations.
Dianne Hackborne98f5db2013-07-17 17:23:25 -0700152 mAppOps.startOperation(AppOpsManager.getToken(mAppOps),
153 AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName);
Jeff Brown96307042012-07-27 15:51:34 -0700154 }
Craig Mautner259328c2012-08-21 19:30:58 -0700155 } catch (RemoteException ex) {
156 // Ignore
Jeff Brown96307042012-07-27 15:51:34 -0700157 }
158 }
159
160 /**
161 * Called when a wake lock is released.
162 */
Dianne Hackborn713df152013-05-17 11:27:57 -0700163 public void onWakeLockReleased(int flags, String tag, String packageName,
164 int ownerUid, int ownerPid, WorkSource workSource) {
Jeff Brown96307042012-07-27 15:51:34 -0700165 if (DEBUG) {
166 Slog.d(TAG, "onWakeLockReleased: flags=" + flags + ", tag=\"" + tag
Dianne Hackborn713df152013-05-17 11:27:57 -0700167 + "\", packageName=" + packageName
168 + ", ownerUid=" + ownerUid + ", ownerPid=" + ownerPid
Jeff Brown96307042012-07-27 15:51:34 -0700169 + ", workSource=" + workSource);
170 }
171
Craig Mautner259328c2012-08-21 19:30:58 -0700172 try {
173 final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
174 if (workSource != null) {
175 mBatteryStats.noteStopWakelockFromSource(workSource, ownerPid, tag, monitorType);
176 } else {
177 mBatteryStats.noteStopWakelock(ownerUid, ownerPid, tag, monitorType);
Dianne Hackborne98f5db2013-07-17 17:23:25 -0700178 mAppOps.finishOperation(AppOpsManager.getToken(mAppOps),
179 AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName);
Jeff Brown96307042012-07-27 15:51:34 -0700180 }
Craig Mautner259328c2012-08-21 19:30:58 -0700181 } catch (RemoteException ex) {
182 // Ignore
Jeff Brown96307042012-07-27 15:51:34 -0700183 }
184 }
185
Jeff Brown96307042012-07-27 15:51:34 -0700186 private static int getBatteryStatsWakeLockMonitorType(int flags) {
187 switch (flags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
188 case PowerManager.PARTIAL_WAKE_LOCK:
189 case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
190 return BatteryStats.WAKE_TYPE_PARTIAL;
191 default:
192 return BatteryStats.WAKE_TYPE_FULL;
193 }
194 }
195
196 /**
197 * Called when the screen is turned on.
198 */
199 public void onScreenOn() {
200 if (DEBUG) {
201 Slog.d(TAG, "onScreenOn");
202 }
203
204 try {
205 mBatteryStats.noteScreenOn();
206 } catch (RemoteException ex) {
207 // Ignore
208 }
209 }
210
211 /**
212 * Called when the screen is turned off.
213 */
214 public void onScreenOff() {
215 if (DEBUG) {
216 Slog.d(TAG, "onScreenOff");
217 }
218
219 try {
220 mBatteryStats.noteScreenOff();
221 } catch (RemoteException ex) {
222 // Ignore
223 }
224 }
225
226 /**
227 * Called when the screen changes brightness.
228 */
229 public void onScreenBrightness(int brightness) {
230 if (DEBUG) {
231 Slog.d(TAG, "onScreenBrightness: brightness=" + brightness);
232 }
233
234 try {
235 mBatteryStats.noteScreenBrightness(brightness);
236 } catch (RemoteException ex) {
237 // Ignore
238 }
239 }
240
241 /**
242 * Called when the device is waking up from sleep and the
243 * display is about to be turned on.
244 */
245 public void onWakeUpStarted() {
246 if (DEBUG) {
247 Slog.d(TAG, "onWakeUpStarted");
248 }
249
250 synchronized (mLock) {
251 if (mActualPowerState != POWER_STATE_AWAKE) {
252 mActualPowerState = POWER_STATE_AWAKE;
Jeff Brown54308352012-10-04 17:59:58 -0700253 mPendingWakeUpBroadcast = true;
Jeff Brownc38c9be2012-10-04 13:16:19 -0700254 if (!mScreenOnBlockerAcquired) {
255 mScreenOnBlockerAcquired = true;
256 mScreenOnBlocker.acquire();
257 }
Jeff Brown96307042012-07-27 15:51:34 -0700258 updatePendingBroadcastLocked();
259 }
260 }
261 }
262
263 /**
264 * Called when the device has finished waking up from sleep
265 * and the display has been turned on.
266 */
267 public void onWakeUpFinished() {
268 if (DEBUG) {
269 Slog.d(TAG, "onWakeUpFinished");
270 }
271 }
272
273 /**
274 * Called when the device is going to sleep.
275 */
276 public void onGoToSleepStarted(int reason) {
277 if (DEBUG) {
278 Slog.d(TAG, "onGoToSleepStarted");
279 }
280
281 synchronized (mLock) {
282 mLastGoToSleepReason = reason;
283 }
284 }
285
286 /**
287 * Called when the device has finished going to sleep and the
288 * display has been turned off.
289 *
290 * This is a good time to make transitions that we don't want the user to see,
291 * such as bringing the key guard to focus. There's no guarantee for this,
292 * however because the user could turn the device on again at any time.
293 * Some things may need to be protected by other mechanisms that defer screen on.
294 */
295 public void onGoToSleepFinished() {
296 if (DEBUG) {
297 Slog.d(TAG, "onGoToSleepFinished");
298 }
299
300 synchronized (mLock) {
301 if (mActualPowerState != POWER_STATE_ASLEEP) {
302 mActualPowerState = POWER_STATE_ASLEEP;
Jeff Brown54308352012-10-04 17:59:58 -0700303 mPendingGoToSleepBroadcast = true;
Jeff Brown96307042012-07-27 15:51:34 -0700304 if (mUserActivityPending) {
305 mUserActivityPending = false;
306 mHandler.removeMessages(MSG_USER_ACTIVITY);
307 }
308 updatePendingBroadcastLocked();
309 }
310 }
311 }
312
313 /**
314 * Called when there has been user activity.
315 */
316 public void onUserActivity(int event, int uid) {
317 if (DEBUG) {
318 Slog.d(TAG, "onUserActivity: event=" + event + ", uid=" + uid);
319 }
320
321 try {
322 mBatteryStats.noteUserActivity(uid, event);
323 } catch (RemoteException ex) {
324 // Ignore
325 }
326
327 synchronized (mLock) {
328 if (!mUserActivityPending) {
329 mUserActivityPending = true;
330 Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY);
331 msg.setAsynchronous(true);
332 mHandler.sendMessage(msg);
333 }
334 }
335 }
336
Jeff Brown84e27562012-12-07 13:56:34 -0800337 /**
338 * Called when wireless charging has started so as to provide user feedback.
339 */
340 public void onWirelessChargingStarted() {
341 if (DEBUG) {
342 Slog.d(TAG, "onWirelessChargingStarted");
343 }
344
345 mSuspendBlocker.acquire();
346 Message msg = mHandler.obtainMessage(MSG_WIRELESS_CHARGING_STARTED);
347 msg.setAsynchronous(true);
348 mHandler.sendMessage(msg);
349 }
350
Jeff Brown96307042012-07-27 15:51:34 -0700351 private void updatePendingBroadcastLocked() {
352 if (!mBroadcastInProgress
353 && mActualPowerState != POWER_STATE_UNKNOWN
Jeff Brown54308352012-10-04 17:59:58 -0700354 && (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
355 || mActualPowerState != mBroadcastedPowerState)) {
Jeff Brown96307042012-07-27 15:51:34 -0700356 mBroadcastInProgress = true;
357 mSuspendBlocker.acquire();
358 Message msg = mHandler.obtainMessage(MSG_BROADCAST);
359 msg.setAsynchronous(true);
360 mHandler.sendMessage(msg);
361 }
362 }
363
Jeff Brown54308352012-10-04 17:59:58 -0700364 private void finishPendingBroadcastLocked() {
365 mBroadcastInProgress = false;
366 mSuspendBlocker.release();
367 }
368
Jeff Brown96307042012-07-27 15:51:34 -0700369 private void sendUserActivity() {
370 synchronized (mLock) {
371 if (!mUserActivityPending) {
372 return;
373 }
374 mUserActivityPending = false;
375 }
376
377 mPolicy.userActivity();
378 }
379
380 private void sendNextBroadcast() {
381 final int powerState;
382 final int goToSleepReason;
383 synchronized (mLock) {
Jeff Brown54308352012-10-04 17:59:58 -0700384 if (mBroadcastedPowerState == POWER_STATE_UNKNOWN) {
385 // Broadcasted power state is unknown. Send wake up.
386 mPendingWakeUpBroadcast = false;
387 mBroadcastedPowerState = POWER_STATE_AWAKE;
388 } else if (mBroadcastedPowerState == POWER_STATE_AWAKE) {
389 // Broadcasted power state is awake. Send asleep if needed.
390 if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
391 || mActualPowerState == POWER_STATE_ASLEEP) {
392 mPendingGoToSleepBroadcast = false;
393 mBroadcastedPowerState = POWER_STATE_ASLEEP;
394 } else {
395 finishPendingBroadcastLocked();
396 return;
397 }
398 } else {
399 // Broadcasted power state is asleep. Send awake if needed.
400 if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
401 || mActualPowerState == POWER_STATE_AWAKE) {
402 mPendingWakeUpBroadcast = false;
403 mBroadcastedPowerState = POWER_STATE_AWAKE;
404 } else {
405 finishPendingBroadcastLocked();
406 return;
407 }
Jeff Brown96307042012-07-27 15:51:34 -0700408 }
409
Jeff Brown96307042012-07-27 15:51:34 -0700410 mBroadcastStartTime = SystemClock.uptimeMillis();
Jeff Brown54308352012-10-04 17:59:58 -0700411 powerState = mBroadcastedPowerState;
412 goToSleepReason = mLastGoToSleepReason;
Jeff Brown96307042012-07-27 15:51:34 -0700413 }
414
415 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_SEND, 1);
416
417 if (powerState == POWER_STATE_AWAKE) {
418 sendWakeUpBroadcast();
419 } else {
420 sendGoToSleepBroadcast(goToSleepReason);
421 }
422 }
423
424 private void sendWakeUpBroadcast() {
425 if (DEBUG) {
426 Slog.d(TAG, "Sending wake up broadcast.");
427 }
428
429 EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, 0, 0, 0);
430
431 mPolicy.screenTurningOn(mScreenOnListener);
Jeff Brownc38c9be2012-10-04 13:16:19 -0700432
Jeff Brown96307042012-07-27 15:51:34 -0700433 try {
434 ActivityManagerNative.getDefault().wakingUp();
435 } catch (RemoteException e) {
436 // ignore it
437 }
438
439 if (ActivityManagerNative.isSystemReady()) {
Dianne Hackborn5ac72a22012-08-29 18:32:08 -0700440 mContext.sendOrderedBroadcastAsUser(mScreenOnIntent, UserHandle.ALL, null,
Jeff Brown96307042012-07-27 15:51:34 -0700441 mWakeUpBroadcastDone, mHandler, 0, null, null);
442 } else {
443 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 2, 1);
444 sendNextBroadcast();
445 }
446 }
447
Jeff Brownc38c9be2012-10-04 13:16:19 -0700448 private final WindowManagerPolicy.ScreenOnListener mScreenOnListener =
449 new WindowManagerPolicy.ScreenOnListener() {
450 @Override
451 public void onScreenOn() {
452 synchronized (mLock) {
453 if (mScreenOnBlockerAcquired && !mPendingWakeUpBroadcast) {
454 mScreenOnBlockerAcquired = false;
455 mScreenOnBlocker.release();
456 }
457 }
458 }
459 };
460
Jeff Brown96307042012-07-27 15:51:34 -0700461 private final BroadcastReceiver mWakeUpBroadcastDone = new BroadcastReceiver() {
462 @Override
463 public void onReceive(Context context, Intent intent) {
464 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 1,
465 SystemClock.uptimeMillis() - mBroadcastStartTime, 1);
466 sendNextBroadcast();
467 }
468 };
469
470 private void sendGoToSleepBroadcast(int reason) {
471 if (DEBUG) {
472 Slog.d(TAG, "Sending go to sleep broadcast.");
473 }
474
475 int why = WindowManagerPolicy.OFF_BECAUSE_OF_USER;
476 switch (reason) {
477 case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN:
478 why = WindowManagerPolicy.OFF_BECAUSE_OF_ADMIN;
479 break;
480 case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT:
481 why = WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT;
482 break;
483 }
484
485 EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0, why, 0, 0);
486
487 mPolicy.screenTurnedOff(why);
488 try {
489 ActivityManagerNative.getDefault().goingToSleep();
490 } catch (RemoteException e) {
491 // ignore it.
492 }
493
494 if (ActivityManagerNative.isSystemReady()) {
Dianne Hackborn5ac72a22012-08-29 18:32:08 -0700495 mContext.sendOrderedBroadcastAsUser(mScreenOffIntent, UserHandle.ALL, null,
Jeff Brown96307042012-07-27 15:51:34 -0700496 mGoToSleepBroadcastDone, mHandler, 0, null, null);
497 } else {
498 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 3, 1);
499 sendNextBroadcast();
500 }
501 }
502
503 private final BroadcastReceiver mGoToSleepBroadcastDone = new BroadcastReceiver() {
504 @Override
505 public void onReceive(Context context, Intent intent) {
506 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 0,
507 SystemClock.uptimeMillis() - mBroadcastStartTime, 1);
508 sendNextBroadcast();
509 }
510 };
511
Jeff Brown84e27562012-12-07 13:56:34 -0800512 private void playWirelessChargingStartedSound() {
513 final String soundPath = Settings.Global.getString(mContext.getContentResolver(),
514 Settings.Global.WIRELESS_CHARGING_STARTED_SOUND);
515 if (soundPath != null) {
516 final Uri soundUri = Uri.parse("file://" + soundPath);
517 if (soundUri != null) {
518 final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
519 if (sfx != null) {
520 sfx.setStreamType(AudioManager.STREAM_SYSTEM);
521 sfx.play();
522 }
523 }
524 }
525
526 mSuspendBlocker.release();
527 }
528
Jeff Brown96307042012-07-27 15:51:34 -0700529 private final class NotifierHandler extends Handler {
530 public NotifierHandler(Looper looper) {
Jeff Browna2910d02012-08-25 12:29:46 -0700531 super(looper, null, true /*async*/);
Jeff Brown96307042012-07-27 15:51:34 -0700532 }
533
534 @Override
535 public void handleMessage(Message msg) {
536 switch (msg.what) {
537 case MSG_USER_ACTIVITY:
538 sendUserActivity();
539 break;
540
541 case MSG_BROADCAST:
542 sendNextBroadcast();
543 break;
Jeff Brown84e27562012-12-07 13:56:34 -0800544
545 case MSG_WIRELESS_CHARGING_STARTED:
546 playWirelessChargingStartedSound();
547 break;
Jeff Brown96307042012-07-27 15:51:34 -0700548 }
549 }
550 }
551}