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