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