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