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