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