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