Notifier.java revision 3d658bf20e2d56e36941e7407deebeec1276fbcf
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) { 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, monitorType, 147 unimportantForLogging); 148 } else { 149 mBatteryStats.noteStartWakelock(ownerUid, ownerPid, tag, monitorType, 150 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 released. 162 */ 163 public void onWakeLockReleased(int flags, String tag, String packageName, 164 int ownerUid, int ownerPid, WorkSource workSource) { 165 if (DEBUG) { 166 Slog.d(TAG, "onWakeLockReleased: flags=" + flags + ", tag=\"" + tag 167 + "\", packageName=" + packageName 168 + ", ownerUid=" + ownerUid + ", ownerPid=" + ownerPid 169 + ", workSource=" + workSource); 170 } 171 172 try { 173 final int monitorType = getBatteryStatsWakeLockMonitorType(flags); 174 if (workSource != null) { 175 mBatteryStats.noteStopWakelockFromSource(workSource, ownerPid, tag, monitorType); 176 } else { 177 mBatteryStats.noteStopWakelock(ownerUid, ownerPid, tag, monitorType); 178 mAppOps.finishOperation(AppOpsManager.getToken(mAppOps), 179 AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName); 180 } 181 } catch (RemoteException ex) { 182 // Ignore 183 } 184 } 185 186 private static int getBatteryStatsWakeLockMonitorType(int flags) { 187 switch (flags & PowerManager.WAKE_LOCK_LEVEL_MASK) { 188 case PowerManager.PARTIAL_WAKE_LOCK: 189 case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK: 190 return BatteryStats.WAKE_TYPE_PARTIAL; 191 default: 192 return BatteryStats.WAKE_TYPE_FULL; 193 } 194 } 195 196 /** 197 * Called when the screen is turned on. 198 */ 199 public void onScreenOn() { 200 if (DEBUG) { 201 Slog.d(TAG, "onScreenOn"); 202 } 203 204 try { 205 mBatteryStats.noteScreenOn(); 206 } catch (RemoteException ex) { 207 // Ignore 208 } 209 } 210 211 /** 212 * Called when the screen is turned off. 213 */ 214 public void onScreenOff() { 215 if (DEBUG) { 216 Slog.d(TAG, "onScreenOff"); 217 } 218 219 try { 220 mBatteryStats.noteScreenOff(); 221 } catch (RemoteException ex) { 222 // Ignore 223 } 224 } 225 226 /** 227 * Called when the screen changes brightness. 228 */ 229 public void onScreenBrightness(int brightness) { 230 if (DEBUG) { 231 Slog.d(TAG, "onScreenBrightness: brightness=" + brightness); 232 } 233 234 try { 235 mBatteryStats.noteScreenBrightness(brightness); 236 } catch (RemoteException ex) { 237 // Ignore 238 } 239 } 240 241 /** 242 * Called when the device is waking up from sleep and the 243 * display is about to be turned on. 244 */ 245 public void onWakeUpStarted() { 246 if (DEBUG) { 247 Slog.d(TAG, "onWakeUpStarted"); 248 } 249 250 synchronized (mLock) { 251 if (mActualPowerState != POWER_STATE_AWAKE) { 252 mActualPowerState = POWER_STATE_AWAKE; 253 mPendingWakeUpBroadcast = true; 254 if (!mScreenOnBlockerAcquired) { 255 mScreenOnBlockerAcquired = true; 256 mScreenOnBlocker.acquire(); 257 } 258 updatePendingBroadcastLocked(); 259 } 260 } 261 } 262 263 /** 264 * Called when the device has finished waking up from sleep 265 * and the display has been turned on. 266 */ 267 public void onWakeUpFinished() { 268 if (DEBUG) { 269 Slog.d(TAG, "onWakeUpFinished"); 270 } 271 } 272 273 /** 274 * Called when the device is going to sleep. 275 */ 276 public void onGoToSleepStarted(int reason) { 277 if (DEBUG) { 278 Slog.d(TAG, "onGoToSleepStarted"); 279 } 280 281 synchronized (mLock) { 282 mLastGoToSleepReason = reason; 283 } 284 } 285 286 /** 287 * Called when the device has finished going to sleep and the 288 * display has been turned off. 289 * 290 * This is a good time to make transitions that we don't want the user to see, 291 * such as bringing the key guard to focus. There's no guarantee for this, 292 * however because the user could turn the device on again at any time. 293 * Some things may need to be protected by other mechanisms that defer screen on. 294 */ 295 public void onGoToSleepFinished() { 296 if (DEBUG) { 297 Slog.d(TAG, "onGoToSleepFinished"); 298 } 299 300 synchronized (mLock) { 301 if (mActualPowerState != POWER_STATE_ASLEEP) { 302 mActualPowerState = POWER_STATE_ASLEEP; 303 mPendingGoToSleepBroadcast = true; 304 if (mUserActivityPending) { 305 mUserActivityPending = false; 306 mHandler.removeMessages(MSG_USER_ACTIVITY); 307 } 308 updatePendingBroadcastLocked(); 309 } 310 } 311 } 312 313 /** 314 * Called when there has been user activity. 315 */ 316 public void onUserActivity(int event, int uid) { 317 if (DEBUG) { 318 Slog.d(TAG, "onUserActivity: event=" + event + ", uid=" + uid); 319 } 320 321 try { 322 mBatteryStats.noteUserActivity(uid, event); 323 } catch (RemoteException ex) { 324 // Ignore 325 } 326 327 synchronized (mLock) { 328 if (!mUserActivityPending) { 329 mUserActivityPending = true; 330 Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY); 331 msg.setAsynchronous(true); 332 mHandler.sendMessage(msg); 333 } 334 } 335 } 336 337 /** 338 * Called when wireless charging has started so as to provide user feedback. 339 */ 340 public void onWirelessChargingStarted() { 341 if (DEBUG) { 342 Slog.d(TAG, "onWirelessChargingStarted"); 343 } 344 345 mSuspendBlocker.acquire(); 346 Message msg = mHandler.obtainMessage(MSG_WIRELESS_CHARGING_STARTED); 347 msg.setAsynchronous(true); 348 mHandler.sendMessage(msg); 349 } 350 351 private void updatePendingBroadcastLocked() { 352 if (!mBroadcastInProgress 353 && mActualPowerState != POWER_STATE_UNKNOWN 354 && (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast 355 || mActualPowerState != mBroadcastedPowerState)) { 356 mBroadcastInProgress = true; 357 mSuspendBlocker.acquire(); 358 Message msg = mHandler.obtainMessage(MSG_BROADCAST); 359 msg.setAsynchronous(true); 360 mHandler.sendMessage(msg); 361 } 362 } 363 364 private void finishPendingBroadcastLocked() { 365 mBroadcastInProgress = false; 366 mSuspendBlocker.release(); 367 } 368 369 private void sendUserActivity() { 370 synchronized (mLock) { 371 if (!mUserActivityPending) { 372 return; 373 } 374 mUserActivityPending = false; 375 } 376 377 mPolicy.userActivity(); 378 } 379 380 private void sendNextBroadcast() { 381 final int powerState; 382 final int goToSleepReason; 383 synchronized (mLock) { 384 if (mBroadcastedPowerState == POWER_STATE_UNKNOWN) { 385 // Broadcasted power state is unknown. Send wake up. 386 mPendingWakeUpBroadcast = false; 387 mBroadcastedPowerState = POWER_STATE_AWAKE; 388 } else if (mBroadcastedPowerState == POWER_STATE_AWAKE) { 389 // Broadcasted power state is awake. Send asleep if needed. 390 if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast 391 || mActualPowerState == POWER_STATE_ASLEEP) { 392 mPendingGoToSleepBroadcast = false; 393 mBroadcastedPowerState = POWER_STATE_ASLEEP; 394 } else { 395 finishPendingBroadcastLocked(); 396 return; 397 } 398 } else { 399 // Broadcasted power state is asleep. Send awake if needed. 400 if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast 401 || mActualPowerState == POWER_STATE_AWAKE) { 402 mPendingWakeUpBroadcast = false; 403 mBroadcastedPowerState = POWER_STATE_AWAKE; 404 } else { 405 finishPendingBroadcastLocked(); 406 return; 407 } 408 } 409 410 mBroadcastStartTime = SystemClock.uptimeMillis(); 411 powerState = mBroadcastedPowerState; 412 goToSleepReason = mLastGoToSleepReason; 413 } 414 415 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_SEND, 1); 416 417 if (powerState == POWER_STATE_AWAKE) { 418 sendWakeUpBroadcast(); 419 } else { 420 sendGoToSleepBroadcast(goToSleepReason); 421 } 422 } 423 424 private void sendWakeUpBroadcast() { 425 if (DEBUG) { 426 Slog.d(TAG, "Sending wake up broadcast."); 427 } 428 429 EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, 0, 0, 0); 430 431 mPolicy.screenTurningOn(mScreenOnListener); 432 433 try { 434 ActivityManagerNative.getDefault().wakingUp(); 435 } catch (RemoteException e) { 436 // ignore it 437 } 438 439 if (ActivityManagerNative.isSystemReady()) { 440 mContext.sendOrderedBroadcastAsUser(mScreenOnIntent, UserHandle.ALL, null, 441 mWakeUpBroadcastDone, mHandler, 0, null, null); 442 } else { 443 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 2, 1); 444 sendNextBroadcast(); 445 } 446 } 447 448 private final WindowManagerPolicy.ScreenOnListener mScreenOnListener = 449 new WindowManagerPolicy.ScreenOnListener() { 450 @Override 451 public void onScreenOn() { 452 synchronized (mLock) { 453 if (mScreenOnBlockerAcquired && !mPendingWakeUpBroadcast) { 454 mScreenOnBlockerAcquired = false; 455 mScreenOnBlocker.release(); 456 } 457 } 458 } 459 }; 460 461 private final BroadcastReceiver mWakeUpBroadcastDone = new BroadcastReceiver() { 462 @Override 463 public void onReceive(Context context, Intent intent) { 464 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 1, 465 SystemClock.uptimeMillis() - mBroadcastStartTime, 1); 466 sendNextBroadcast(); 467 } 468 }; 469 470 private void sendGoToSleepBroadcast(int reason) { 471 if (DEBUG) { 472 Slog.d(TAG, "Sending go to sleep broadcast."); 473 } 474 475 int why = WindowManagerPolicy.OFF_BECAUSE_OF_USER; 476 switch (reason) { 477 case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN: 478 why = WindowManagerPolicy.OFF_BECAUSE_OF_ADMIN; 479 break; 480 case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT: 481 why = WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT; 482 break; 483 } 484 485 EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0, why, 0, 0); 486 487 mPolicy.screenTurnedOff(why); 488 try { 489 ActivityManagerNative.getDefault().goingToSleep(); 490 } catch (RemoteException e) { 491 // ignore it. 492 } 493 494 if (ActivityManagerNative.isSystemReady()) { 495 mContext.sendOrderedBroadcastAsUser(mScreenOffIntent, UserHandle.ALL, null, 496 mGoToSleepBroadcastDone, mHandler, 0, null, null); 497 } else { 498 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 3, 1); 499 sendNextBroadcast(); 500 } 501 } 502 503 private final BroadcastReceiver mGoToSleepBroadcastDone = new BroadcastReceiver() { 504 @Override 505 public void onReceive(Context context, Intent intent) { 506 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 0, 507 SystemClock.uptimeMillis() - mBroadcastStartTime, 1); 508 sendNextBroadcast(); 509 } 510 }; 511 512 private void playWirelessChargingStartedSound() { 513 final String soundPath = Settings.Global.getString(mContext.getContentResolver(), 514 Settings.Global.WIRELESS_CHARGING_STARTED_SOUND); 515 if (soundPath != null) { 516 final Uri soundUri = Uri.parse("file://" + soundPath); 517 if (soundUri != null) { 518 final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri); 519 if (sfx != null) { 520 sfx.setStreamType(AudioManager.STREAM_SYSTEM); 521 sfx.play(); 522 } 523 } 524 } 525 526 mSuspendBlocker.release(); 527 } 528 529 private final class NotifierHandler extends Handler { 530 public NotifierHandler(Looper looper) { 531 super(looper, null, true /*async*/); 532 } 533 534 @Override 535 public void handleMessage(Message msg) { 536 switch (msg.what) { 537 case MSG_USER_ACTIVITY: 538 sendUserActivity(); 539 break; 540 541 case MSG_BROADCAST: 542 sendNextBroadcast(); 543 break; 544 545 case MSG_WIRELESS_CHARGING_STARTED: 546 playWirelessChargingStartedSound(); 547 break; 548 } 549 } 550 } 551} 552