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