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