Notifier.java revision 5ac72a29593ab9a20337a2225df52bdf4754be02
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; 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 try { 121 final int monitorType = getBatteryStatsWakeLockMonitorType(flags); 122 if (workSource != null) { 123 mBatteryStats.noteStartWakelockFromSource(workSource, ownerPid, tag, monitorType); 124 } else { 125 mBatteryStats.noteStartWakelock(ownerUid, ownerPid, tag, monitorType); 126 } 127 } catch (RemoteException ex) { 128 // Ignore 129 } 130 } 131 132 /** 133 * Called when a wake lock is released. 134 */ 135 public void onWakeLockReleased(int flags, String tag, int ownerUid, int ownerPid, 136 WorkSource workSource) { 137 if (DEBUG) { 138 Slog.d(TAG, "onWakeLockReleased: flags=" + flags + ", tag=\"" + tag 139 + "\", ownerUid=" + ownerUid + ", ownerPid=" + ownerPid 140 + ", workSource=" + workSource); 141 } 142 143 try { 144 final int monitorType = getBatteryStatsWakeLockMonitorType(flags); 145 if (workSource != null) { 146 mBatteryStats.noteStopWakelockFromSource(workSource, ownerPid, tag, monitorType); 147 } else { 148 mBatteryStats.noteStopWakelock(ownerUid, ownerPid, tag, monitorType); 149 } 150 } catch (RemoteException ex) { 151 // Ignore 152 } 153 } 154 155 private static int getBatteryStatsWakeLockMonitorType(int flags) { 156 switch (flags & PowerManager.WAKE_LOCK_LEVEL_MASK) { 157 case PowerManager.PARTIAL_WAKE_LOCK: 158 case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK: 159 return BatteryStats.WAKE_TYPE_PARTIAL; 160 default: 161 return BatteryStats.WAKE_TYPE_FULL; 162 } 163 } 164 165 /** 166 * Called when the screen is turned on. 167 */ 168 public void onScreenOn() { 169 if (DEBUG) { 170 Slog.d(TAG, "onScreenOn"); 171 } 172 173 try { 174 mBatteryStats.noteScreenOn(); 175 } catch (RemoteException ex) { 176 // Ignore 177 } 178 } 179 180 /** 181 * Called when the screen is turned off. 182 */ 183 public void onScreenOff() { 184 if (DEBUG) { 185 Slog.d(TAG, "onScreenOff"); 186 } 187 188 try { 189 mBatteryStats.noteScreenOff(); 190 } catch (RemoteException ex) { 191 // Ignore 192 } 193 } 194 195 /** 196 * Called when the screen changes brightness. 197 */ 198 public void onScreenBrightness(int brightness) { 199 if (DEBUG) { 200 Slog.d(TAG, "onScreenBrightness: brightness=" + brightness); 201 } 202 203 try { 204 mBatteryStats.noteScreenBrightness(brightness); 205 } catch (RemoteException ex) { 206 // Ignore 207 } 208 } 209 210 /** 211 * Called when the device is waking up from sleep and the 212 * display is about to be turned on. 213 */ 214 public void onWakeUpStarted() { 215 if (DEBUG) { 216 Slog.d(TAG, "onWakeUpStarted"); 217 } 218 219 synchronized (mLock) { 220 if (mActualPowerState != POWER_STATE_AWAKE) { 221 mActualPowerState = POWER_STATE_AWAKE; 222 updatePendingBroadcastLocked(); 223 } 224 } 225 } 226 227 /** 228 * Called when the device has finished waking up from sleep 229 * and the display has been turned on. 230 */ 231 public void onWakeUpFinished() { 232 if (DEBUG) { 233 Slog.d(TAG, "onWakeUpFinished"); 234 } 235 } 236 237 /** 238 * Called when the device is going to sleep. 239 */ 240 public void onGoToSleepStarted(int reason) { 241 if (DEBUG) { 242 Slog.d(TAG, "onGoToSleepStarted"); 243 } 244 245 synchronized (mLock) { 246 mLastGoToSleepReason = reason; 247 } 248 } 249 250 /** 251 * Called when the device has finished going to sleep and the 252 * display has been turned off. 253 * 254 * This is a good time to make transitions that we don't want the user to see, 255 * such as bringing the key guard to focus. There's no guarantee for this, 256 * however because the user could turn the device on again at any time. 257 * Some things may need to be protected by other mechanisms that defer screen on. 258 */ 259 public void onGoToSleepFinished() { 260 if (DEBUG) { 261 Slog.d(TAG, "onGoToSleepFinished"); 262 } 263 264 synchronized (mLock) { 265 if (mActualPowerState != POWER_STATE_ASLEEP) { 266 mActualPowerState = POWER_STATE_ASLEEP; 267 if (mUserActivityPending) { 268 mUserActivityPending = false; 269 mHandler.removeMessages(MSG_USER_ACTIVITY); 270 } 271 updatePendingBroadcastLocked(); 272 } 273 } 274 } 275 276 /** 277 * Called when there has been user activity. 278 */ 279 public void onUserActivity(int event, int uid) { 280 if (DEBUG) { 281 Slog.d(TAG, "onUserActivity: event=" + event + ", uid=" + uid); 282 } 283 284 try { 285 mBatteryStats.noteUserActivity(uid, event); 286 } catch (RemoteException ex) { 287 // Ignore 288 } 289 290 synchronized (mLock) { 291 if (!mUserActivityPending) { 292 mUserActivityPending = true; 293 Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY); 294 msg.setAsynchronous(true); 295 mHandler.sendMessage(msg); 296 } 297 } 298 } 299 300 private void updatePendingBroadcastLocked() { 301 if (!mBroadcastInProgress 302 && mActualPowerState != POWER_STATE_UNKNOWN 303 && mActualPowerState != mBroadcastedPowerState) { 304 mBroadcastInProgress = true; 305 mSuspendBlocker.acquire(); 306 Message msg = mHandler.obtainMessage(MSG_BROADCAST); 307 msg.setAsynchronous(true); 308 mHandler.sendMessage(msg); 309 } 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 (mActualPowerState == POWER_STATE_UNKNOWN 328 || mActualPowerState == mBroadcastedPowerState) { 329 mBroadcastInProgress = false; 330 mSuspendBlocker.release(); 331 return; 332 } 333 334 powerState = mActualPowerState; 335 goToSleepReason = mLastGoToSleepReason; 336 337 mBroadcastedPowerState = powerState; 338 mBroadcastStartTime = SystemClock.uptimeMillis(); 339 } 340 341 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_SEND, 1); 342 343 if (powerState == POWER_STATE_AWAKE) { 344 sendWakeUpBroadcast(); 345 } else { 346 sendGoToSleepBroadcast(goToSleepReason); 347 } 348 } 349 350 private void sendWakeUpBroadcast() { 351 if (DEBUG) { 352 Slog.d(TAG, "Sending wake up broadcast."); 353 } 354 355 EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, 0, 0, 0); 356 357 mPolicy.screenTurningOn(mScreenOnListener); 358 try { 359 ActivityManagerNative.getDefault().wakingUp(); 360 } catch (RemoteException e) { 361 // ignore it 362 } 363 364 if (ActivityManagerNative.isSystemReady()) { 365 mContext.sendOrderedBroadcastAsUser(mScreenOnIntent, UserHandle.ALL, null, 366 mWakeUpBroadcastDone, mHandler, 0, null, null); 367 } else { 368 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 2, 1); 369 sendNextBroadcast(); 370 } 371 } 372 373 private final BroadcastReceiver mWakeUpBroadcastDone = new BroadcastReceiver() { 374 @Override 375 public void onReceive(Context context, Intent intent) { 376 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 1, 377 SystemClock.uptimeMillis() - mBroadcastStartTime, 1); 378 sendNextBroadcast(); 379 } 380 }; 381 382 private void sendGoToSleepBroadcast(int reason) { 383 if (DEBUG) { 384 Slog.d(TAG, "Sending go to sleep broadcast."); 385 } 386 387 int why = WindowManagerPolicy.OFF_BECAUSE_OF_USER; 388 switch (reason) { 389 case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN: 390 why = WindowManagerPolicy.OFF_BECAUSE_OF_ADMIN; 391 break; 392 case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT: 393 why = WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT; 394 break; 395 } 396 397 EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0, why, 0, 0); 398 399 mPolicy.screenTurnedOff(why); 400 try { 401 ActivityManagerNative.getDefault().goingToSleep(); 402 } catch (RemoteException e) { 403 // ignore it. 404 } 405 406 if (ActivityManagerNative.isSystemReady()) { 407 mContext.sendOrderedBroadcastAsUser(mScreenOffIntent, UserHandle.ALL, null, 408 mGoToSleepBroadcastDone, mHandler, 0, null, null); 409 } else { 410 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 3, 1); 411 sendNextBroadcast(); 412 } 413 } 414 415 private final BroadcastReceiver mGoToSleepBroadcastDone = new BroadcastReceiver() { 416 @Override 417 public void onReceive(Context context, Intent intent) { 418 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 0, 419 SystemClock.uptimeMillis() - mBroadcastStartTime, 1); 420 sendNextBroadcast(); 421 } 422 }; 423 424 private final class NotifierHandler extends Handler { 425 public NotifierHandler(Looper looper) { 426 super(looper, null, true /*async*/); 427 } 428 429 @Override 430 public void handleMessage(Message msg) { 431 switch (msg.what) { 432 case MSG_USER_ACTIVITY: 433 sendUserActivity(); 434 break; 435 436 case MSG_BROADCAST: 437 sendNextBroadcast(); 438 break; 439 } 440 } 441 } 442} 443