Notifier.java revision 13014b5fe5967b3c7e232ffaf81581ed178e6df6
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.media.AudioManager; 32import android.media.Ringtone; 33import android.media.RingtoneManager; 34import android.net.Uri; 35import android.os.BatteryStats; 36import android.os.Handler; 37import android.os.Looper; 38import android.os.Message; 39import android.os.PowerManager; 40import android.os.RemoteException; 41import android.os.SystemClock; 42import android.os.UserHandle; 43import android.os.WorkSource; 44import android.provider.Settings; 45import android.util.EventLog; 46import android.util.Slog; 47import android.view.WindowManagerPolicy; 48 49/** 50 * Sends broadcasts about important power state changes. 51 * <p> 52 * This methods of this class may be called by the power manager service while 53 * its lock is being held. Internally it takes care of sending broadcasts to 54 * notify other components of the system or applications asynchronously. 55 * </p><p> 56 * The notifier is designed to collapse unnecessary broadcasts when it is not 57 * possible for the system to have observed an intermediate state. 58 * </p><p> 59 * For example, if the device wakes up, goes to sleep, wakes up again and goes to 60 * sleep again before the wake up notification is sent, then the system will 61 * be told about only one wake up and sleep. However, we always notify the 62 * fact that at least one transition occurred. It is especially important to 63 * tell the system when we go to sleep so that it can lock the keyguard if needed. 64 * </p> 65 */ 66final class Notifier { 67 private static final String TAG = "PowerManagerNotifier"; 68 69 private static final boolean DEBUG = false; 70 71 private static final int POWER_STATE_UNKNOWN = 0; 72 private static final int POWER_STATE_AWAKE = 1; 73 private static final int POWER_STATE_ASLEEP = 2; 74 75 private static final int MSG_USER_ACTIVITY = 1; 76 private static final int MSG_BROADCAST = 2; 77 private static final int MSG_WIRELESS_CHARGING_STARTED = 3; 78 79 private final Object mLock = new Object(); 80 81 private final Context mContext; 82 private final IBatteryStats mBatteryStats; 83 private final IAppOpsService mAppOps; 84 private final SuspendBlocker mSuspendBlocker; 85 private final ScreenOnBlocker mScreenOnBlocker; 86 private final WindowManagerPolicy mPolicy; 87 private final ActivityManagerInternal mActivityManagerInternal; 88 89 private final NotifierHandler mHandler; 90 private final Intent mScreenOnIntent; 91 private final Intent mScreenOffIntent; 92 93 // The current power state. 94 private int mActualPowerState; 95 private int mLastGoToSleepReason; 96 97 // True if there is a pending transition that needs to be reported. 98 private boolean mPendingWakeUpBroadcast; 99 private boolean mPendingGoToSleepBroadcast; 100 101 // The currently broadcasted power state. This reflects what other parts of the 102 // system have observed. 103 private int mBroadcastedPowerState; 104 private boolean mBroadcastInProgress; 105 private long mBroadcastStartTime; 106 107 // True if a user activity message should be sent. 108 private boolean mUserActivityPending; 109 110 // True if the screen on blocker has been acquired. 111 private boolean mScreenOnBlockerAcquired; 112 113 public Notifier(Looper looper, Context context, IBatteryStats batteryStats, 114 IAppOpsService appOps, SuspendBlocker suspendBlocker, ScreenOnBlocker screenOnBlocker, 115 WindowManagerPolicy policy) { 116 mContext = context; 117 mBatteryStats = batteryStats; 118 mAppOps = appOps; 119 mSuspendBlocker = suspendBlocker; 120 mScreenOnBlocker = screenOnBlocker; 121 mPolicy = policy; 122 mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class); 123 124 mHandler = new NotifierHandler(looper); 125 mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON); 126 mScreenOnIntent.addFlags( 127 Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); 128 mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF); 129 mScreenOffIntent.addFlags( 130 Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); 131 } 132 133 /** 134 * Called when a wake lock is acquired. 135 */ 136 public void onWakeLockAcquired(int flags, String tag, String packageName, 137 int ownerUid, int ownerPid, WorkSource workSource) { 138 if (DEBUG) { 139 Slog.d(TAG, "onWakeLockAcquired: flags=" + flags + ", tag=\"" + tag 140 + "\", packageName=" + packageName 141 + ", ownerUid=" + ownerUid + ", ownerPid=" + ownerPid 142 + ", workSource=" + workSource); 143 } 144 145 try { 146 final int monitorType = getBatteryStatsWakeLockMonitorType(flags); 147 if (workSource != null) { 148 mBatteryStats.noteStartWakelockFromSource(workSource, ownerPid, tag, monitorType); 149 } else { 150 mBatteryStats.noteStartWakelock(ownerUid, ownerPid, tag, monitorType); 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 device is waking up from sleep and the 198 * display is about to be turned on. 199 */ 200 public void onWakeUpStarted() { 201 if (DEBUG) { 202 Slog.d(TAG, "onWakeUpStarted"); 203 } 204 205 synchronized (mLock) { 206 if (mActualPowerState != POWER_STATE_AWAKE) { 207 mActualPowerState = POWER_STATE_AWAKE; 208 mPendingWakeUpBroadcast = true; 209 if (!mScreenOnBlockerAcquired) { 210 mScreenOnBlockerAcquired = true; 211 mScreenOnBlocker.acquire(); 212 } 213 updatePendingBroadcastLocked(); 214 } 215 } 216 } 217 218 /** 219 * Called when the device has finished waking up from sleep 220 * and the display has been turned on. 221 */ 222 public void onWakeUpFinished() { 223 if (DEBUG) { 224 Slog.d(TAG, "onWakeUpFinished"); 225 } 226 } 227 228 /** 229 * Called when the device is going to sleep. 230 */ 231 public void onGoToSleepStarted(int reason) { 232 if (DEBUG) { 233 Slog.d(TAG, "onGoToSleepStarted"); 234 } 235 236 synchronized (mLock) { 237 mLastGoToSleepReason = reason; 238 } 239 } 240 241 /** 242 * Called when the device has finished going to sleep and the 243 * display has been turned off. 244 * 245 * This is a good time to make transitions that we don't want the user to see, 246 * such as bringing the key guard to focus. There's no guarantee for this, 247 * however because the user could turn the device on again at any time. 248 * Some things may need to be protected by other mechanisms that defer screen on. 249 */ 250 public void onGoToSleepFinished() { 251 if (DEBUG) { 252 Slog.d(TAG, "onGoToSleepFinished"); 253 } 254 255 synchronized (mLock) { 256 if (mActualPowerState != POWER_STATE_ASLEEP) { 257 mActualPowerState = POWER_STATE_ASLEEP; 258 mPendingGoToSleepBroadcast = true; 259 if (mUserActivityPending) { 260 mUserActivityPending = false; 261 mHandler.removeMessages(MSG_USER_ACTIVITY); 262 } 263 updatePendingBroadcastLocked(); 264 } 265 } 266 } 267 268 /** 269 * Called when there has been user activity. 270 */ 271 public void onUserActivity(int event, int uid) { 272 if (DEBUG) { 273 Slog.d(TAG, "onUserActivity: event=" + event + ", uid=" + uid); 274 } 275 276 try { 277 mBatteryStats.noteUserActivity(uid, event); 278 } catch (RemoteException ex) { 279 // Ignore 280 } 281 282 synchronized (mLock) { 283 if (!mUserActivityPending) { 284 mUserActivityPending = true; 285 Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY); 286 msg.setAsynchronous(true); 287 mHandler.sendMessage(msg); 288 } 289 } 290 } 291 292 /** 293 * Called when wireless charging has started so as to provide user feedback. 294 */ 295 public void onWirelessChargingStarted() { 296 if (DEBUG) { 297 Slog.d(TAG, "onWirelessChargingStarted"); 298 } 299 300 mSuspendBlocker.acquire(); 301 Message msg = mHandler.obtainMessage(MSG_WIRELESS_CHARGING_STARTED); 302 msg.setAsynchronous(true); 303 mHandler.sendMessage(msg); 304 } 305 306 private void updatePendingBroadcastLocked() { 307 if (!mBroadcastInProgress 308 && mActualPowerState != POWER_STATE_UNKNOWN 309 && (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast 310 || mActualPowerState != mBroadcastedPowerState)) { 311 mBroadcastInProgress = true; 312 mSuspendBlocker.acquire(); 313 Message msg = mHandler.obtainMessage(MSG_BROADCAST); 314 msg.setAsynchronous(true); 315 mHandler.sendMessage(msg); 316 } 317 } 318 319 private void finishPendingBroadcastLocked() { 320 mBroadcastInProgress = false; 321 mSuspendBlocker.release(); 322 } 323 324 private void sendUserActivity() { 325 synchronized (mLock) { 326 if (!mUserActivityPending) { 327 return; 328 } 329 mUserActivityPending = false; 330 } 331 332 mPolicy.userActivity(); 333 } 334 335 private void sendNextBroadcast() { 336 final int powerState; 337 final int goToSleepReason; 338 synchronized (mLock) { 339 if (mBroadcastedPowerState == POWER_STATE_UNKNOWN) { 340 // Broadcasted power state is unknown. Send wake up. 341 mPendingWakeUpBroadcast = false; 342 mBroadcastedPowerState = POWER_STATE_AWAKE; 343 } else if (mBroadcastedPowerState == POWER_STATE_AWAKE) { 344 // Broadcasted power state is awake. Send asleep if needed. 345 if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast 346 || mActualPowerState == POWER_STATE_ASLEEP) { 347 mPendingGoToSleepBroadcast = false; 348 mBroadcastedPowerState = POWER_STATE_ASLEEP; 349 } else { 350 finishPendingBroadcastLocked(); 351 return; 352 } 353 } else { 354 // Broadcasted power state is asleep. Send awake if needed. 355 if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast 356 || mActualPowerState == POWER_STATE_AWAKE) { 357 mPendingWakeUpBroadcast = false; 358 mBroadcastedPowerState = POWER_STATE_AWAKE; 359 } else { 360 finishPendingBroadcastLocked(); 361 return; 362 } 363 } 364 365 mBroadcastStartTime = SystemClock.uptimeMillis(); 366 powerState = mBroadcastedPowerState; 367 goToSleepReason = mLastGoToSleepReason; 368 } 369 370 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_SEND, 1); 371 372 if (powerState == POWER_STATE_AWAKE) { 373 sendWakeUpBroadcast(); 374 } else { 375 sendGoToSleepBroadcast(goToSleepReason); 376 } 377 } 378 379 private void sendWakeUpBroadcast() { 380 if (DEBUG) { 381 Slog.d(TAG, "Sending wake up broadcast."); 382 } 383 384 EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, 0, 0, 0); 385 386 mPolicy.screenTurningOn(mScreenOnListener); 387 mActivityManagerInternal.wakingUp(); 388 389 if (ActivityManagerNative.isSystemReady()) { 390 mContext.sendOrderedBroadcastAsUser(mScreenOnIntent, UserHandle.ALL, null, 391 mWakeUpBroadcastDone, mHandler, 0, null, null); 392 } else { 393 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 2, 1); 394 sendNextBroadcast(); 395 } 396 } 397 398 private final WindowManagerPolicy.ScreenOnListener mScreenOnListener = 399 new WindowManagerPolicy.ScreenOnListener() { 400 @Override 401 public void onScreenOn() { 402 synchronized (mLock) { 403 if (mScreenOnBlockerAcquired && !mPendingWakeUpBroadcast) { 404 mScreenOnBlockerAcquired = false; 405 mScreenOnBlocker.release(); 406 } 407 } 408 } 409 }; 410 411 private final BroadcastReceiver mWakeUpBroadcastDone = new BroadcastReceiver() { 412 @Override 413 public void onReceive(Context context, Intent intent) { 414 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 1, 415 SystemClock.uptimeMillis() - mBroadcastStartTime, 1); 416 sendNextBroadcast(); 417 } 418 }; 419 420 private void sendGoToSleepBroadcast(int reason) { 421 if (DEBUG) { 422 Slog.d(TAG, "Sending go to sleep broadcast."); 423 } 424 425 int why = WindowManagerPolicy.OFF_BECAUSE_OF_USER; 426 switch (reason) { 427 case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN: 428 why = WindowManagerPolicy.OFF_BECAUSE_OF_ADMIN; 429 break; 430 case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT: 431 why = WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT; 432 break; 433 } 434 435 EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0, why, 0, 0); 436 437 mPolicy.screenTurnedOff(why); 438 mActivityManagerInternal.goingToSleep(); 439 440 if (ActivityManagerNative.isSystemReady()) { 441 mContext.sendOrderedBroadcastAsUser(mScreenOffIntent, UserHandle.ALL, null, 442 mGoToSleepBroadcastDone, mHandler, 0, null, null); 443 } else { 444 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 3, 1); 445 sendNextBroadcast(); 446 } 447 } 448 449 private final BroadcastReceiver mGoToSleepBroadcastDone = new BroadcastReceiver() { 450 @Override 451 public void onReceive(Context context, Intent intent) { 452 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 0, 453 SystemClock.uptimeMillis() - mBroadcastStartTime, 1); 454 sendNextBroadcast(); 455 } 456 }; 457 458 private void playWirelessChargingStartedSound() { 459 final String soundPath = Settings.Global.getString(mContext.getContentResolver(), 460 Settings.Global.WIRELESS_CHARGING_STARTED_SOUND); 461 if (soundPath != null) { 462 final Uri soundUri = Uri.parse("file://" + soundPath); 463 if (soundUri != null) { 464 final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri); 465 if (sfx != null) { 466 sfx.setStreamType(AudioManager.STREAM_SYSTEM); 467 sfx.play(); 468 } 469 } 470 } 471 472 mSuspendBlocker.release(); 473 } 474 475 private final class NotifierHandler extends Handler { 476 public NotifierHandler(Looper looper) { 477 super(looper, null, true /*async*/); 478 } 479 480 @Override 481 public void handleMessage(Message msg) { 482 switch (msg.what) { 483 case MSG_USER_ACTIVITY: 484 sendUserActivity(); 485 break; 486 487 case MSG_BROADCAST: 488 sendNextBroadcast(); 489 break; 490 491 case MSG_WIRELESS_CHARGING_STARTED: 492 playWirelessChargingStartedSound(); 493 break; 494 } 495 } 496 } 497} 498