blob: 1349926e86976a5df0e5b3d42e38ac20119717d1 [file] [log] [blame]
Jeff Brown96307042012-07-27 15:51:34 -07001/*
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
Jeff Brown13014b52014-04-07 19:45:27 -070019import android.app.ActivityManagerInternal;
Dianne Hackborn713df152013-05-17 11:27:57 -070020import android.app.AppOpsManager;
Jeff Brown13014b52014-04-07 19:45:27 -070021
Dianne Hackborn713df152013-05-17 11:27:57 -070022import com.android.internal.app.IAppOpsService;
Jeff Brown96307042012-07-27 15:51:34 -070023import com.android.internal.app.IBatteryStats;
24import com.android.server.EventLogTags;
Jeff Brown13014b52014-04-07 19:45:27 -070025import com.android.server.LocalServices;
Jeff Brown96307042012-07-27 15:51:34 -070026
27import android.app.ActivityManagerNative;
28import android.content.BroadcastReceiver;
29import android.content.Context;
30import android.content.Intent;
Jeff Brown037c33e2014-04-09 00:31:55 -070031import android.hardware.input.InputManagerInternal;
Jeff Brown84e27562012-12-07 13:56:34 -080032import android.media.AudioManager;
33import android.media.Ringtone;
34import android.media.RingtoneManager;
35import android.net.Uri;
Jeff Brown96307042012-07-27 15:51:34 -070036import android.os.BatteryStats;
37import android.os.Handler;
38import android.os.Looper;
39import android.os.Message;
40import android.os.PowerManager;
Jeff Brownfbe96702014-11-19 18:30:58 -080041import android.os.PowerManagerInternal;
Dianne Hackborn3d658bf2014-02-05 13:38:56 -080042import android.os.Process;
Jeff Brown96307042012-07-27 15:51:34 -070043import android.os.RemoteException;
44import android.os.SystemClock;
Dianne Hackborn5ac72a22012-08-29 18:32:08 -070045import android.os.UserHandle;
Jeff Brown96307042012-07-27 15:51:34 -070046import android.os.WorkSource;
Jeff Brown84e27562012-12-07 13:56:34 -080047import android.provider.Settings;
Jeff Brown96307042012-07-27 15:51:34 -070048import android.util.EventLog;
49import android.util.Slog;
50import android.view.WindowManagerPolicy;
Jeff Brown96307042012-07-27 15:51:34 -070051
52/**
53 * Sends broadcasts about important power state changes.
Jeff Brown54308352012-10-04 17:59:58 -070054 * <p>
Jeff Brown96307042012-07-27 15:51:34 -070055 * This methods of this class may be called by the power manager service while
56 * its lock is being held. Internally it takes care of sending broadcasts to
57 * notify other components of the system or applications asynchronously.
Jeff Brown54308352012-10-04 17:59:58 -070058 * </p><p>
Jeff Brown96307042012-07-27 15:51:34 -070059 * The notifier is designed to collapse unnecessary broadcasts when it is not
60 * possible for the system to have observed an intermediate state.
Jeff Brown54308352012-10-04 17:59:58 -070061 * </p><p>
62 * For example, if the device wakes up, goes to sleep, wakes up again and goes to
63 * sleep again before the wake up notification is sent, then the system will
64 * be told about only one wake up and sleep. However, we always notify the
65 * fact that at least one transition occurred. It is especially important to
66 * tell the system when we go to sleep so that it can lock the keyguard if needed.
67 * </p>
Jeff Brown96307042012-07-27 15:51:34 -070068 */
69final class Notifier {
70 private static final String TAG = "PowerManagerNotifier";
71
72 private static final boolean DEBUG = false;
73
Jeff Brownfbe96702014-11-19 18:30:58 -080074 private static final int INTERACTIVE_STATE_UNKNOWN = 0;
75 private static final int INTERACTIVE_STATE_AWAKE = 1;
76 private static final int INTERACTIVE_STATE_ASLEEP = 2;
Jeff Brown96307042012-07-27 15:51:34 -070077
78 private static final int MSG_USER_ACTIVITY = 1;
79 private static final int MSG_BROADCAST = 2;
Jeff Brown84e27562012-12-07 13:56:34 -080080 private static final int MSG_WIRELESS_CHARGING_STARTED = 3;
Jeff Brown96307042012-07-27 15:51:34 -070081
82 private final Object mLock = new Object();
83
84 private final Context mContext;
85 private final IBatteryStats mBatteryStats;
Dianne Hackborn713df152013-05-17 11:27:57 -070086 private final IAppOpsService mAppOps;
Jeff Brown96307042012-07-27 15:51:34 -070087 private final SuspendBlocker mSuspendBlocker;
88 private final WindowManagerPolicy mPolicy;
Jeff Brown13014b52014-04-07 19:45:27 -070089 private final ActivityManagerInternal mActivityManagerInternal;
Jeff Brown037c33e2014-04-09 00:31:55 -070090 private final InputManagerInternal mInputManagerInternal;
Jeff Brown96307042012-07-27 15:51:34 -070091
92 private final NotifierHandler mHandler;
93 private final Intent mScreenOnIntent;
94 private final Intent mScreenOffIntent;
95
Jeff Brownfbe96702014-11-19 18:30:58 -080096 // The current interactive state.
97 private int mActualInteractiveState;
98 private int mLastReason;
Jeff Brown96307042012-07-27 15:51:34 -070099
Jeff Brown54308352012-10-04 17:59:58 -0700100 // True if there is a pending transition that needs to be reported.
101 private boolean mPendingWakeUpBroadcast;
102 private boolean mPendingGoToSleepBroadcast;
103
Jeff Brownfbe96702014-11-19 18:30:58 -0800104 // The currently broadcasted interactive state. This reflects what other parts of the
Jeff Brown96307042012-07-27 15:51:34 -0700105 // system have observed.
Jeff Brownfbe96702014-11-19 18:30:58 -0800106 private int mBroadcastedInteractiveState;
Jeff Brown96307042012-07-27 15:51:34 -0700107 private boolean mBroadcastInProgress;
108 private long mBroadcastStartTime;
109
110 // True if a user activity message should be sent.
111 private boolean mUserActivityPending;
112
113 public Notifier(Looper looper, Context context, IBatteryStats batteryStats,
Jeff Brown3ee549c2014-09-22 20:14:39 -0700114 IAppOpsService appOps, SuspendBlocker suspendBlocker,
Jeff Brownc38c9be2012-10-04 13:16:19 -0700115 WindowManagerPolicy policy) {
Jeff Brown96307042012-07-27 15:51:34 -0700116 mContext = context;
117 mBatteryStats = batteryStats;
Dianne Hackborn713df152013-05-17 11:27:57 -0700118 mAppOps = appOps;
Jeff Brown96307042012-07-27 15:51:34 -0700119 mSuspendBlocker = suspendBlocker;
120 mPolicy = policy;
Jeff Brown13014b52014-04-07 19:45:27 -0700121 mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
Jeff Brown037c33e2014-04-09 00:31:55 -0700122 mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
Jeff Brown96307042012-07-27 15:51:34 -0700123
124 mHandler = new NotifierHandler(looper);
125 mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);
126 mScreenOnIntent.addFlags(
127 Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
128 mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF);
129 mScreenOffIntent.addFlags(
130 Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
Jeff Browne95c3cd2014-05-02 16:59:26 -0700131
132 // Initialize interactive state for battery stats.
133 try {
134 mBatteryStats.noteInteractive(true);
135 } catch (RemoteException ex) { }
Jeff Brown96307042012-07-27 15:51:34 -0700136 }
137
138 /**
139 * Called when a wake lock is acquired.
140 */
Dianne Hackborn713df152013-05-17 11:27:57 -0700141 public void onWakeLockAcquired(int flags, String tag, String packageName,
Dianne Hackborna1f1a3c2014-02-24 18:12:28 -0800142 int ownerUid, int ownerPid, WorkSource workSource, String historyTag) {
Jeff Brown96307042012-07-27 15:51:34 -0700143 if (DEBUG) {
144 Slog.d(TAG, "onWakeLockAcquired: flags=" + flags + ", tag=\"" + tag
Dianne Hackborn713df152013-05-17 11:27:57 -0700145 + "\", packageName=" + packageName
146 + ", ownerUid=" + ownerUid + ", ownerPid=" + ownerPid
Jeff Brown96307042012-07-27 15:51:34 -0700147 + ", workSource=" + workSource);
148 }
149
Craig Mautner259328c2012-08-21 19:30:58 -0700150 try {
151 final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800152 boolean unimportantForLogging = (flags&PowerManager.UNIMPORTANT_FOR_LOGGING) != 0
153 && ownerUid == Process.SYSTEM_UID;
Craig Mautner259328c2012-08-21 19:30:58 -0700154 if (workSource != null) {
Dianne Hackborna1f1a3c2014-02-24 18:12:28 -0800155 mBatteryStats.noteStartWakelockFromSource(workSource, ownerPid, tag, historyTag,
156 monitorType, unimportantForLogging);
Craig Mautner259328c2012-08-21 19:30:58 -0700157 } else {
Dianne Hackborna1f1a3c2014-02-24 18:12:28 -0800158 mBatteryStats.noteStartWakelock(ownerUid, ownerPid, tag, historyTag,
159 monitorType, unimportantForLogging);
Dianne Hackborn713df152013-05-17 11:27:57 -0700160 // XXX need to deal with disabled operations.
Dianne Hackborne98f5db2013-07-17 17:23:25 -0700161 mAppOps.startOperation(AppOpsManager.getToken(mAppOps),
162 AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName);
Jeff Brown96307042012-07-27 15:51:34 -0700163 }
Craig Mautner259328c2012-08-21 19:30:58 -0700164 } catch (RemoteException ex) {
165 // Ignore
Jeff Brown96307042012-07-27 15:51:34 -0700166 }
167 }
168
169 /**
Dianne Hackborne5167ca2014-03-08 14:39:10 -0800170 * Called when a wake lock is changing.
171 */
172 public void onWakeLockChanging(int flags, String tag, String packageName,
173 int ownerUid, int ownerPid, WorkSource workSource, String historyTag,
174 int newFlags, String newTag, String newPackageName, int newOwnerUid,
175 int newOwnerPid, WorkSource newWorkSource, String newHistoryTag) {
176
Dianne Hackborne5167ca2014-03-08 14:39:10 -0800177 if (workSource != null && newWorkSource != null) {
Dianne Hackbornbbb74722014-03-13 09:50:24 -0700178 final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
179 final int newMonitorType = getBatteryStatsWakeLockMonitorType(newFlags);
180 boolean unimportantForLogging = (newFlags&PowerManager.UNIMPORTANT_FOR_LOGGING) != 0
181 && newOwnerUid == Process.SYSTEM_UID;
Dianne Hackborne5167ca2014-03-08 14:39:10 -0800182 if (DEBUG) {
183 Slog.d(TAG, "onWakeLockChanging: flags=" + newFlags + ", tag=\"" + newTag
184 + "\", packageName=" + newPackageName
185 + ", ownerUid=" + newOwnerUid + ", ownerPid=" + newOwnerPid
186 + ", workSource=" + newWorkSource);
187 }
188 try {
Dianne Hackborncbefd8d2014-05-14 11:42:00 -0700189 mBatteryStats.noteChangeWakelockFromSource(workSource, ownerPid, tag, historyTag,
190 monitorType, newWorkSource, newOwnerPid, newTag, newHistoryTag,
Dianne Hackborne5167ca2014-03-08 14:39:10 -0800191 newMonitorType, unimportantForLogging);
192 } catch (RemoteException ex) {
193 // Ignore
194 }
195 } else {
Dianne Hackborncbefd8d2014-05-14 11:42:00 -0700196 onWakeLockReleased(flags, tag, packageName, ownerUid, ownerPid, workSource, historyTag);
Dianne Hackborne5167ca2014-03-08 14:39:10 -0800197 onWakeLockAcquired(newFlags, newTag, newPackageName, newOwnerUid, newOwnerPid,
198 newWorkSource, newHistoryTag);
199 }
200 }
201
202 /**
Jeff Brown96307042012-07-27 15:51:34 -0700203 * Called when a wake lock is released.
204 */
Dianne Hackborn713df152013-05-17 11:27:57 -0700205 public void onWakeLockReleased(int flags, String tag, String packageName,
Dianne Hackborncbefd8d2014-05-14 11:42:00 -0700206 int ownerUid, int ownerPid, WorkSource workSource, String historyTag) {
Jeff Brown96307042012-07-27 15:51:34 -0700207 if (DEBUG) {
208 Slog.d(TAG, "onWakeLockReleased: flags=" + flags + ", tag=\"" + tag
Dianne Hackborn713df152013-05-17 11:27:57 -0700209 + "\", packageName=" + packageName
210 + ", ownerUid=" + ownerUid + ", ownerPid=" + ownerPid
Jeff Brown96307042012-07-27 15:51:34 -0700211 + ", workSource=" + workSource);
212 }
213
Craig Mautner259328c2012-08-21 19:30:58 -0700214 try {
215 final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
216 if (workSource != null) {
Dianne Hackborncbefd8d2014-05-14 11:42:00 -0700217 mBatteryStats.noteStopWakelockFromSource(workSource, ownerPid, tag, historyTag,
218 monitorType);
Craig Mautner259328c2012-08-21 19:30:58 -0700219 } else {
Dianne Hackborncbefd8d2014-05-14 11:42:00 -0700220 mBatteryStats.noteStopWakelock(ownerUid, ownerPid, tag, historyTag, monitorType);
Dianne Hackborne98f5db2013-07-17 17:23:25 -0700221 mAppOps.finishOperation(AppOpsManager.getToken(mAppOps),
222 AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName);
Jeff Brown96307042012-07-27 15:51:34 -0700223 }
Craig Mautner259328c2012-08-21 19:30:58 -0700224 } catch (RemoteException ex) {
225 // Ignore
Jeff Brown96307042012-07-27 15:51:34 -0700226 }
227 }
228
Jeff Brown96307042012-07-27 15:51:34 -0700229 private static int getBatteryStatsWakeLockMonitorType(int flags) {
230 switch (flags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
231 case PowerManager.PARTIAL_WAKE_LOCK:
232 case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
233 return BatteryStats.WAKE_TYPE_PARTIAL;
234 default:
235 return BatteryStats.WAKE_TYPE_FULL;
236 }
237 }
238
239 /**
Jeff Brownfbe96702014-11-19 18:30:58 -0800240 * Notifies that the device is changing wakefulness.
Jeff Brown96307042012-07-27 15:51:34 -0700241 */
Jeff Brownfbe96702014-11-19 18:30:58 -0800242 public void onWakefulnessChangeStarted(int wakefulness, int reason) {
Jeff Brown96307042012-07-27 15:51:34 -0700243 if (DEBUG) {
Jeff Brownfbe96702014-11-19 18:30:58 -0800244 Slog.d(TAG, "onWakefulnessChangeStarted: wakefulness=" + wakefulness
Jeff Brown037c33e2014-04-09 00:31:55 -0700245 + ", reason=" + reason);
Jeff Brown96307042012-07-27 15:51:34 -0700246 }
247
Jeff Brownfbe96702014-11-19 18:30:58 -0800248 // We handle interactive state changes once they start so that the system can
249 // set everything up or the user to begin interacting with applications.
250 final boolean interactive = PowerManagerInternal.isInteractive(wakefulness);
251 if (interactive) {
252 handleWakefulnessChange(wakefulness, interactive, reason);
253 } else {
254 mLastReason = reason;
255 }
256
257 // Start input as soon as we start waking up or going to sleep.
258 mInputManagerInternal.setInteractive(interactive);
259 }
260
261 /**
262 * Notifies that the device has finished changing wakefulness.
263 */
264 public void onWakefulnessChangeFinished(int wakefulness) {
265 if (DEBUG) {
266 Slog.d(TAG, "onWakefulnessChangeFinished: wakefulness=" + wakefulness);
267 }
268
269 // Handle interactive state changes once they are finished so that the system can
270 // finish pending transitions (such as turning the screen off) before causing
271 // applications to change state visibly.
272 final boolean interactive = PowerManagerInternal.isInteractive(wakefulness);
273 if (!interactive) {
274 handleWakefulnessChange(wakefulness, interactive, mLastReason);
275 }
276 }
277
278 private void handleWakefulnessChange(final int wakefulness, boolean interactive,
279 final int reason) {
280 // Tell the activity manager about changes in wakefulness, not just interactivity.
281 // It needs more granularity than other components.
282 mHandler.post(new Runnable() {
283 @Override
284 public void run() {
285 mActivityManagerInternal.onWakefulnessChanged(wakefulness);
286 }
287 });
288
289 // Handle changes in the overall interactive state.
290 boolean interactiveChanged = false;
Jeff Brown96307042012-07-27 15:51:34 -0700291 synchronized (mLock) {
Jeff Brownfbe96702014-11-19 18:30:58 -0800292 // Broadcast interactive state changes.
Jeff Brown037c33e2014-04-09 00:31:55 -0700293 if (interactive) {
294 // Waking up...
Jeff Brownfbe96702014-11-19 18:30:58 -0800295 interactiveChanged = (mActualInteractiveState != INTERACTIVE_STATE_AWAKE);
296 if (interactiveChanged) {
297 mActualInteractiveState = INTERACTIVE_STATE_AWAKE;
Jeff Brown037c33e2014-04-09 00:31:55 -0700298 mPendingWakeUpBroadcast = true;
Jim Millerc522d162014-07-01 17:10:21 -0700299 mHandler.post(new Runnable() {
300 @Override
301 public void run() {
302 EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, 0, 0, 0);
Jeff Brown36c4db82014-09-19 12:05:31 -0700303 mPolicy.wakingUp();
Jim Millerc522d162014-07-01 17:10:21 -0700304 }
305 });
Jeff Brown037c33e2014-04-09 00:31:55 -0700306 updatePendingBroadcastLocked();
Jeff Brownc38c9be2012-10-04 13:16:19 -0700307 }
Jeff Brown037c33e2014-04-09 00:31:55 -0700308 } else {
309 // Going to sleep...
Jeff Brown037c33e2014-04-09 00:31:55 -0700310 // This is a good time to make transitions that we don't want the user to see,
311 // such as bringing the key guard to focus. There's no guarantee for this,
312 // however because the user could turn the device on again at any time.
313 // Some things may need to be protected by other mechanisms that defer screen on.
Jeff Brownfbe96702014-11-19 18:30:58 -0800314 interactiveChanged = (mActualInteractiveState != INTERACTIVE_STATE_ASLEEP);
315 if (interactiveChanged) {
316 mActualInteractiveState = INTERACTIVE_STATE_ASLEEP;
Jeff Brown037c33e2014-04-09 00:31:55 -0700317 mPendingGoToSleepBroadcast = true;
318 if (mUserActivityPending) {
319 mUserActivityPending = false;
320 mHandler.removeMessages(MSG_USER_ACTIVITY);
321 }
Jim Millerc522d162014-07-01 17:10:21 -0700322 mHandler.post(new Runnable() {
323 @Override
324 public void run() {
325 int why = WindowManagerPolicy.OFF_BECAUSE_OF_USER;
Jeff Brownfbe96702014-11-19 18:30:58 -0800326 switch (reason) {
Jim Millerc522d162014-07-01 17:10:21 -0700327 case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN:
328 why = WindowManagerPolicy.OFF_BECAUSE_OF_ADMIN;
329 break;
330 case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT:
331 why = WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT;
332 break;
333 }
334 EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0, why, 0, 0);
335 mPolicy.goingToSleep(why);
Jim Millerc522d162014-07-01 17:10:21 -0700336 }
337 });
Jeff Brown037c33e2014-04-09 00:31:55 -0700338 updatePendingBroadcastLocked();
Jeff Brown96307042012-07-27 15:51:34 -0700339 }
Jeff Brown96307042012-07-27 15:51:34 -0700340 }
341 }
Jeff Browne95c3cd2014-05-02 16:59:26 -0700342
Jeff Brownfbe96702014-11-19 18:30:58 -0800343 // Notify battery stats.
344 if (interactiveChanged) {
Jeff Browne95c3cd2014-05-02 16:59:26 -0700345 try {
Jeff Brownfbe96702014-11-19 18:30:58 -0800346 mBatteryStats.noteInteractive(interactive);
Jeff Browne95c3cd2014-05-02 16:59:26 -0700347 } catch (RemoteException ex) { }
348 }
Jeff Brown96307042012-07-27 15:51:34 -0700349 }
350
351 /**
352 * Called when there has been user activity.
353 */
354 public void onUserActivity(int event, int uid) {
355 if (DEBUG) {
356 Slog.d(TAG, "onUserActivity: event=" + event + ", uid=" + uid);
357 }
358
359 try {
360 mBatteryStats.noteUserActivity(uid, event);
361 } catch (RemoteException ex) {
362 // Ignore
363 }
364
365 synchronized (mLock) {
366 if (!mUserActivityPending) {
367 mUserActivityPending = true;
368 Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY);
369 msg.setAsynchronous(true);
370 mHandler.sendMessage(msg);
371 }
372 }
373 }
374
Jeff Brown84e27562012-12-07 13:56:34 -0800375 /**
376 * Called when wireless charging has started so as to provide user feedback.
377 */
378 public void onWirelessChargingStarted() {
379 if (DEBUG) {
380 Slog.d(TAG, "onWirelessChargingStarted");
381 }
382
383 mSuspendBlocker.acquire();
384 Message msg = mHandler.obtainMessage(MSG_WIRELESS_CHARGING_STARTED);
385 msg.setAsynchronous(true);
386 mHandler.sendMessage(msg);
387 }
388
Jeff Brown96307042012-07-27 15:51:34 -0700389 private void updatePendingBroadcastLocked() {
390 if (!mBroadcastInProgress
Jeff Brownfbe96702014-11-19 18:30:58 -0800391 && mActualInteractiveState != INTERACTIVE_STATE_UNKNOWN
Jeff Brown54308352012-10-04 17:59:58 -0700392 && (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
Jeff Brownfbe96702014-11-19 18:30:58 -0800393 || mActualInteractiveState != mBroadcastedInteractiveState)) {
Jeff Brown96307042012-07-27 15:51:34 -0700394 mBroadcastInProgress = true;
395 mSuspendBlocker.acquire();
396 Message msg = mHandler.obtainMessage(MSG_BROADCAST);
397 msg.setAsynchronous(true);
398 mHandler.sendMessage(msg);
399 }
400 }
401
Jeff Brown54308352012-10-04 17:59:58 -0700402 private void finishPendingBroadcastLocked() {
403 mBroadcastInProgress = false;
404 mSuspendBlocker.release();
405 }
406
Jeff Brown96307042012-07-27 15:51:34 -0700407 private void sendUserActivity() {
408 synchronized (mLock) {
409 if (!mUserActivityPending) {
410 return;
411 }
412 mUserActivityPending = false;
413 }
414
415 mPolicy.userActivity();
416 }
417
418 private void sendNextBroadcast() {
419 final int powerState;
Jeff Brown96307042012-07-27 15:51:34 -0700420 synchronized (mLock) {
Jeff Brownfbe96702014-11-19 18:30:58 -0800421 if (mBroadcastedInteractiveState == INTERACTIVE_STATE_UNKNOWN) {
Jeff Brown54308352012-10-04 17:59:58 -0700422 // Broadcasted power state is unknown. Send wake up.
423 mPendingWakeUpBroadcast = false;
Jeff Brownfbe96702014-11-19 18:30:58 -0800424 mBroadcastedInteractiveState = INTERACTIVE_STATE_AWAKE;
425 } else if (mBroadcastedInteractiveState == INTERACTIVE_STATE_AWAKE) {
Jeff Brown54308352012-10-04 17:59:58 -0700426 // Broadcasted power state is awake. Send asleep if needed.
427 if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
Jeff Brownfbe96702014-11-19 18:30:58 -0800428 || mActualInteractiveState == INTERACTIVE_STATE_ASLEEP) {
Jeff Brown54308352012-10-04 17:59:58 -0700429 mPendingGoToSleepBroadcast = false;
Jeff Brownfbe96702014-11-19 18:30:58 -0800430 mBroadcastedInteractiveState = INTERACTIVE_STATE_ASLEEP;
Jeff Brown54308352012-10-04 17:59:58 -0700431 } else {
432 finishPendingBroadcastLocked();
433 return;
434 }
435 } else {
436 // Broadcasted power state is asleep. Send awake if needed.
437 if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
Jeff Brownfbe96702014-11-19 18:30:58 -0800438 || mActualInteractiveState == INTERACTIVE_STATE_AWAKE) {
Jeff Brown54308352012-10-04 17:59:58 -0700439 mPendingWakeUpBroadcast = false;
Jeff Brownfbe96702014-11-19 18:30:58 -0800440 mBroadcastedInteractiveState = INTERACTIVE_STATE_AWAKE;
Jeff Brown54308352012-10-04 17:59:58 -0700441 } else {
442 finishPendingBroadcastLocked();
443 return;
444 }
Jeff Brown96307042012-07-27 15:51:34 -0700445 }
446
Jeff Brown96307042012-07-27 15:51:34 -0700447 mBroadcastStartTime = SystemClock.uptimeMillis();
Jeff Brownfbe96702014-11-19 18:30:58 -0800448 powerState = mBroadcastedInteractiveState;
Jeff Brown96307042012-07-27 15:51:34 -0700449 }
450
451 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_SEND, 1);
452
Jeff Brownfbe96702014-11-19 18:30:58 -0800453 if (powerState == INTERACTIVE_STATE_AWAKE) {
Jeff Brown96307042012-07-27 15:51:34 -0700454 sendWakeUpBroadcast();
455 } else {
Jim Millerc522d162014-07-01 17:10:21 -0700456 sendGoToSleepBroadcast();
Jeff Brown96307042012-07-27 15:51:34 -0700457 }
458 }
459
460 private void sendWakeUpBroadcast() {
461 if (DEBUG) {
462 Slog.d(TAG, "Sending wake up broadcast.");
463 }
464
Jeff Brown96307042012-07-27 15:51:34 -0700465 if (ActivityManagerNative.isSystemReady()) {
Dianne Hackborn5ac72a22012-08-29 18:32:08 -0700466 mContext.sendOrderedBroadcastAsUser(mScreenOnIntent, UserHandle.ALL, null,
Jeff Brown96307042012-07-27 15:51:34 -0700467 mWakeUpBroadcastDone, mHandler, 0, null, null);
468 } else {
469 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 2, 1);
470 sendNextBroadcast();
471 }
472 }
473
474 private final BroadcastReceiver mWakeUpBroadcastDone = new BroadcastReceiver() {
475 @Override
476 public void onReceive(Context context, Intent intent) {
477 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 1,
478 SystemClock.uptimeMillis() - mBroadcastStartTime, 1);
479 sendNextBroadcast();
480 }
481 };
482
Jim Millerc522d162014-07-01 17:10:21 -0700483 private void sendGoToSleepBroadcast() {
Jeff Brown96307042012-07-27 15:51:34 -0700484 if (DEBUG) {
485 Slog.d(TAG, "Sending go to sleep broadcast.");
486 }
487
Jeff Brown96307042012-07-27 15:51:34 -0700488 if (ActivityManagerNative.isSystemReady()) {
Dianne Hackborn5ac72a22012-08-29 18:32:08 -0700489 mContext.sendOrderedBroadcastAsUser(mScreenOffIntent, UserHandle.ALL, null,
Jeff Brown96307042012-07-27 15:51:34 -0700490 mGoToSleepBroadcastDone, mHandler, 0, null, null);
491 } else {
492 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 3, 1);
493 sendNextBroadcast();
494 }
495 }
496
497 private final BroadcastReceiver mGoToSleepBroadcastDone = new BroadcastReceiver() {
498 @Override
499 public void onReceive(Context context, Intent intent) {
500 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 0,
501 SystemClock.uptimeMillis() - mBroadcastStartTime, 1);
502 sendNextBroadcast();
503 }
504 };
505
Jeff Brown84e27562012-12-07 13:56:34 -0800506 private void playWirelessChargingStartedSound() {
507 final String soundPath = Settings.Global.getString(mContext.getContentResolver(),
508 Settings.Global.WIRELESS_CHARGING_STARTED_SOUND);
509 if (soundPath != null) {
510 final Uri soundUri = Uri.parse("file://" + soundPath);
511 if (soundUri != null) {
512 final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
513 if (sfx != null) {
514 sfx.setStreamType(AudioManager.STREAM_SYSTEM);
515 sfx.play();
516 }
517 }
518 }
519
520 mSuspendBlocker.release();
521 }
522
Jeff Brown96307042012-07-27 15:51:34 -0700523 private final class NotifierHandler extends Handler {
524 public NotifierHandler(Looper looper) {
Jeff Browna2910d02012-08-25 12:29:46 -0700525 super(looper, null, true /*async*/);
Jeff Brown96307042012-07-27 15:51:34 -0700526 }
527
528 @Override
529 public void handleMessage(Message msg) {
530 switch (msg.what) {
531 case MSG_USER_ACTIVITY:
532 sendUserActivity();
533 break;
534
535 case MSG_BROADCAST:
536 sendNextBroadcast();
537 break;
Jeff Brown84e27562012-12-07 13:56:34 -0800538
539 case MSG_WIRELESS_CHARGING_STARTED:
540 playWirelessChargingStartedSound();
541 break;
Jeff Brown96307042012-07-27 15:51:34 -0700542 }
543 }
544 }
545}