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 import android.view.inputmethod.InputMethodManagerInternal; 52 53 /** 54 * Sends broadcasts about important power state changes. 55 * <p> 56 * This methods of this class may be called by the power manager service while 57 * its lock is being held. Internally it takes care of sending broadcasts to 58 * notify other components of the system or applications asynchronously. 59 * </p><p> 60 * The notifier is designed to collapse unnecessary broadcasts when it is not 61 * possible for the system to have observed an intermediate state. 62 * </p><p> 63 * For example, if the device wakes up, goes to sleep, wakes up again and goes to 64 * sleep again before the wake up notification is sent, then the system will 65 * be told about only one wake up and sleep. However, we always notify the 66 * fact that at least one transition occurred. It is especially important to 67 * tell the system when we go to sleep so that it can lock the keyguard if needed. 68 * </p> 69 */ 70 final class Notifier { 71 private static final String TAG = "PowerManagerNotifier"; 72 73 private static final boolean DEBUG = false; 74 75 private static final int INTERACTIVE_STATE_UNKNOWN = 0; 76 private static final int INTERACTIVE_STATE_AWAKE = 1; 77 private static final int INTERACTIVE_STATE_ASLEEP = 2; 78 79 private static final int MSG_USER_ACTIVITY = 1; 80 private static final int MSG_BROADCAST = 2; 81 private static final int MSG_WIRELESS_CHARGING_STARTED = 3; 82 private static final int MSG_SCREEN_BRIGHTNESS_BOOST_CHANGED = 4; 83 84 private final Object mLock = new Object(); 85 86 private final Context mContext; 87 private final IBatteryStats mBatteryStats; 88 private final IAppOpsService mAppOps; 89 private final SuspendBlocker mSuspendBlocker; 90 private final WindowManagerPolicy mPolicy; 91 private final ActivityManagerInternal mActivityManagerInternal; 92 private final InputManagerInternal mInputManagerInternal; 93 private final InputMethodManagerInternal mInputMethodManagerInternal; 94 95 private final NotifierHandler mHandler; 96 private final Intent mScreenOnIntent; 97 private final Intent mScreenOffIntent; 98 private final Intent mScreenBrightnessBoostIntent; 99 100 // True if the device should suspend when the screen is off due to proximity. 101 private final boolean mSuspendWhenScreenOffDueToProximityConfig; 102 103 // The current interactive state. This is set as soon as an interactive state 104 // transition begins so as to capture the reason that it happened. At some point 105 // this state will propagate to the pending state then eventually to the 106 // broadcasted state over the course of reporting the transition asynchronously. 107 private boolean mInteractive = true; 108 private int mInteractiveChangeReason; 109 private boolean mInteractiveChanging; 110 111 // The pending interactive state that we will eventually want to broadcast. 112 // This is designed so that we can collapse redundant sequences of awake/sleep 113 // transition pairs while still guaranteeing that at least one transition is observed 114 // whenever this happens. 115 private int mPendingInteractiveState; 116 private boolean mPendingWakeUpBroadcast; 117 private boolean mPendingGoToSleepBroadcast; 118 119 // The currently broadcasted interactive state. This reflects what other parts of the 120 // system have observed. 121 private int mBroadcastedInteractiveState; 122 private boolean mBroadcastInProgress; 123 private long mBroadcastStartTime; 124 125 // True if a user activity message should be sent. 126 private boolean mUserActivityPending; 127 Notifier(Looper looper, Context context, IBatteryStats batteryStats, IAppOpsService appOps, SuspendBlocker suspendBlocker, WindowManagerPolicy policy)128 public Notifier(Looper looper, Context context, IBatteryStats batteryStats, 129 IAppOpsService appOps, SuspendBlocker suspendBlocker, 130 WindowManagerPolicy policy) { 131 mContext = context; 132 mBatteryStats = batteryStats; 133 mAppOps = appOps; 134 mSuspendBlocker = suspendBlocker; 135 mPolicy = policy; 136 mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class); 137 mInputManagerInternal = LocalServices.getService(InputManagerInternal.class); 138 mInputMethodManagerInternal = LocalServices.getService(InputMethodManagerInternal.class); 139 140 mHandler = new NotifierHandler(looper); 141 mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON); 142 mScreenOnIntent.addFlags( 143 Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); 144 mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF); 145 mScreenOffIntent.addFlags( 146 Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); 147 mScreenBrightnessBoostIntent = 148 new Intent(PowerManager.ACTION_SCREEN_BRIGHTNESS_BOOST_CHANGED); 149 mScreenBrightnessBoostIntent.addFlags( 150 Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); 151 152 mSuspendWhenScreenOffDueToProximityConfig = context.getResources().getBoolean( 153 com.android.internal.R.bool.config_suspendWhenScreenOffDueToProximity); 154 155 // Initialize interactive state for battery stats. 156 try { 157 mBatteryStats.noteInteractive(true); 158 } catch (RemoteException ex) { } 159 } 160 161 /** 162 * Called when a wake lock is acquired. 163 */ onWakeLockAcquired(int flags, String tag, String packageName, int ownerUid, int ownerPid, WorkSource workSource, String historyTag)164 public void onWakeLockAcquired(int flags, String tag, String packageName, 165 int ownerUid, int ownerPid, WorkSource workSource, String historyTag) { 166 if (DEBUG) { 167 Slog.d(TAG, "onWakeLockAcquired: flags=" + flags + ", tag=\"" + tag 168 + "\", packageName=" + packageName 169 + ", ownerUid=" + ownerUid + ", ownerPid=" + ownerPid 170 + ", workSource=" + workSource); 171 } 172 173 final int monitorType = getBatteryStatsWakeLockMonitorType(flags); 174 if (monitorType >= 0) { 175 try { 176 final boolean unimportantForLogging = ownerUid == Process.SYSTEM_UID 177 && (flags & PowerManager.UNIMPORTANT_FOR_LOGGING) != 0; 178 if (workSource != null) { 179 mBatteryStats.noteStartWakelockFromSource(workSource, ownerPid, tag, 180 historyTag, monitorType, unimportantForLogging); 181 } else { 182 mBatteryStats.noteStartWakelock(ownerUid, ownerPid, tag, historyTag, 183 monitorType, unimportantForLogging); 184 // XXX need to deal with disabled operations. 185 mAppOps.startOperation(AppOpsManager.getToken(mAppOps), 186 AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName); 187 } 188 } catch (RemoteException ex) { 189 // Ignore 190 } 191 } 192 } 193 194 /** 195 * Called when a wake lock is changing. 196 */ onWakeLockChanging(int flags, String tag, String packageName, int ownerUid, int ownerPid, WorkSource workSource, String historyTag, int newFlags, String newTag, String newPackageName, int newOwnerUid, int newOwnerPid, WorkSource newWorkSource, String newHistoryTag)197 public void onWakeLockChanging(int flags, String tag, String packageName, 198 int ownerUid, int ownerPid, WorkSource workSource, String historyTag, 199 int newFlags, String newTag, String newPackageName, int newOwnerUid, 200 int newOwnerPid, WorkSource newWorkSource, String newHistoryTag) { 201 202 final int monitorType = getBatteryStatsWakeLockMonitorType(flags); 203 final int newMonitorType = getBatteryStatsWakeLockMonitorType(newFlags); 204 if (workSource != null && newWorkSource != null 205 && monitorType >= 0 && newMonitorType >= 0) { 206 if (DEBUG) { 207 Slog.d(TAG, "onWakeLockChanging: flags=" + newFlags + ", tag=\"" + newTag 208 + "\", packageName=" + newPackageName 209 + ", ownerUid=" + newOwnerUid + ", ownerPid=" + newOwnerPid 210 + ", workSource=" + newWorkSource); 211 } 212 213 final boolean unimportantForLogging = newOwnerUid == Process.SYSTEM_UID 214 && (newFlags & PowerManager.UNIMPORTANT_FOR_LOGGING) != 0; 215 try { 216 mBatteryStats.noteChangeWakelockFromSource(workSource, ownerPid, tag, historyTag, 217 monitorType, newWorkSource, newOwnerPid, newTag, newHistoryTag, 218 newMonitorType, unimportantForLogging); 219 } catch (RemoteException ex) { 220 // Ignore 221 } 222 } else { 223 onWakeLockReleased(flags, tag, packageName, ownerUid, ownerPid, workSource, historyTag); 224 onWakeLockAcquired(newFlags, newTag, newPackageName, newOwnerUid, newOwnerPid, 225 newWorkSource, newHistoryTag); 226 } 227 } 228 229 /** 230 * Called when a wake lock is released. 231 */ onWakeLockReleased(int flags, String tag, String packageName, int ownerUid, int ownerPid, WorkSource workSource, String historyTag)232 public void onWakeLockReleased(int flags, String tag, String packageName, 233 int ownerUid, int ownerPid, WorkSource workSource, String historyTag) { 234 if (DEBUG) { 235 Slog.d(TAG, "onWakeLockReleased: flags=" + flags + ", tag=\"" + tag 236 + "\", packageName=" + packageName 237 + ", ownerUid=" + ownerUid + ", ownerPid=" + ownerPid 238 + ", workSource=" + workSource); 239 } 240 241 final int monitorType = getBatteryStatsWakeLockMonitorType(flags); 242 if (monitorType >= 0) { 243 try { 244 if (workSource != null) { 245 mBatteryStats.noteStopWakelockFromSource(workSource, ownerPid, tag, 246 historyTag, monitorType); 247 } else { 248 mBatteryStats.noteStopWakelock(ownerUid, ownerPid, tag, 249 historyTag, monitorType); 250 mAppOps.finishOperation(AppOpsManager.getToken(mAppOps), 251 AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName); 252 } 253 } catch (RemoteException ex) { 254 // Ignore 255 } 256 } 257 } 258 getBatteryStatsWakeLockMonitorType(int flags)259 private int getBatteryStatsWakeLockMonitorType(int flags) { 260 switch (flags & PowerManager.WAKE_LOCK_LEVEL_MASK) { 261 case PowerManager.PARTIAL_WAKE_LOCK: 262 return BatteryStats.WAKE_TYPE_PARTIAL; 263 264 case PowerManager.SCREEN_DIM_WAKE_LOCK: 265 case PowerManager.SCREEN_BRIGHT_WAKE_LOCK: 266 return BatteryStats.WAKE_TYPE_FULL; 267 268 case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK: 269 if (mSuspendWhenScreenOffDueToProximityConfig) { 270 return -1; 271 } 272 return BatteryStats.WAKE_TYPE_PARTIAL; 273 274 case PowerManager.DRAW_WAKE_LOCK: 275 return BatteryStats.WAKE_TYPE_DRAW; 276 277 case PowerManager.DOZE_WAKE_LOCK: 278 // Doze wake locks are an internal implementation detail of the 279 // communication between dream manager service and power manager 280 // service. They have no additive battery impact. 281 return -1; 282 283 default: 284 return -1; 285 } 286 } 287 288 /** 289 * Notifies that the device is changing wakefulness. 290 * This function may be called even if the previous change hasn't finished in 291 * which case it will assume that the state did not fully converge before the 292 * next transition began and will recover accordingly. 293 */ onWakefulnessChangeStarted(final int wakefulness, int reason)294 public void onWakefulnessChangeStarted(final int wakefulness, int reason) { 295 final boolean interactive = PowerManagerInternal.isInteractive(wakefulness); 296 if (DEBUG) { 297 Slog.d(TAG, "onWakefulnessChangeStarted: wakefulness=" + wakefulness 298 + ", reason=" + reason + ", interactive=" + interactive); 299 } 300 301 // Tell the activity manager about changes in wakefulness, not just interactivity. 302 // It needs more granularity than other components. 303 mHandler.post(new Runnable() { 304 @Override 305 public void run() { 306 mActivityManagerInternal.onWakefulnessChanged(wakefulness); 307 } 308 }); 309 310 // Handle any early interactive state changes. 311 // Finish pending incomplete ones from a previous cycle. 312 if (mInteractive != interactive) { 313 // Finish up late behaviors if needed. 314 if (mInteractiveChanging) { 315 handleLateInteractiveChange(); 316 } 317 318 // Start input as soon as we start waking up or going to sleep. 319 mInputManagerInternal.setInteractive(interactive); 320 mInputMethodManagerInternal.setInteractive(interactive); 321 322 // Notify battery stats. 323 try { 324 mBatteryStats.noteInteractive(interactive); 325 } catch (RemoteException ex) { } 326 327 // Handle early behaviors. 328 mInteractive = interactive; 329 mInteractiveChangeReason = reason; 330 mInteractiveChanging = true; 331 handleEarlyInteractiveChange(); 332 } 333 } 334 335 /** 336 * Notifies that the device has finished changing wakefulness. 337 */ onWakefulnessChangeFinished()338 public void onWakefulnessChangeFinished() { 339 if (DEBUG) { 340 Slog.d(TAG, "onWakefulnessChangeFinished"); 341 } 342 343 if (mInteractiveChanging) { 344 mInteractiveChanging = false; 345 handleLateInteractiveChange(); 346 } 347 } 348 349 /** 350 * Handle early interactive state changes such as getting applications or the lock 351 * screen running and ready for the user to see (such as when turning on the screen). 352 */ handleEarlyInteractiveChange()353 private void handleEarlyInteractiveChange() { 354 synchronized (mLock) { 355 if (mInteractive) { 356 // Waking up... 357 mHandler.post(new Runnable() { 358 @Override 359 public void run() { 360 EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, 0, 0, 0); 361 mPolicy.startedWakingUp(); 362 } 363 }); 364 365 // Send interactive broadcast. 366 mPendingInteractiveState = INTERACTIVE_STATE_AWAKE; 367 mPendingWakeUpBroadcast = true; 368 updatePendingBroadcastLocked(); 369 } else { 370 // Going to sleep... 371 // Tell the policy that we started going to sleep. 372 final int why = translateOffReason(mInteractiveChangeReason); 373 mHandler.post(new Runnable() { 374 @Override 375 public void run() { 376 mPolicy.startedGoingToSleep(why); 377 } 378 }); 379 } 380 } 381 } 382 383 /** 384 * Handle late interactive state changes once they are finished so that the system can 385 * finish pending transitions (such as turning the screen off) before causing 386 * applications to change state visibly. 387 */ handleLateInteractiveChange()388 private void handleLateInteractiveChange() { 389 synchronized (mLock) { 390 if (mInteractive) { 391 // Finished waking up... 392 mHandler.post(new Runnable() { 393 @Override 394 public void run() { 395 mPolicy.finishedWakingUp(); 396 } 397 }); 398 } else { 399 // Finished going to sleep... 400 // This is a good time to make transitions that we don't want the user to see, 401 // such as bringing the key guard to focus. There's no guarantee for this 402 // however because the user could turn the device on again at any time. 403 // Some things may need to be protected by other mechanisms that defer screen on. 404 405 // Cancel pending user activity. 406 if (mUserActivityPending) { 407 mUserActivityPending = false; 408 mHandler.removeMessages(MSG_USER_ACTIVITY); 409 } 410 411 // Tell the policy we finished going to sleep. 412 final int why = translateOffReason(mInteractiveChangeReason); 413 mHandler.post(new Runnable() { 414 @Override 415 public void run() { 416 EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0, why, 0, 0); 417 mPolicy.finishedGoingToSleep(why); 418 } 419 }); 420 421 // Send non-interactive broadcast. 422 mPendingInteractiveState = INTERACTIVE_STATE_ASLEEP; 423 mPendingGoToSleepBroadcast = true; 424 updatePendingBroadcastLocked(); 425 } 426 } 427 } 428 translateOffReason(int reason)429 private static int translateOffReason(int reason) { 430 switch (reason) { 431 case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN: 432 return WindowManagerPolicy.OFF_BECAUSE_OF_ADMIN; 433 case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT: 434 return WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT; 435 default: 436 return WindowManagerPolicy.OFF_BECAUSE_OF_USER; 437 } 438 } 439 440 /** 441 * Called when screen brightness boost begins or ends. 442 */ onScreenBrightnessBoostChanged()443 public void onScreenBrightnessBoostChanged() { 444 if (DEBUG) { 445 Slog.d(TAG, "onScreenBrightnessBoostChanged"); 446 } 447 448 mSuspendBlocker.acquire(); 449 Message msg = mHandler.obtainMessage(MSG_SCREEN_BRIGHTNESS_BOOST_CHANGED); 450 msg.setAsynchronous(true); 451 mHandler.sendMessage(msg); 452 } 453 454 /** 455 * Called when there has been user activity. 456 */ onUserActivity(int event, int uid)457 public void onUserActivity(int event, int uid) { 458 if (DEBUG) { 459 Slog.d(TAG, "onUserActivity: event=" + event + ", uid=" + uid); 460 } 461 462 try { 463 mBatteryStats.noteUserActivity(uid, event); 464 } catch (RemoteException ex) { 465 // Ignore 466 } 467 468 synchronized (mLock) { 469 if (!mUserActivityPending) { 470 mUserActivityPending = true; 471 Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY); 472 msg.setAsynchronous(true); 473 mHandler.sendMessage(msg); 474 } 475 } 476 } 477 478 /** 479 * Called when the screen has turned on. 480 */ onWakeUp(String reason, int reasonUid, String opPackageName, int opUid)481 public void onWakeUp(String reason, int reasonUid, String opPackageName, int opUid) { 482 if (DEBUG) { 483 Slog.d(TAG, "onWakeUp: event=" + reason + ", reasonUid=" + reasonUid 484 + " opPackageName=" + opPackageName + " opUid=" + opUid); 485 } 486 487 try { 488 mBatteryStats.noteWakeUp(reason, reasonUid); 489 if (opPackageName != null) { 490 mAppOps.noteOperation(AppOpsManager.OP_TURN_SCREEN_ON, opUid, opPackageName); 491 } 492 } catch (RemoteException ex) { 493 // Ignore 494 } 495 496 } 497 498 /** 499 * Called when wireless charging has started so as to provide user feedback. 500 */ onWirelessChargingStarted()501 public void onWirelessChargingStarted() { 502 if (DEBUG) { 503 Slog.d(TAG, "onWirelessChargingStarted"); 504 } 505 506 mSuspendBlocker.acquire(); 507 Message msg = mHandler.obtainMessage(MSG_WIRELESS_CHARGING_STARTED); 508 msg.setAsynchronous(true); 509 mHandler.sendMessage(msg); 510 } 511 updatePendingBroadcastLocked()512 private void updatePendingBroadcastLocked() { 513 if (!mBroadcastInProgress 514 && mPendingInteractiveState != INTERACTIVE_STATE_UNKNOWN 515 && (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast 516 || mPendingInteractiveState != mBroadcastedInteractiveState)) { 517 mBroadcastInProgress = true; 518 mSuspendBlocker.acquire(); 519 Message msg = mHandler.obtainMessage(MSG_BROADCAST); 520 msg.setAsynchronous(true); 521 mHandler.sendMessage(msg); 522 } 523 } 524 finishPendingBroadcastLocked()525 private void finishPendingBroadcastLocked() { 526 mBroadcastInProgress = false; 527 mSuspendBlocker.release(); 528 } 529 sendUserActivity()530 private void sendUserActivity() { 531 synchronized (mLock) { 532 if (!mUserActivityPending) { 533 return; 534 } 535 mUserActivityPending = false; 536 } 537 538 mPolicy.userActivity(); 539 } 540 sendNextBroadcast()541 private void sendNextBroadcast() { 542 final int powerState; 543 synchronized (mLock) { 544 if (mBroadcastedInteractiveState == INTERACTIVE_STATE_UNKNOWN) { 545 // Broadcasted power state is unknown. Send wake up. 546 mPendingWakeUpBroadcast = false; 547 mBroadcastedInteractiveState = INTERACTIVE_STATE_AWAKE; 548 } else if (mBroadcastedInteractiveState == INTERACTIVE_STATE_AWAKE) { 549 // Broadcasted power state is awake. Send asleep if needed. 550 if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast 551 || mPendingInteractiveState == INTERACTIVE_STATE_ASLEEP) { 552 mPendingGoToSleepBroadcast = false; 553 mBroadcastedInteractiveState = INTERACTIVE_STATE_ASLEEP; 554 } else { 555 finishPendingBroadcastLocked(); 556 return; 557 } 558 } else { 559 // Broadcasted power state is asleep. Send awake if needed. 560 if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast 561 || mPendingInteractiveState == INTERACTIVE_STATE_AWAKE) { 562 mPendingWakeUpBroadcast = false; 563 mBroadcastedInteractiveState = INTERACTIVE_STATE_AWAKE; 564 } else { 565 finishPendingBroadcastLocked(); 566 return; 567 } 568 } 569 570 mBroadcastStartTime = SystemClock.uptimeMillis(); 571 powerState = mBroadcastedInteractiveState; 572 } 573 574 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_SEND, 1); 575 576 if (powerState == INTERACTIVE_STATE_AWAKE) { 577 sendWakeUpBroadcast(); 578 } else { 579 sendGoToSleepBroadcast(); 580 } 581 } 582 sendBrightnessBoostChangedBroadcast()583 private void sendBrightnessBoostChangedBroadcast() { 584 if (DEBUG) { 585 Slog.d(TAG, "Sending brightness boost changed broadcast."); 586 } 587 588 mContext.sendOrderedBroadcastAsUser(mScreenBrightnessBoostIntent, UserHandle.ALL, null, 589 mScreeBrightnessBoostChangedDone, mHandler, 0, null, null); 590 } 591 592 private final BroadcastReceiver mScreeBrightnessBoostChangedDone = new BroadcastReceiver() { 593 @Override 594 public void onReceive(Context context, Intent intent) { 595 mSuspendBlocker.release(); 596 } 597 }; 598 sendWakeUpBroadcast()599 private void sendWakeUpBroadcast() { 600 if (DEBUG) { 601 Slog.d(TAG, "Sending wake up broadcast."); 602 } 603 604 if (ActivityManagerNative.isSystemReady()) { 605 mContext.sendOrderedBroadcastAsUser(mScreenOnIntent, UserHandle.ALL, null, 606 mWakeUpBroadcastDone, mHandler, 0, null, null); 607 } else { 608 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 2, 1); 609 sendNextBroadcast(); 610 } 611 } 612 613 private final BroadcastReceiver mWakeUpBroadcastDone = new BroadcastReceiver() { 614 @Override 615 public void onReceive(Context context, Intent intent) { 616 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 1, 617 SystemClock.uptimeMillis() - mBroadcastStartTime, 1); 618 sendNextBroadcast(); 619 } 620 }; 621 sendGoToSleepBroadcast()622 private void sendGoToSleepBroadcast() { 623 if (DEBUG) { 624 Slog.d(TAG, "Sending go to sleep broadcast."); 625 } 626 627 if (ActivityManagerNative.isSystemReady()) { 628 mContext.sendOrderedBroadcastAsUser(mScreenOffIntent, UserHandle.ALL, null, 629 mGoToSleepBroadcastDone, mHandler, 0, null, null); 630 } else { 631 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 3, 1); 632 sendNextBroadcast(); 633 } 634 } 635 636 private final BroadcastReceiver mGoToSleepBroadcastDone = new BroadcastReceiver() { 637 @Override 638 public void onReceive(Context context, Intent intent) { 639 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 0, 640 SystemClock.uptimeMillis() - mBroadcastStartTime, 1); 641 sendNextBroadcast(); 642 } 643 }; 644 playWirelessChargingStartedSound()645 private void playWirelessChargingStartedSound() { 646 final boolean enabled = Settings.Global.getInt(mContext.getContentResolver(), 647 Settings.Global.CHARGING_SOUNDS_ENABLED, 1) != 0; 648 final String soundPath = Settings.Global.getString(mContext.getContentResolver(), 649 Settings.Global.WIRELESS_CHARGING_STARTED_SOUND); 650 if (enabled && soundPath != null) { 651 final Uri soundUri = Uri.parse("file://" + soundPath); 652 if (soundUri != null) { 653 final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri); 654 if (sfx != null) { 655 sfx.setStreamType(AudioManager.STREAM_SYSTEM); 656 sfx.play(); 657 } 658 } 659 } 660 661 mSuspendBlocker.release(); 662 } 663 664 private final class NotifierHandler extends Handler { NotifierHandler(Looper looper)665 public NotifierHandler(Looper looper) { 666 super(looper, null, true /*async*/); 667 } 668 669 @Override handleMessage(Message msg)670 public void handleMessage(Message msg) { 671 switch (msg.what) { 672 case MSG_USER_ACTIVITY: 673 sendUserActivity(); 674 break; 675 676 case MSG_BROADCAST: 677 sendNextBroadcast(); 678 break; 679 680 case MSG_WIRELESS_CHARGING_STARTED: 681 playWirelessChargingStartedSound(); 682 break; 683 case MSG_SCREEN_BRIGHTNESS_BOOST_CHANGED: 684 sendBrightnessBoostChangedBroadcast(); 685 break; 686 } 687 } 688 } 689 } 690