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