Notifier.java revision cbefd8dd2befcb768f911a63becc427ec4c13250
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.ActivityManagerInternal; 20import android.app.AppOpsManager; 21 22import com.android.internal.app.IAppOpsService; 23import com.android.internal.app.IBatteryStats; 24import com.android.server.EventLogTags; 25import com.android.server.LocalServices; 26 27import android.app.ActivityManagerNative; 28import android.content.BroadcastReceiver; 29import android.content.Context; 30import android.content.Intent; 31import android.hardware.input.InputManagerInternal; 32import android.media.AudioManager; 33import android.media.Ringtone; 34import android.media.RingtoneManager; 35import android.net.Uri; 36import android.os.BatteryStats; 37import android.os.Handler; 38import android.os.Looper; 39import android.os.Message; 40import android.os.PowerManager; 41import android.os.Process; 42import android.os.RemoteException; 43import android.os.SystemClock; 44import android.os.UserHandle; 45import android.os.WorkSource; 46import android.provider.Settings; 47import android.util.EventLog; 48import android.util.Slog; 49import android.view.WindowManagerPolicy; 50 51/** 52 * Sends broadcasts about important power state changes. 53 * <p> 54 * This methods of this class may be called by the power manager service while 55 * its lock is being held. Internally it takes care of sending broadcasts to 56 * notify other components of the system or applications asynchronously. 57 * </p><p> 58 * The notifier is designed to collapse unnecessary broadcasts when it is not 59 * possible for the system to have observed an intermediate state. 60 * </p><p> 61 * For example, if the device wakes up, goes to sleep, wakes up again and goes to 62 * sleep again before the wake up notification is sent, then the system will 63 * be told about only one wake up and sleep. However, we always notify the 64 * fact that at least one transition occurred. It is especially important to 65 * tell the system when we go to sleep so that it can lock the keyguard if needed. 66 * </p> 67 */ 68final class Notifier { 69 private static final String TAG = "PowerManagerNotifier"; 70 71 private static final boolean DEBUG = false; 72 73 private static final int POWER_STATE_UNKNOWN = 0; 74 private static final int POWER_STATE_AWAKE = 1; 75 private static final int POWER_STATE_ASLEEP = 2; 76 77 private static final int MSG_USER_ACTIVITY = 1; 78 private static final int MSG_BROADCAST = 2; 79 private static final int MSG_WIRELESS_CHARGING_STARTED = 3; 80 81 private final Object mLock = new Object(); 82 83 private final Context mContext; 84 private final IBatteryStats mBatteryStats; 85 private final IAppOpsService mAppOps; 86 private final SuspendBlocker mSuspendBlocker; 87 private final ScreenOnBlocker mScreenOnBlocker; 88 private final WindowManagerPolicy mPolicy; 89 private final ActivityManagerInternal mActivityManagerInternal; 90 private final InputManagerInternal mInputManagerInternal; 91 92 private final NotifierHandler mHandler; 93 private final Intent mScreenOnIntent; 94 private final Intent mScreenOffIntent; 95 96 // The current power state. 97 private int mActualPowerState; 98 private int mLastGoToSleepReason; 99 100 // True if there is a pending transition that needs to be reported. 101 private boolean mPendingWakeUpBroadcast; 102 private boolean mPendingGoToSleepBroadcast; 103 104 // The currently broadcasted power state. This reflects what other parts of the 105 // system have observed. 106 private int mBroadcastedPowerState; 107 private boolean mBroadcastInProgress; 108 private long mBroadcastStartTime; 109 110 // True if a user activity message should be sent. 111 private boolean mUserActivityPending; 112 113 // True if the screen on blocker has been acquired. 114 private boolean mScreenOnBlockerAcquired; 115 116 public Notifier(Looper looper, Context context, IBatteryStats batteryStats, 117 IAppOpsService appOps, SuspendBlocker suspendBlocker, ScreenOnBlocker screenOnBlocker, 118 WindowManagerPolicy policy) { 119 mContext = context; 120 mBatteryStats = batteryStats; 121 mAppOps = appOps; 122 mSuspendBlocker = suspendBlocker; 123 mScreenOnBlocker = screenOnBlocker; 124 mPolicy = policy; 125 mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class); 126 mInputManagerInternal = LocalServices.getService(InputManagerInternal.class); 127 128 mHandler = new NotifierHandler(looper); 129 mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON); 130 mScreenOnIntent.addFlags( 131 Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); 132 mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF); 133 mScreenOffIntent.addFlags( 134 Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); 135 136 // Initialize interactive state for battery stats. 137 try { 138 mBatteryStats.noteInteractive(true); 139 } catch (RemoteException ex) { } 140 } 141 142 /** 143 * Called when a wake lock is acquired. 144 */ 145 public void onWakeLockAcquired(int flags, String tag, String packageName, 146 int ownerUid, int ownerPid, WorkSource workSource, String historyTag) { 147 if (DEBUG) { 148 Slog.d(TAG, "onWakeLockAcquired: flags=" + flags + ", tag=\"" + tag 149 + "\", packageName=" + packageName 150 + ", ownerUid=" + ownerUid + ", ownerPid=" + ownerPid 151 + ", workSource=" + workSource); 152 } 153 154 try { 155 final int monitorType = getBatteryStatsWakeLockMonitorType(flags); 156 boolean unimportantForLogging = (flags&PowerManager.UNIMPORTANT_FOR_LOGGING) != 0 157 && ownerUid == Process.SYSTEM_UID; 158 if (workSource != null) { 159 mBatteryStats.noteStartWakelockFromSource(workSource, ownerPid, tag, historyTag, 160 monitorType, unimportantForLogging); 161 } else { 162 mBatteryStats.noteStartWakelock(ownerUid, ownerPid, tag, historyTag, 163 monitorType, unimportantForLogging); 164 // XXX need to deal with disabled operations. 165 mAppOps.startOperation(AppOpsManager.getToken(mAppOps), 166 AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName); 167 } 168 } catch (RemoteException ex) { 169 // Ignore 170 } 171 } 172 173 /** 174 * Called when a wake lock is changing. 175 */ 176 public void onWakeLockChanging(int flags, String tag, String packageName, 177 int ownerUid, int ownerPid, WorkSource workSource, String historyTag, 178 int newFlags, String newTag, String newPackageName, int newOwnerUid, 179 int newOwnerPid, WorkSource newWorkSource, String newHistoryTag) { 180 181 if (workSource != null && newWorkSource != null) { 182 final int monitorType = getBatteryStatsWakeLockMonitorType(flags); 183 final int newMonitorType = getBatteryStatsWakeLockMonitorType(newFlags); 184 boolean unimportantForLogging = (newFlags&PowerManager.UNIMPORTANT_FOR_LOGGING) != 0 185 && newOwnerUid == Process.SYSTEM_UID; 186 if (DEBUG) { 187 Slog.d(TAG, "onWakeLockChanging: flags=" + newFlags + ", tag=\"" + newTag 188 + "\", packageName=" + newPackageName 189 + ", ownerUid=" + newOwnerUid + ", ownerPid=" + newOwnerPid 190 + ", workSource=" + newWorkSource); 191 } 192 try { 193 mBatteryStats.noteChangeWakelockFromSource(workSource, ownerPid, tag, historyTag, 194 monitorType, newWorkSource, newOwnerPid, newTag, newHistoryTag, 195 newMonitorType, unimportantForLogging); 196 } catch (RemoteException ex) { 197 // Ignore 198 } 199 } else { 200 onWakeLockReleased(flags, tag, packageName, ownerUid, ownerPid, workSource, historyTag); 201 onWakeLockAcquired(newFlags, newTag, newPackageName, newOwnerUid, newOwnerPid, 202 newWorkSource, newHistoryTag); 203 } 204 } 205 206 /** 207 * Called when a wake lock is released. 208 */ 209 public void onWakeLockReleased(int flags, String tag, String packageName, 210 int ownerUid, int ownerPid, WorkSource workSource, String historyTag) { 211 if (DEBUG) { 212 Slog.d(TAG, "onWakeLockReleased: flags=" + flags + ", tag=\"" + tag 213 + "\", packageName=" + packageName 214 + ", ownerUid=" + ownerUid + ", ownerPid=" + ownerPid 215 + ", workSource=" + workSource); 216 } 217 218 try { 219 final int monitorType = getBatteryStatsWakeLockMonitorType(flags); 220 if (workSource != null) { 221 mBatteryStats.noteStopWakelockFromSource(workSource, ownerPid, tag, historyTag, 222 monitorType); 223 } else { 224 mBatteryStats.noteStopWakelock(ownerUid, ownerPid, tag, historyTag, monitorType); 225 mAppOps.finishOperation(AppOpsManager.getToken(mAppOps), 226 AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName); 227 } 228 } catch (RemoteException ex) { 229 // Ignore 230 } 231 } 232 233 private static int getBatteryStatsWakeLockMonitorType(int flags) { 234 switch (flags & PowerManager.WAKE_LOCK_LEVEL_MASK) { 235 case PowerManager.PARTIAL_WAKE_LOCK: 236 case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK: 237 return BatteryStats.WAKE_TYPE_PARTIAL; 238 default: 239 return BatteryStats.WAKE_TYPE_FULL; 240 } 241 } 242 243 /** 244 * Notifies that the device is changing interactive state. 245 */ 246 public void onInteractiveStateChangeStarted(boolean interactive, int reason) { 247 if (DEBUG) { 248 Slog.d(TAG, "onInteractiveChangeStarted: interactive=" + interactive 249 + ", reason=" + reason); 250 } 251 252 synchronized (mLock) { 253 if (interactive) { 254 // Waking up... 255 if (mActualPowerState != POWER_STATE_AWAKE) { 256 mActualPowerState = POWER_STATE_AWAKE; 257 mPendingWakeUpBroadcast = true; 258 if (!mScreenOnBlockerAcquired) { 259 mScreenOnBlockerAcquired = true; 260 mScreenOnBlocker.acquire(); 261 } 262 updatePendingBroadcastLocked(); 263 } 264 } else { 265 // Going to sleep... 266 mLastGoToSleepReason = reason; 267 } 268 } 269 270 mInputManagerInternal.setInteractive(interactive); 271 272 if (interactive) { 273 try { 274 mBatteryStats.noteInteractive(true); 275 } catch (RemoteException ex) { } 276 } 277 } 278 279 /** 280 * Notifies that the device has finished changing interactive state. 281 */ 282 public void onInteractiveStateChangeFinished(boolean interactive) { 283 if (DEBUG) { 284 Slog.d(TAG, "onInteractiveChangeFinished"); 285 } 286 287 synchronized (mLock) { 288 if (!interactive) { 289 // Finished going to sleep... 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 if (mActualPowerState != POWER_STATE_ASLEEP) { 295 mActualPowerState = POWER_STATE_ASLEEP; 296 mPendingGoToSleepBroadcast = true; 297 if (mUserActivityPending) { 298 mUserActivityPending = false; 299 mHandler.removeMessages(MSG_USER_ACTIVITY); 300 } 301 updatePendingBroadcastLocked(); 302 } 303 } 304 } 305 306 if (!interactive) { 307 try { 308 mBatteryStats.noteInteractive(false); 309 } catch (RemoteException ex) { } 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.wakingUp(mScreenOnListener); 432 mActivityManagerInternal.wakingUp(); 433 434 if (ActivityManagerNative.isSystemReady()) { 435 mContext.sendOrderedBroadcastAsUser(mScreenOnIntent, UserHandle.ALL, null, 436 mWakeUpBroadcastDone, mHandler, 0, null, null); 437 } else { 438 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 2, 1); 439 sendNextBroadcast(); 440 } 441 } 442 443 private final WindowManagerPolicy.ScreenOnListener mScreenOnListener = 444 new WindowManagerPolicy.ScreenOnListener() { 445 @Override 446 public void onScreenOn() { 447 synchronized (mLock) { 448 if (mScreenOnBlockerAcquired && !mPendingWakeUpBroadcast) { 449 mScreenOnBlockerAcquired = false; 450 mScreenOnBlocker.release(); 451 } 452 } 453 } 454 }; 455 456 private final BroadcastReceiver mWakeUpBroadcastDone = new BroadcastReceiver() { 457 @Override 458 public void onReceive(Context context, Intent intent) { 459 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 1, 460 SystemClock.uptimeMillis() - mBroadcastStartTime, 1); 461 sendNextBroadcast(); 462 } 463 }; 464 465 private void sendGoToSleepBroadcast(int reason) { 466 if (DEBUG) { 467 Slog.d(TAG, "Sending go to sleep broadcast."); 468 } 469 470 int why = WindowManagerPolicy.OFF_BECAUSE_OF_USER; 471 switch (reason) { 472 case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN: 473 why = WindowManagerPolicy.OFF_BECAUSE_OF_ADMIN; 474 break; 475 case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT: 476 why = WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT; 477 break; 478 } 479 480 EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0, why, 0, 0); 481 482 mPolicy.goingToSleep(why); 483 mActivityManagerInternal.goingToSleep(); 484 485 if (ActivityManagerNative.isSystemReady()) { 486 mContext.sendOrderedBroadcastAsUser(mScreenOffIntent, UserHandle.ALL, null, 487 mGoToSleepBroadcastDone, mHandler, 0, null, null); 488 } else { 489 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 3, 1); 490 sendNextBroadcast(); 491 } 492 } 493 494 private final BroadcastReceiver mGoToSleepBroadcastDone = new BroadcastReceiver() { 495 @Override 496 public void onReceive(Context context, Intent intent) { 497 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 0, 498 SystemClock.uptimeMillis() - mBroadcastStartTime, 1); 499 sendNextBroadcast(); 500 } 501 }; 502 503 private void playWirelessChargingStartedSound() { 504 final String soundPath = Settings.Global.getString(mContext.getContentResolver(), 505 Settings.Global.WIRELESS_CHARGING_STARTED_SOUND); 506 if (soundPath != null) { 507 final Uri soundUri = Uri.parse("file://" + soundPath); 508 if (soundUri != null) { 509 final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri); 510 if (sfx != null) { 511 sfx.setStreamType(AudioManager.STREAM_SYSTEM); 512 sfx.play(); 513 } 514 } 515 } 516 517 mSuspendBlocker.release(); 518 } 519 520 private final class NotifierHandler extends Handler { 521 public NotifierHandler(Looper looper) { 522 super(looper, null, true /*async*/); 523 } 524 525 @Override 526 public void handleMessage(Message msg) { 527 switch (msg.what) { 528 case MSG_USER_ACTIVITY: 529 sendUserActivity(); 530 break; 531 532 case MSG_BROADCAST: 533 sendNextBroadcast(); 534 break; 535 536 case MSG_WIRELESS_CHARGING_STARTED: 537 playWirelessChargingStartedSound(); 538 break; 539 } 540 } 541 } 542} 543