Notifier.java revision e5167ca61e2c5607aad9041b44158581bc61b4d8
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 17package com.android.server.power; 18 19import android.app.AppOpsManager; 20import com.android.internal.app.IAppOpsService; 21import com.android.internal.app.IBatteryStats; 22import com.android.server.EventLogTags; 23 24import android.app.ActivityManagerNative; 25import android.content.BroadcastReceiver; 26import android.content.Context; 27import android.content.Intent; 28import android.media.AudioManager; 29import android.media.Ringtone; 30import android.media.RingtoneManager; 31import android.net.Uri; 32import android.os.BatteryStats; 33import android.os.Handler; 34import android.os.Looper; 35import android.os.Message; 36import android.os.PowerManager; 37import android.os.Process; 38import android.os.RemoteException; 39import android.os.SystemClock; 40import android.os.UserHandle; 41import android.os.WorkSource; 42import android.provider.Settings; 43import android.util.EventLog; 44import android.util.Slog; 45import android.view.WindowManagerPolicy; 46 47/** 48 * Sends broadcasts about important power state changes. 49 * <p> 50 * This methods of this class may be called by the power manager service while 51 * its lock is being held. Internally it takes care of sending broadcasts to 52 * notify other components of the system or applications asynchronously. 53 * </p><p> 54 * The notifier is designed to collapse unnecessary broadcasts when it is not 55 * possible for the system to have observed an intermediate state. 56 * </p><p> 57 * For example, if the device wakes up, goes to sleep, wakes up again and goes to 58 * sleep again before the wake up notification is sent, then the system will 59 * be told about only one wake up and sleep. However, we always notify the 60 * fact that at least one transition occurred. It is especially important to 61 * tell the system when we go to sleep so that it can lock the keyguard if needed. 62 * </p> 63 */ 64final class Notifier { 65 private static final String TAG = "PowerManagerNotifier"; 66 67 private static final boolean DEBUG = false; 68 69 private static final int POWER_STATE_UNKNOWN = 0; 70 private static final int POWER_STATE_AWAKE = 1; 71 private static final int POWER_STATE_ASLEEP = 2; 72 73 private static final int MSG_USER_ACTIVITY = 1; 74 private static final int MSG_BROADCAST = 2; 75 private static final int MSG_WIRELESS_CHARGING_STARTED = 3; 76 77 private final Object mLock = new Object(); 78 79 private final Context mContext; 80 private final IBatteryStats mBatteryStats; 81 private final IAppOpsService mAppOps; 82 private final SuspendBlocker mSuspendBlocker; 83 private final ScreenOnBlocker mScreenOnBlocker; 84 private final WindowManagerPolicy mPolicy; 85 86 private final NotifierHandler mHandler; 87 private final Intent mScreenOnIntent; 88 private final Intent mScreenOffIntent; 89 90 // The current power state. 91 private int mActualPowerState; 92 private int mLastGoToSleepReason; 93 94 // True if there is a pending transition that needs to be reported. 95 private boolean mPendingWakeUpBroadcast; 96 private boolean mPendingGoToSleepBroadcast; 97 98 // The currently broadcasted power state. This reflects what other parts of the 99 // system have observed. 100 private int mBroadcastedPowerState; 101 private boolean mBroadcastInProgress; 102 private long mBroadcastStartTime; 103 104 // True if a user activity message should be sent. 105 private boolean mUserActivityPending; 106 107 // True if the screen on blocker has been acquired. 108 private boolean mScreenOnBlockerAcquired; 109 110 public Notifier(Looper looper, Context context, IBatteryStats batteryStats, 111 IAppOpsService appOps, SuspendBlocker suspendBlocker, ScreenOnBlocker screenOnBlocker, 112 WindowManagerPolicy policy) { 113 mContext = context; 114 mBatteryStats = batteryStats; 115 mAppOps = appOps; 116 mSuspendBlocker = suspendBlocker; 117 mScreenOnBlocker = screenOnBlocker; 118 mPolicy = policy; 119 120 mHandler = new NotifierHandler(looper); 121 mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON); 122 mScreenOnIntent.addFlags( 123 Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); 124 mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF); 125 mScreenOffIntent.addFlags( 126 Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); 127 } 128 129 /** 130 * Called when a wake lock is acquired. 131 */ 132 public void onWakeLockAcquired(int flags, String tag, String packageName, 133 int ownerUid, int ownerPid, WorkSource workSource, String historyTag) { 134 if (DEBUG) { 135 Slog.d(TAG, "onWakeLockAcquired: flags=" + flags + ", tag=\"" + tag 136 + "\", packageName=" + packageName 137 + ", ownerUid=" + ownerUid + ", ownerPid=" + ownerPid 138 + ", workSource=" + workSource); 139 } 140 141 try { 142 final int monitorType = getBatteryStatsWakeLockMonitorType(flags); 143 boolean unimportantForLogging = (flags&PowerManager.UNIMPORTANT_FOR_LOGGING) != 0 144 && ownerUid == Process.SYSTEM_UID; 145 if (workSource != null) { 146 mBatteryStats.noteStartWakelockFromSource(workSource, ownerPid, tag, historyTag, 147 monitorType, unimportantForLogging); 148 } else { 149 mBatteryStats.noteStartWakelock(ownerUid, ownerPid, tag, historyTag, 150 monitorType, unimportantForLogging); 151 // XXX need to deal with disabled operations. 152 mAppOps.startOperation(AppOpsManager.getToken(mAppOps), 153 AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName); 154 } 155 } catch (RemoteException ex) { 156 // Ignore 157 } 158 } 159 160 /** 161 * Called when a wake lock is changing. 162 */ 163 public void onWakeLockChanging(int flags, String tag, String packageName, 164 int ownerUid, int ownerPid, WorkSource workSource, String historyTag, 165 int newFlags, String newTag, String newPackageName, int newOwnerUid, 166 int newOwnerPid, WorkSource newWorkSource, String newHistoryTag) { 167 168 final int monitorType = getBatteryStatsWakeLockMonitorType(flags); 169 final int newMonitorType = getBatteryStatsWakeLockMonitorType(newFlags); 170 boolean unimportantForLogging = (flags&PowerManager.UNIMPORTANT_FOR_LOGGING) != 0 171 && ownerUid == Process.SYSTEM_UID; 172 if (workSource != null && newWorkSource != null) { 173 if (DEBUG) { 174 Slog.d(TAG, "onWakeLockChanging: flags=" + newFlags + ", tag=\"" + newTag 175 + "\", packageName=" + newPackageName 176 + ", ownerUid=" + newOwnerUid + ", ownerPid=" + newOwnerPid 177 + ", workSource=" + newWorkSource); 178 } 179 try { 180 mBatteryStats.noteChangeWakelockFromSource(workSource, ownerPid, tag, monitorType, 181 newWorkSource, newOwnerPid, newTag, newHistoryTag, 182 newMonitorType, unimportantForLogging); 183 } catch (RemoteException ex) { 184 // Ignore 185 } 186 } else { 187 onWakeLockReleased(flags, tag, packageName, ownerUid, ownerPid, workSource); 188 onWakeLockAcquired(newFlags, newTag, newPackageName, newOwnerUid, newOwnerPid, 189 newWorkSource, newHistoryTag); 190 } 191 } 192 193 /** 194 * Called when a wake lock is released. 195 */ 196 public void onWakeLockReleased(int flags, String tag, String packageName, 197 int ownerUid, int ownerPid, WorkSource workSource) { 198 if (DEBUG) { 199 Slog.d(TAG, "onWakeLockReleased: flags=" + flags + ", tag=\"" + tag 200 + "\", packageName=" + packageName 201 + ", ownerUid=" + ownerUid + ", ownerPid=" + ownerPid 202 + ", workSource=" + workSource); 203 } 204 205 try { 206 final int monitorType = getBatteryStatsWakeLockMonitorType(flags); 207 if (workSource != null) { 208 mBatteryStats.noteStopWakelockFromSource(workSource, ownerPid, tag, monitorType); 209 } else { 210 mBatteryStats.noteStopWakelock(ownerUid, ownerPid, tag, monitorType); 211 mAppOps.finishOperation(AppOpsManager.getToken(mAppOps), 212 AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName); 213 } 214 } catch (RemoteException ex) { 215 // Ignore 216 } 217 } 218 219 private static int getBatteryStatsWakeLockMonitorType(int flags) { 220 switch (flags & PowerManager.WAKE_LOCK_LEVEL_MASK) { 221 case PowerManager.PARTIAL_WAKE_LOCK: 222 case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK: 223 return BatteryStats.WAKE_TYPE_PARTIAL; 224 default: 225 return BatteryStats.WAKE_TYPE_FULL; 226 } 227 } 228 229 /** 230 * Called when the screen is turned on. 231 */ 232 public void onScreenOn() { 233 if (DEBUG) { 234 Slog.d(TAG, "onScreenOn"); 235 } 236 237 try { 238 mBatteryStats.noteScreenOn(); 239 } catch (RemoteException ex) { 240 // Ignore 241 } 242 } 243 244 /** 245 * Called when the screen is turned off. 246 */ 247 public void onScreenOff() { 248 if (DEBUG) { 249 Slog.d(TAG, "onScreenOff"); 250 } 251 252 try { 253 mBatteryStats.noteScreenOff(); 254 } catch (RemoteException ex) { 255 // Ignore 256 } 257 } 258 259 /** 260 * Called when the screen changes brightness. 261 */ 262 public void onScreenBrightness(int brightness) { 263 if (DEBUG) { 264 Slog.d(TAG, "onScreenBrightness: brightness=" + brightness); 265 } 266 267 try { 268 mBatteryStats.noteScreenBrightness(brightness); 269 } catch (RemoteException ex) { 270 // Ignore 271 } 272 } 273 274 /** 275 * Called when the device is waking up from sleep and the 276 * display is about to be turned on. 277 */ 278 public void onWakeUpStarted() { 279 if (DEBUG) { 280 Slog.d(TAG, "onWakeUpStarted"); 281 } 282 283 synchronized (mLock) { 284 if (mActualPowerState != POWER_STATE_AWAKE) { 285 mActualPowerState = POWER_STATE_AWAKE; 286 mPendingWakeUpBroadcast = true; 287 if (!mScreenOnBlockerAcquired) { 288 mScreenOnBlockerAcquired = true; 289 mScreenOnBlocker.acquire(); 290 } 291 updatePendingBroadcastLocked(); 292 } 293 } 294 } 295 296 /** 297 * Called when the device has finished waking up from sleep 298 * and the display has been turned on. 299 */ 300 public void onWakeUpFinished() { 301 if (DEBUG) { 302 Slog.d(TAG, "onWakeUpFinished"); 303 } 304 } 305 306 /** 307 * Called when the device is going to sleep. 308 */ 309 public void onGoToSleepStarted(int reason) { 310 if (DEBUG) { 311 Slog.d(TAG, "onGoToSleepStarted"); 312 } 313 314 synchronized (mLock) { 315 mLastGoToSleepReason = reason; 316 } 317 } 318 319 /** 320 * Called when the device has finished going to sleep and the 321 * display has been turned off. 322 * 323 * This is a good time to make transitions that we don't want the user to see, 324 * such as bringing the key guard to focus. There's no guarantee for this, 325 * however because the user could turn the device on again at any time. 326 * Some things may need to be protected by other mechanisms that defer screen on. 327 */ 328 public void onGoToSleepFinished() { 329 if (DEBUG) { 330 Slog.d(TAG, "onGoToSleepFinished"); 331 } 332 333 synchronized (mLock) { 334 if (mActualPowerState != POWER_STATE_ASLEEP) { 335 mActualPowerState = POWER_STATE_ASLEEP; 336 mPendingGoToSleepBroadcast = true; 337 if (mUserActivityPending) { 338 mUserActivityPending = false; 339 mHandler.removeMessages(MSG_USER_ACTIVITY); 340 } 341 updatePendingBroadcastLocked(); 342 } 343 } 344 } 345 346 /** 347 * Called when there has been user activity. 348 */ 349 public void onUserActivity(int event, int uid) { 350 if (DEBUG) { 351 Slog.d(TAG, "onUserActivity: event=" + event + ", uid=" + uid); 352 } 353 354 try { 355 mBatteryStats.noteUserActivity(uid, event); 356 } catch (RemoteException ex) { 357 // Ignore 358 } 359 360 synchronized (mLock) { 361 if (!mUserActivityPending) { 362 mUserActivityPending = true; 363 Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY); 364 msg.setAsynchronous(true); 365 mHandler.sendMessage(msg); 366 } 367 } 368 } 369 370 /** 371 * Called when wireless charging has started so as to provide user feedback. 372 */ 373 public void onWirelessChargingStarted() { 374 if (DEBUG) { 375 Slog.d(TAG, "onWirelessChargingStarted"); 376 } 377 378 mSuspendBlocker.acquire(); 379 Message msg = mHandler.obtainMessage(MSG_WIRELESS_CHARGING_STARTED); 380 msg.setAsynchronous(true); 381 mHandler.sendMessage(msg); 382 } 383 384 private void updatePendingBroadcastLocked() { 385 if (!mBroadcastInProgress 386 && mActualPowerState != POWER_STATE_UNKNOWN 387 && (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast 388 || mActualPowerState != mBroadcastedPowerState)) { 389 mBroadcastInProgress = true; 390 mSuspendBlocker.acquire(); 391 Message msg = mHandler.obtainMessage(MSG_BROADCAST); 392 msg.setAsynchronous(true); 393 mHandler.sendMessage(msg); 394 } 395 } 396 397 private void finishPendingBroadcastLocked() { 398 mBroadcastInProgress = false; 399 mSuspendBlocker.release(); 400 } 401 402 private void sendUserActivity() { 403 synchronized (mLock) { 404 if (!mUserActivityPending) { 405 return; 406 } 407 mUserActivityPending = false; 408 } 409 410 mPolicy.userActivity(); 411 } 412 413 private void sendNextBroadcast() { 414 final int powerState; 415 final int goToSleepReason; 416 synchronized (mLock) { 417 if (mBroadcastedPowerState == POWER_STATE_UNKNOWN) { 418 // Broadcasted power state is unknown. Send wake up. 419 mPendingWakeUpBroadcast = false; 420 mBroadcastedPowerState = POWER_STATE_AWAKE; 421 } else if (mBroadcastedPowerState == POWER_STATE_AWAKE) { 422 // Broadcasted power state is awake. Send asleep if needed. 423 if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast 424 || mActualPowerState == POWER_STATE_ASLEEP) { 425 mPendingGoToSleepBroadcast = false; 426 mBroadcastedPowerState = POWER_STATE_ASLEEP; 427 } else { 428 finishPendingBroadcastLocked(); 429 return; 430 } 431 } else { 432 // Broadcasted power state is asleep. Send awake if needed. 433 if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast 434 || mActualPowerState == POWER_STATE_AWAKE) { 435 mPendingWakeUpBroadcast = false; 436 mBroadcastedPowerState = POWER_STATE_AWAKE; 437 } else { 438 finishPendingBroadcastLocked(); 439 return; 440 } 441 } 442 443 mBroadcastStartTime = SystemClock.uptimeMillis(); 444 powerState = mBroadcastedPowerState; 445 goToSleepReason = mLastGoToSleepReason; 446 } 447 448 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_SEND, 1); 449 450 if (powerState == POWER_STATE_AWAKE) { 451 sendWakeUpBroadcast(); 452 } else { 453 sendGoToSleepBroadcast(goToSleepReason); 454 } 455 } 456 457 private void sendWakeUpBroadcast() { 458 if (DEBUG) { 459 Slog.d(TAG, "Sending wake up broadcast."); 460 } 461 462 EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, 0, 0, 0); 463 464 mPolicy.screenTurningOn(mScreenOnListener); 465 466 try { 467 ActivityManagerNative.getDefault().wakingUp(); 468 } catch (RemoteException e) { 469 // ignore it 470 } 471 472 if (ActivityManagerNative.isSystemReady()) { 473 mContext.sendOrderedBroadcastAsUser(mScreenOnIntent, UserHandle.ALL, null, 474 mWakeUpBroadcastDone, mHandler, 0, null, null); 475 } else { 476 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 2, 1); 477 sendNextBroadcast(); 478 } 479 } 480 481 private final WindowManagerPolicy.ScreenOnListener mScreenOnListener = 482 new WindowManagerPolicy.ScreenOnListener() { 483 @Override 484 public void onScreenOn() { 485 synchronized (mLock) { 486 if (mScreenOnBlockerAcquired && !mPendingWakeUpBroadcast) { 487 mScreenOnBlockerAcquired = false; 488 mScreenOnBlocker.release(); 489 } 490 } 491 } 492 }; 493 494 private final BroadcastReceiver mWakeUpBroadcastDone = new BroadcastReceiver() { 495 @Override 496 public void onReceive(Context context, Intent intent) { 497 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 1, 498 SystemClock.uptimeMillis() - mBroadcastStartTime, 1); 499 sendNextBroadcast(); 500 } 501 }; 502 503 private void sendGoToSleepBroadcast(int reason) { 504 if (DEBUG) { 505 Slog.d(TAG, "Sending go to sleep broadcast."); 506 } 507 508 int why = WindowManagerPolicy.OFF_BECAUSE_OF_USER; 509 switch (reason) { 510 case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN: 511 why = WindowManagerPolicy.OFF_BECAUSE_OF_ADMIN; 512 break; 513 case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT: 514 why = WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT; 515 break; 516 } 517 518 EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0, why, 0, 0); 519 520 mPolicy.screenTurnedOff(why); 521 try { 522 ActivityManagerNative.getDefault().goingToSleep(); 523 } catch (RemoteException e) { 524 // ignore it. 525 } 526 527 if (ActivityManagerNative.isSystemReady()) { 528 mContext.sendOrderedBroadcastAsUser(mScreenOffIntent, UserHandle.ALL, null, 529 mGoToSleepBroadcastDone, mHandler, 0, null, null); 530 } else { 531 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 3, 1); 532 sendNextBroadcast(); 533 } 534 } 535 536 private final BroadcastReceiver mGoToSleepBroadcastDone = new BroadcastReceiver() { 537 @Override 538 public void onReceive(Context context, Intent intent) { 539 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 0, 540 SystemClock.uptimeMillis() - mBroadcastStartTime, 1); 541 sendNextBroadcast(); 542 } 543 }; 544 545 private void playWirelessChargingStartedSound() { 546 final String soundPath = Settings.Global.getString(mContext.getContentResolver(), 547 Settings.Global.WIRELESS_CHARGING_STARTED_SOUND); 548 if (soundPath != null) { 549 final Uri soundUri = Uri.parse("file://" + soundPath); 550 if (soundUri != null) { 551 final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri); 552 if (sfx != null) { 553 sfx.setStreamType(AudioManager.STREAM_SYSTEM); 554 sfx.play(); 555 } 556 } 557 } 558 559 mSuspendBlocker.release(); 560 } 561 562 private final class NotifierHandler extends Handler { 563 public NotifierHandler(Looper looper) { 564 super(looper, null, true /*async*/); 565 } 566 567 @Override 568 public void handleMessage(Message msg) { 569 switch (msg.what) { 570 case MSG_USER_ACTIVITY: 571 sendUserActivity(); 572 break; 573 574 case MSG_BROADCAST: 575 sendNextBroadcast(); 576 break; 577 578 case MSG_WIRELESS_CHARGING_STARTED: 579 playWirelessChargingStartedSound(); 580 break; 581 } 582 } 583 } 584} 585