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 
17 package com.android.server.power;
18 
19 import android.annotation.Nullable;
20 import android.annotation.UserIdInt;
21 import android.app.ActivityManagerInternal;
22 import android.app.AppOpsManager;
23 import android.app.BroadcastOptions;
24 import android.app.trust.TrustManager;
25 import android.content.Context;
26 import android.content.IIntentReceiver;
27 import android.content.Intent;
28 import android.hardware.display.DisplayManagerInternal;
29 import android.media.AudioManager;
30 import android.media.Ringtone;
31 import android.media.RingtoneManager;
32 import android.metrics.LogMaker;
33 import android.net.Uri;
34 import android.os.BatteryStats;
35 import android.os.Bundle;
36 import android.os.Handler;
37 import android.os.IWakeLockCallback;
38 import android.os.Looper;
39 import android.os.Message;
40 import android.os.PowerManager;
41 import android.os.PowerManagerInternal;
42 import android.os.Process;
43 import android.os.RemoteException;
44 import android.os.SystemClock;
45 import android.os.UserHandle;
46 import android.os.VibrationAttributes;
47 import android.os.VibrationEffect;
48 import android.os.Vibrator;
49 import android.os.WorkSource;
50 import android.provider.Settings;
51 import android.telephony.TelephonyManager;
52 import android.util.EventLog;
53 import android.util.Slog;
54 import android.util.SparseArray;
55 import android.view.WindowManagerPolicyConstants;
56 
57 import com.android.internal.annotations.VisibleForTesting;
58 import com.android.internal.app.IBatteryStats;
59 import com.android.internal.logging.MetricsLogger;
60 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
61 import com.android.internal.util.FrameworkStatsLog;
62 import com.android.server.EventLogTags;
63 import com.android.server.LocalServices;
64 import com.android.server.input.InputManagerInternal;
65 import com.android.server.inputmethod.InputMethodManagerInternal;
66 import com.android.server.policy.WindowManagerPolicy;
67 import com.android.server.power.feature.PowerManagerFlags;
68 import com.android.server.statusbar.StatusBarManagerInternal;
69 
70 import java.io.PrintWriter;
71 import java.util.UUID;
72 import java.util.concurrent.Executor;
73 import java.util.concurrent.atomic.AtomicBoolean;
74 
75 /**
76  * Sends broadcasts about important power state changes.
77  * <p>
78  * This methods of this class may be called by the power manager service while
79  * its lock is being held.  Internally it takes care of sending broadcasts to
80  * notify other components of the system or applications asynchronously.
81  * </p><p>
82  * The notifier is designed to collapse unnecessary broadcasts when it is not
83  * possible for the system to have observed an intermediate state.
84  * </p><p>
85  * For example, if the device wakes up, goes to sleep, wakes up again and goes to
86  * sleep again before the wake up notification is sent, then the system will
87  * be told about only one wake up and sleep.  However, we always notify the
88  * fact that at least one transition occurred.  It is especially important to
89  * tell the system when we go to sleep so that it can lock the keyguard if needed.
90  * </p>
91  */
92 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED)
93 public class Notifier {
94     private static final String TAG = "PowerManagerNotifier";
95 
96     private static final boolean DEBUG = false;
97 
98     private static final int INTERACTIVE_STATE_UNKNOWN = 0;
99     private static final int INTERACTIVE_STATE_AWAKE = 1;
100     private static final int INTERACTIVE_STATE_ASLEEP = 2;
101 
102     private static final int MSG_USER_ACTIVITY = 1;
103     private static final int MSG_BROADCAST = 2;
104     private static final int MSG_WIRELESS_CHARGING_STARTED = 3;
105     private static final int MSG_BROADCAST_ENHANCED_PREDICTION = 4;
106     private static final int MSG_PROFILE_TIMED_OUT = 5;
107     private static final int MSG_WIRED_CHARGING_STARTED = 6;
108     private static final int MSG_SCREEN_POLICY = 7;
109 
110     private static final long[] CHARGING_VIBRATION_TIME = {
111             40, 40, 40, 40, 40, 40, 40, 40, 40, // ramp-up sampling rate = 40ms
112             40, 40, 40, 40, 40, 40, 40 // ramp-down sampling rate = 40ms
113     };
114     private static final int[] CHARGING_VIBRATION_AMPLITUDE = {
115             1, 4, 11, 25, 44, 67, 91, 114, 123, // ramp-up amplitude (from 0 to 50%)
116             103, 79, 55, 34, 17, 7, 2 // ramp-up amplitude
117     };
118     private static final VibrationEffect CHARGING_VIBRATION_EFFECT =
119             VibrationEffect.createWaveform(CHARGING_VIBRATION_TIME, CHARGING_VIBRATION_AMPLITUDE,
120                     -1);
121     private static final VibrationAttributes HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES =
122             VibrationAttributes.createForUsage(VibrationAttributes.USAGE_HARDWARE_FEEDBACK);
123 
124     private final Object mLock = new Object();
125 
126     private final Context mContext;
127     private final IBatteryStats mBatteryStats;
128     private final AppOpsManager mAppOps;
129     private final SuspendBlocker mSuspendBlocker;
130     private final WindowManagerPolicy mPolicy;
131     private final FaceDownDetector mFaceDownDetector;
132     private final ScreenUndimDetector mScreenUndimDetector;
133     private final WakefulnessSessionObserver mWakefulnessSessionObserver;
134     private final ActivityManagerInternal mActivityManagerInternal;
135     private final InputManagerInternal mInputManagerInternal;
136     private final InputMethodManagerInternal mInputMethodManagerInternal;
137     @Nullable private final StatusBarManagerInternal mStatusBarManagerInternal;
138     private final TrustManager mTrustManager;
139     private final Vibrator mVibrator;
140     private final WakeLockLog mWakeLockLog;
141     private final DisplayManagerInternal mDisplayManagerInternal;
142 
143     private final NotifierHandler mHandler;
144     private final Executor mBackgroundExecutor;
145     private final Intent mScreenOnIntent;
146     private final Intent mScreenOffIntent;
147     private final Bundle mScreenOnOffOptions;
148 
149     // True if the device should suspend when the screen is off due to proximity.
150     private final boolean mSuspendWhenScreenOffDueToProximityConfig;
151 
152     // True if the device should show the wireless charging animation when the device
153     // begins charging wirelessly
154     private final boolean mShowWirelessChargingAnimationConfig;
155 
156     // Encapsulates interactivity information about a particular display group.
157     private static class Interactivity {
158         public boolean isInteractive = true;
159         public int changeReason;
160         public long changeStartTime; // In SystemClock.uptimeMillis()
161         public boolean isChanging;
162     }
163 
164     private final SparseArray<Interactivity> mInteractivityByGroupId = new SparseArray<>();
165 
166     // The current global interactive state.  This is set as soon as an interactive state
167     // transition begins so as to capture the reason that it happened.  At some point
168     // this state will propagate to the pending state then eventually to the
169     // broadcasted state over the course of reporting the transition asynchronously.
170     private Interactivity mGlobalInteractivity = new Interactivity();
171 
172     // The pending interactive state that we will eventually want to broadcast.
173     // This is designed so that we can collapse redundant sequences of awake/sleep
174     // transition pairs while still guaranteeing that at least one transition is observed
175     // whenever this happens.
176     private int mPendingInteractiveState;
177     private boolean mPendingWakeUpBroadcast;
178     private boolean mPendingGoToSleepBroadcast;
179 
180     // The currently broadcasted interactive state.  This reflects what other parts of the
181     // system have observed.
182     private int mBroadcastedInteractiveState;
183     private boolean mBroadcastInProgress;
184     private long mBroadcastStartTime;
185 
186     // True if a user activity message should be sent.
187     private boolean mUserActivityPending;
188 
189     private final AtomicBoolean mIsPlayingChargingStartedFeedback = new AtomicBoolean(false);
190 
191     private final Injector mInjector;
192 
193     private final PowerManagerFlags mFlags;
194 
Notifier(Looper looper, Context context, IBatteryStats batteryStats, SuspendBlocker suspendBlocker, WindowManagerPolicy policy, FaceDownDetector faceDownDetector, ScreenUndimDetector screenUndimDetector, Executor backgroundExecutor, PowerManagerFlags powerManagerFlags, Injector injector)195     public Notifier(Looper looper, Context context, IBatteryStats batteryStats,
196             SuspendBlocker suspendBlocker, WindowManagerPolicy policy,
197             FaceDownDetector faceDownDetector, ScreenUndimDetector screenUndimDetector,
198             Executor backgroundExecutor, PowerManagerFlags powerManagerFlags, Injector injector) {
199         mContext = context;
200         mFlags = powerManagerFlags;
201         mBatteryStats = batteryStats;
202         mAppOps = mContext.getSystemService(AppOpsManager.class);
203         mSuspendBlocker = suspendBlocker;
204         mPolicy = policy;
205         mFaceDownDetector = faceDownDetector;
206         mScreenUndimDetector = screenUndimDetector;
207         mWakefulnessSessionObserver = new WakefulnessSessionObserver(mContext, null);
208         mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
209         mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
210         mInputMethodManagerInternal = LocalServices.getService(InputMethodManagerInternal.class);
211         mStatusBarManagerInternal = LocalServices.getService(StatusBarManagerInternal.class);
212         mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
213         mTrustManager = mContext.getSystemService(TrustManager.class);
214         mVibrator = mContext.getSystemService(Vibrator.class);
215 
216         mHandler = new NotifierHandler(looper);
217         mBackgroundExecutor = backgroundExecutor;
218         mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);
219         mScreenOnIntent.addFlags(
220                 Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND
221                 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
222         mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF);
223         mScreenOffIntent.addFlags(
224                 Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND
225                 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
226         mScreenOnOffOptions = createScreenOnOffBroadcastOptions();
227 
228         mSuspendWhenScreenOffDueToProximityConfig = context.getResources().getBoolean(
229                 com.android.internal.R.bool.config_suspendWhenScreenOffDueToProximity);
230         mShowWirelessChargingAnimationConfig = context.getResources().getBoolean(
231                 com.android.internal.R.bool.config_showBuiltinWirelessChargingAnim);
232 
233         mInjector = (injector == null) ? new RealInjector() : injector;
234         mWakeLockLog = mInjector.getWakeLockLog(context);
235         // Initialize interactive state for battery stats.
236         try {
237             mBatteryStats.noteInteractive(true);
238         } catch (RemoteException ex) { }
239         FrameworkStatsLog.write(FrameworkStatsLog.INTERACTIVE_STATE_CHANGED,
240                 FrameworkStatsLog.INTERACTIVE_STATE_CHANGED__STATE__ON);
241     }
242 
243     /**
244      * Create the {@link BroadcastOptions} bundle that will be used with sending the
245      * {@link Intent#ACTION_SCREEN_ON} and {@link Intent#ACTION_SCREEN_OFF} broadcasts.
246      */
createScreenOnOffBroadcastOptions()247     private Bundle createScreenOnOffBroadcastOptions() {
248         final BroadcastOptions options = BroadcastOptions.makeBasic();
249         // This allows the broadcasting system to discard any older broadcasts
250         // waiting to be delivered to a process.
251         options.setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT);
252         // Set namespace and key to identify which older broadcasts can be discarded.
253         // We could use any strings here but namespace needs to be unlikely to be reused with in
254         // the system_server process, as that could result in potentially discarding some
255         // non-screen on/off related broadcast.
256         options.setDeliveryGroupMatchingKey(
257                 UUID.randomUUID().toString(),
258                 Intent.ACTION_SCREEN_ON);
259         // This allows the broadcast delivery to be delayed to apps in the Cached state.
260         options.setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE);
261         return options.toBundle();
262     }
263 
264     /**
265      * Called when a wake lock is acquired.
266      */
onWakeLockAcquired(int flags, String tag, String packageName, int ownerUid, int ownerPid, WorkSource workSource, String historyTag, IWakeLockCallback callback)267     public void onWakeLockAcquired(int flags, String tag, String packageName,
268             int ownerUid, int ownerPid, WorkSource workSource, String historyTag,
269             IWakeLockCallback callback) {
270         if (DEBUG) {
271             Slog.d(TAG, "onWakeLockAcquired: flags=" + flags + ", tag=\"" + tag
272                     + "\", packageName=" + packageName
273                     + ", ownerUid=" + ownerUid + ", ownerPid=" + ownerPid
274                     + ", workSource=" + workSource);
275         }
276         notifyWakeLockListener(callback, tag, true, ownerUid, flags);
277         final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
278         if (monitorType >= 0) {
279             try {
280                 final boolean unimportantForLogging = ownerUid == Process.SYSTEM_UID
281                         && (flags & PowerManager.UNIMPORTANT_FOR_LOGGING) != 0;
282                 if (workSource != null) {
283                     mBatteryStats.noteStartWakelockFromSource(workSource, ownerPid, tag,
284                             historyTag, monitorType, unimportantForLogging);
285                 } else {
286                     mBatteryStats.noteStartWakelock(ownerUid, ownerPid, tag, historyTag,
287                             monitorType, unimportantForLogging);
288                     // XXX need to deal with disabled operations.
289                     mAppOps.startOpNoThrow(AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName);
290                 }
291             } catch (RemoteException ex) {
292                 // Ignore
293             }
294         }
295 
296         if (!mFlags.improveWakelockLatency()) {
297             mWakeLockLog.onWakeLockAcquired(tag, ownerUid, flags, /*eventTime=*/ -1);
298         }
299         mWakefulnessSessionObserver.onWakeLockAcquired(flags);
300     }
301 
onLongPartialWakeLockStart(String tag, int ownerUid, WorkSource workSource, String historyTag)302     public void onLongPartialWakeLockStart(String tag, int ownerUid, WorkSource workSource,
303             String historyTag) {
304         if (DEBUG) {
305             Slog.d(TAG, "onLongPartialWakeLockStart: ownerUid=" + ownerUid
306                     + ", workSource=" + workSource);
307         }
308 
309         try {
310             if (workSource != null) {
311                 mBatteryStats.noteLongPartialWakelockStartFromSource(tag, historyTag, workSource);
312                 FrameworkStatsLog.write(FrameworkStatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED,
313                         workSource, tag, historyTag,
314                         FrameworkStatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__ON);
315             } else {
316                 mBatteryStats.noteLongPartialWakelockStart(tag, historyTag, ownerUid);
317                 FrameworkStatsLog.write_non_chained(
318                         FrameworkStatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED, ownerUid, null, tag,
319                         historyTag,
320                         FrameworkStatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__ON);
321             }
322         } catch (RemoteException ex) {
323             // Ignore
324         }
325     }
326 
onLongPartialWakeLockFinish(String tag, int ownerUid, WorkSource workSource, String historyTag)327     public void onLongPartialWakeLockFinish(String tag, int ownerUid, WorkSource workSource,
328             String historyTag) {
329         if (DEBUG) {
330             Slog.d(TAG, "onLongPartialWakeLockFinish: ownerUid=" + ownerUid
331                     + ", workSource=" + workSource);
332         }
333 
334         try {
335             if (workSource != null) {
336                 mBatteryStats.noteLongPartialWakelockFinishFromSource(tag, historyTag, workSource);
337                 FrameworkStatsLog.write(FrameworkStatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED,
338                         workSource, tag, historyTag,
339                         FrameworkStatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__OFF);
340             } else {
341                 mBatteryStats.noteLongPartialWakelockFinish(tag, historyTag, ownerUid);
342                 FrameworkStatsLog.write_non_chained(
343                         FrameworkStatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED, ownerUid, null, tag,
344                         historyTag,
345                         FrameworkStatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__OFF);
346             }
347         } catch (RemoteException ex) {
348             // Ignore
349         }
350     }
351 
352     /**
353      * Called when a wake lock is changing.
354      */
onWakeLockChanging(int flags, String tag, String packageName, int ownerUid, int ownerPid, WorkSource workSource, String historyTag, IWakeLockCallback callback, int newFlags, String newTag, String newPackageName, int newOwnerUid, int newOwnerPid, WorkSource newWorkSource, String newHistoryTag, IWakeLockCallback newCallback)355     public void onWakeLockChanging(int flags, String tag, String packageName,
356             int ownerUid, int ownerPid, WorkSource workSource, String historyTag,
357             IWakeLockCallback callback, int newFlags, String newTag, String newPackageName,
358             int newOwnerUid, int newOwnerPid, WorkSource newWorkSource, String newHistoryTag,
359             IWakeLockCallback newCallback) {
360 
361         final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
362         final int newMonitorType = getBatteryStatsWakeLockMonitorType(newFlags);
363         if (workSource != null && newWorkSource != null
364                 && monitorType >= 0 && newMonitorType >= 0) {
365             if (DEBUG) {
366                 Slog.d(TAG, "onWakeLockChanging: flags=" + newFlags + ", tag=\"" + newTag
367                         + "\", packageName=" + newPackageName
368                         + ", ownerUid=" + newOwnerUid + ", ownerPid=" + newOwnerPid
369                         + ", workSource=" + newWorkSource);
370             }
371 
372             final boolean unimportantForLogging = newOwnerUid == Process.SYSTEM_UID
373                     && (newFlags & PowerManager.UNIMPORTANT_FOR_LOGGING) != 0;
374             try {
375                 mBatteryStats.noteChangeWakelockFromSource(workSource, ownerPid, tag, historyTag,
376                         monitorType, newWorkSource, newOwnerPid, newTag, newHistoryTag,
377                         newMonitorType, unimportantForLogging);
378             } catch (RemoteException ex) {
379                 // Ignore
380             }
381         } else if (!PowerManagerService.isSameCallback(callback, newCallback)) {
382             onWakeLockReleased(flags, tag, packageName, ownerUid, ownerPid, workSource, historyTag,
383                     null /* Do not notify the old callback */);
384             onWakeLockAcquired(newFlags, newTag, newPackageName, newOwnerUid, newOwnerPid,
385                     newWorkSource, newHistoryTag, newCallback /* notify the new callback */);
386         } else {
387             onWakeLockReleased(flags, tag, packageName, ownerUid, ownerPid, workSource, historyTag,
388                     callback);
389             onWakeLockAcquired(newFlags, newTag, newPackageName, newOwnerUid, newOwnerPid,
390                     newWorkSource, newHistoryTag, newCallback);
391         }
392     }
393 
394     /**
395      * Called when a wake lock is released.
396      */
onWakeLockReleased(int flags, String tag, String packageName, int ownerUid, int ownerPid, WorkSource workSource, String historyTag, IWakeLockCallback callback)397     public void onWakeLockReleased(int flags, String tag, String packageName,
398             int ownerUid, int ownerPid, WorkSource workSource, String historyTag,
399             IWakeLockCallback callback) {
400         onWakeLockReleased(flags, tag, packageName, ownerUid, ownerPid, workSource, historyTag,
401                 callback, ScreenTimeoutOverridePolicy.RELEASE_REASON_UNKNOWN);
402     }
403 
404     /**
405      * Called when a wake lock is released.
406      */
onWakeLockReleased(int flags, String tag, String packageName, int ownerUid, int ownerPid, WorkSource workSource, String historyTag, IWakeLockCallback callback, int releaseReason)407     public void onWakeLockReleased(int flags, String tag, String packageName,
408             int ownerUid, int ownerPid, WorkSource workSource, String historyTag,
409             IWakeLockCallback callback, int releaseReason) {
410         if (DEBUG) {
411             Slog.d(TAG, "onWakeLockReleased: flags=" + flags + ", tag=\"" + tag
412                     + "\", packageName=" + packageName
413                     + ", ownerUid=" + ownerUid + ", ownerPid=" + ownerPid
414                     + ", workSource=" + workSource);
415         }
416         notifyWakeLockListener(callback, tag, false, ownerUid, flags);
417         final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
418         if (monitorType >= 0) {
419             try {
420                 if (workSource != null) {
421                     mBatteryStats.noteStopWakelockFromSource(workSource, ownerPid, tag,
422                             historyTag, monitorType);
423                 } else {
424                     mBatteryStats.noteStopWakelock(ownerUid, ownerPid, tag,
425                             historyTag, monitorType);
426                     mAppOps.finishOp(AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName);
427                 }
428             } catch (RemoteException ex) {
429                 // Ignore
430             }
431         }
432         if (!mFlags.improveWakelockLatency()) {
433             mWakeLockLog.onWakeLockReleased(tag, ownerUid, /*eventTime=*/ -1);
434         }
435         mWakefulnessSessionObserver.onWakeLockReleased(flags, releaseReason);
436     }
437 
438     /** Shows the keyguard without requesting the device to immediately lock. */
showDismissibleKeyguard()439     public void showDismissibleKeyguard() {
440         mPolicy.showDismissibleKeyguard();
441     }
442 
getBatteryStatsWakeLockMonitorType(int flags)443     private int getBatteryStatsWakeLockMonitorType(int flags) {
444         switch (flags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
445             case PowerManager.PARTIAL_WAKE_LOCK:
446                 return BatteryStats.WAKE_TYPE_PARTIAL;
447 
448             case PowerManager.SCREEN_DIM_WAKE_LOCK:
449             case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
450                 return BatteryStats.WAKE_TYPE_FULL;
451 
452             case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
453                 if (mSuspendWhenScreenOffDueToProximityConfig) {
454                     return -1;
455                 }
456                 return BatteryStats.WAKE_TYPE_PARTIAL;
457 
458             case PowerManager.DRAW_WAKE_LOCK:
459                 return BatteryStats.WAKE_TYPE_DRAW;
460 
461             case PowerManager.DOZE_WAKE_LOCK:
462                 // Doze wake locks are an internal implementation detail of the
463                 // communication between dream manager service and power manager
464                 // service.  They have no additive battery impact.
465                 return -1;
466 
467             default:
468                 return -1;
469         }
470     }
471 
472     /**
473      * Notifies that the device is changing wakefulness.
474      * This function may be called even if the previous change hasn't finished in
475      * which case it will assume that the state did not fully converge before the
476      * next transition began and will recover accordingly.
477      */
onGlobalWakefulnessChangeStarted(final int wakefulness, int reason, long eventTime)478     public void onGlobalWakefulnessChangeStarted(final int wakefulness, int reason,
479             long eventTime) {
480         final boolean interactive = PowerManagerInternal.isInteractive(wakefulness);
481         if (DEBUG) {
482             Slog.d(TAG, "onWakefulnessChangeStarted: wakefulness=" + wakefulness
483                     + ", reason=" + reason + ", interactive=" + interactive);
484         }
485 
486         // Tell the activity manager about changes in wakefulness, not just interactivity.
487         // It needs more granularity than other components.
488         mHandler.post(new Runnable() {
489             @Override
490             public void run() {
491                 mActivityManagerInternal.onWakefulnessChanged(wakefulness);
492             }
493         });
494 
495         // Handle any early interactive state changes.
496         // Finish pending incomplete ones from a previous cycle.
497         if (mGlobalInteractivity.isInteractive != interactive) {
498             // Finish up late behaviors if needed.
499             if (mGlobalInteractivity.isChanging) {
500                 handleLateGlobalInteractiveChange();
501             }
502 
503             // Start input as soon as we start waking up or going to sleep.
504             mInputManagerInternal.setInteractive(interactive);
505             mInputMethodManagerInternal.setInteractive(interactive);
506 
507             // Notify battery stats.
508             try {
509                 mBatteryStats.noteInteractive(interactive);
510             } catch (RemoteException ex) { }
511             FrameworkStatsLog.write(FrameworkStatsLog.INTERACTIVE_STATE_CHANGED,
512                     interactive ? FrameworkStatsLog.INTERACTIVE_STATE_CHANGED__STATE__ON :
513                             FrameworkStatsLog.INTERACTIVE_STATE_CHANGED__STATE__OFF);
514 
515             // Handle early behaviors.
516             mGlobalInteractivity.isInteractive = interactive;
517             mGlobalInteractivity.isChanging = true;
518             mGlobalInteractivity.changeReason = reason;
519             mGlobalInteractivity.changeStartTime = eventTime;
520             handleEarlyGlobalInteractiveChange();
521         }
522     }
523 
524     /**
525      * Notifies that the device has finished changing wakefulness.
526      */
onWakefulnessChangeFinished()527     public void onWakefulnessChangeFinished() {
528         if (DEBUG) {
529             Slog.d(TAG, "onWakefulnessChangeFinished");
530         }
531         for (int i = 0; i < mInteractivityByGroupId.size(); i++) {
532             int groupId = mInteractivityByGroupId.keyAt(i);
533             Interactivity interactivity = mInteractivityByGroupId.valueAt(i);
534             if (interactivity.isChanging) {
535                 interactivity.isChanging = false;
536                 handleLateInteractiveChange(groupId);
537             }
538         }
539         if (mGlobalInteractivity.isChanging) {
540             mGlobalInteractivity.isChanging = false;
541             handleLateGlobalInteractiveChange();
542         }
543     }
544 
545 
handleEarlyInteractiveChange(int groupId)546     private void handleEarlyInteractiveChange(int groupId) {
547         synchronized (mLock) {
548             Interactivity interactivity = mInteractivityByGroupId.get(groupId);
549             if (interactivity == null) {
550                 Slog.e(TAG, "no Interactivity entry for groupId:" + groupId);
551                 return;
552             }
553             final int changeReason = interactivity.changeReason;
554             if (interactivity.isInteractive) {
555                 mHandler.post(() -> mPolicy.startedWakingUp(groupId, changeReason));
556             } else {
557                 mHandler.post(() -> mPolicy.startedGoingToSleep(groupId, changeReason));
558             }
559         }
560     }
561 
562     /**
563      * Handle early interactive state changes such as getting applications or the lock
564      * screen running and ready for the user to see (such as when turning on the screen).
565      */
handleEarlyGlobalInteractiveChange()566     private void handleEarlyGlobalInteractiveChange() {
567         synchronized (mLock) {
568             if (mGlobalInteractivity.isInteractive) {
569                 // Waking up...
570                 mHandler.post(() -> {
571                     mDisplayManagerInternal.onEarlyInteractivityChange(true /*isInteractive*/);
572                     mPolicy.startedWakingUpGlobal(mGlobalInteractivity.changeReason);
573                 });
574 
575                 // Send interactive broadcast.
576                 mPendingInteractiveState = INTERACTIVE_STATE_AWAKE;
577                 mPendingWakeUpBroadcast = true;
578                 updatePendingBroadcastLocked();
579             } else {
580                 // Going to sleep...
581                 mHandler.post(() -> {
582                     mDisplayManagerInternal.onEarlyInteractivityChange(false /*isInteractive*/);
583                     mPolicy.startedGoingToSleepGlobal(mGlobalInteractivity.changeReason);
584                 });
585             }
586         }
587     }
588 
589     /**
590      * Handle late global interactive state changes. Also see
591      * {@link #handleLateInteractiveChange(int)}.
592      */
handleLateGlobalInteractiveChange()593     private void handleLateGlobalInteractiveChange() {
594         synchronized (mLock) {
595             final int interactiveChangeLatency =
596                     (int) (SystemClock.uptimeMillis() - mGlobalInteractivity.changeStartTime);
597             if (mGlobalInteractivity.isInteractive) {
598                 // Finished waking up...
599                 mHandler.post(() -> {
600                     LogMaker log = new LogMaker(MetricsEvent.SCREEN);
601                     log.setType(MetricsEvent.TYPE_OPEN);
602                     log.setSubtype(WindowManagerPolicyConstants.translateWakeReasonToOnReason(
603                             mGlobalInteractivity.changeReason));
604                     log.setLatency(interactiveChangeLatency);
605                     log.addTaggedData(MetricsEvent.FIELD_SCREEN_WAKE_REASON,
606                             mGlobalInteractivity.changeReason);
607                     MetricsLogger.action(log);
608                     EventLogTags.writePowerScreenState(1, 0, 0, 0, interactiveChangeLatency);
609 
610                     mPolicy.finishedWakingUpGlobal(mGlobalInteractivity.changeReason);
611                 });
612             } else {
613                 // Finished going to sleep...
614                 // This is a good time to make transitions that we don't want the user to see,
615                 // such as bringing the key guard to focus.  There's no guarantee for this
616                 // however because the user could turn the device on again at any time.
617                 // Some things may need to be protected by other mechanisms that defer screen on.
618 
619                 // Cancel pending user activity.
620                 if (mUserActivityPending) {
621                     mUserActivityPending = false;
622                     mHandler.removeMessages(MSG_USER_ACTIVITY);
623                 }
624 
625                 // Tell the policy we finished going to sleep.
626                 final int offReason = WindowManagerPolicyConstants.translateSleepReasonToOffReason(
627                         mGlobalInteractivity.changeReason);
628                 mHandler.post(() -> {
629                     LogMaker log = new LogMaker(MetricsEvent.SCREEN);
630                     log.setType(MetricsEvent.TYPE_CLOSE);
631                     log.setSubtype(offReason);
632                     log.setLatency(interactiveChangeLatency);
633                     log.addTaggedData(MetricsEvent.FIELD_SCREEN_SLEEP_REASON,
634                             mGlobalInteractivity.changeReason);
635                     MetricsLogger.action(log);
636                     EventLogTags.writePowerScreenState(
637                             0, offReason, 0, 0, interactiveChangeLatency);
638 
639                     mPolicy.finishedGoingToSleepGlobal(mGlobalInteractivity.changeReason);
640                 });
641 
642                 // Send non-interactive broadcast.
643                 mPendingInteractiveState = INTERACTIVE_STATE_ASLEEP;
644                 mPendingGoToSleepBroadcast = true;
645                 updatePendingBroadcastLocked();
646             }
647         }
648     }
649 
650     /**
651      * Handle late interactive state changes once they are finished so that the system can
652      * finish pending transitions (such as turning the screen off) before causing
653      * applications to change state visibly.
654      */
handleLateInteractiveChange(int groupId)655     private void handleLateInteractiveChange(int groupId) {
656         synchronized (mLock) {
657             Interactivity interactivity = mInteractivityByGroupId.get(groupId);
658             if (interactivity == null) {
659                 Slog.e(TAG, "no Interactivity entry for groupId:" + groupId);
660                 return;
661             }
662             final int changeReason = interactivity.changeReason;
663             if (interactivity.isInteractive) {
664                 mHandler.post(() -> mPolicy.finishedWakingUp(groupId, changeReason));
665             } else {
666                 mHandler.post(() -> mPolicy.finishedGoingToSleep(groupId, changeReason));
667             }
668         }
669     }
670 
671     /**
672      * Called when an individual PowerGroup changes wakefulness.
673      */
onGroupWakefulnessChangeStarted(int groupId, int wakefulness, int changeReason, long eventTime)674     public void onGroupWakefulnessChangeStarted(int groupId, int wakefulness, int changeReason,
675             long eventTime) {
676         final boolean isInteractive = PowerManagerInternal.isInteractive(wakefulness);
677 
678         boolean isNewGroup = false;
679         Interactivity interactivity = mInteractivityByGroupId.get(groupId);
680         if (interactivity == null) {
681             isNewGroup = true;
682             interactivity = new Interactivity();
683             mInteractivityByGroupId.put(groupId, interactivity);
684         }
685         if (isNewGroup || interactivity.isInteractive != isInteractive) {
686             // Finish up late behaviors if needed.
687             if (interactivity.isChanging) {
688                 handleLateInteractiveChange(groupId);
689             }
690 
691             // Handle early behaviors.
692             interactivity.isInteractive = isInteractive;
693             interactivity.changeReason = changeReason;
694             interactivity.changeStartTime = eventTime;
695             interactivity.isChanging = true;
696             handleEarlyInteractiveChange(groupId);
697             mWakefulnessSessionObserver.onWakefulnessChangeStarted(groupId, wakefulness,
698                     changeReason, eventTime);
699         }
700     }
701 
702     /**
703      * Called when a PowerGroup has been removed.
704      *
705      * @param groupId which group was removed
706      */
onGroupRemoved(int groupId)707     public void onGroupRemoved(int groupId) {
708         mInteractivityByGroupId.remove(groupId);
709         mWakefulnessSessionObserver.removePowerGroup(groupId);
710     }
711 
712     /**
713      * Called when there has been user activity.
714      */
onUserActivity(int displayGroupId, @PowerManager.UserActivityEvent int event, int uid)715     public void onUserActivity(int displayGroupId, @PowerManager.UserActivityEvent int event,
716             int uid) {
717         if (DEBUG) {
718             Slog.d(TAG, "onUserActivity: event=" + event + ", uid=" + uid);
719         }
720 
721         try {
722             mBatteryStats.noteUserActivity(uid, event);
723             mWakefulnessSessionObserver.notifyUserActivity(
724                     SystemClock.uptimeMillis(), displayGroupId, event);
725         } catch (RemoteException ex) {
726             // Ignore
727         }
728 
729         synchronized (mLock) {
730             if (!mUserActivityPending) {
731                 mUserActivityPending = true;
732                 Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY);
733                 msg.arg1 = displayGroupId;
734                 msg.arg2 = event;
735                 msg.setAsynchronous(true);
736                 mHandler.sendMessage(msg);
737             }
738         }
739     }
740 
741     /**
742      * Called when the screen has turned on.
743      */
onWakeUp(int reason, String details, int reasonUid, String opPackageName, int opUid)744     public void onWakeUp(int reason, String details, int reasonUid, String opPackageName,
745             int opUid) {
746         if (DEBUG) {
747             Slog.d(TAG, "onWakeUp: reason=" + PowerManager.wakeReasonToString(reason)
748                     + ", details=" + details + ", reasonUid=" + reasonUid
749                     + " opPackageName=" + opPackageName + " opUid=" + opUid);
750         }
751 
752         try {
753             mBatteryStats.noteWakeUp(details, reasonUid);
754             if (opPackageName != null) {
755                 mAppOps.noteOpNoThrow(AppOpsManager.OP_TURN_SCREEN_ON, opUid, opPackageName);
756             }
757         } catch (RemoteException ex) {
758             // Ignore
759         }
760         FrameworkStatsLog.write(FrameworkStatsLog.DISPLAY_WAKE_REPORTED, reason, reasonUid);
761     }
762 
763     /**
764      * Called when profile screen lock timeout has expired.
765      */
onProfileTimeout(@serIdInt int userId)766     public void onProfileTimeout(@UserIdInt int userId) {
767         final Message msg = mHandler.obtainMessage(MSG_PROFILE_TIMED_OUT);
768         msg.setAsynchronous(true);
769         msg.arg1 = userId;
770         mHandler.sendMessage(msg);
771     }
772 
773     /**
774      * Called when wireless charging has started - to provide user feedback (sound and visual).
775      */
onWirelessChargingStarted(int batteryLevel, @UserIdInt int userId)776     public void onWirelessChargingStarted(int batteryLevel, @UserIdInt int userId) {
777         if (DEBUG) {
778             Slog.d(TAG, "onWirelessChargingStarted");
779         }
780 
781         mSuspendBlocker.acquire();
782         Message msg = mHandler.obtainMessage(MSG_WIRELESS_CHARGING_STARTED);
783         msg.setAsynchronous(true);
784         msg.arg1 = batteryLevel;
785         msg.arg2 = userId;
786         mHandler.sendMessage(msg);
787     }
788 
789     /**
790      * Called when wired charging has started - to provide user feedback
791      */
onWiredChargingStarted(@serIdInt int userId)792     public void onWiredChargingStarted(@UserIdInt int userId) {
793         if (DEBUG) {
794             Slog.d(TAG, "onWiredChargingStarted");
795         }
796 
797         mSuspendBlocker.acquire();
798         Message msg = mHandler.obtainMessage(MSG_WIRED_CHARGING_STARTED);
799         msg.setAsynchronous(true);
800         msg.arg1 = userId;
801         mHandler.sendMessage(msg);
802     }
803 
804     /**
805      * Called when the screen policy changes.
806      */
onScreenPolicyUpdate(int displayGroupId, int newPolicy)807     public void onScreenPolicyUpdate(int displayGroupId, int newPolicy) {
808         if (DEBUG) {
809             Slog.d(TAG, "onScreenPolicyUpdate: newPolicy=" + newPolicy);
810         }
811 
812         synchronized (mLock) {
813             Message msg = mHandler.obtainMessage(MSG_SCREEN_POLICY);
814             msg.arg1 = displayGroupId;
815             msg.arg2 = newPolicy;
816             msg.setAsynchronous(true);
817             mHandler.sendMessage(msg);
818         }
819     }
820 
821     /**
822      * Dumps data for bugreports.
823      *
824      * @param pw The stream to print to.
825      */
dump(PrintWriter pw)826     public void dump(PrintWriter pw) {
827         if (mWakeLockLog != null) {
828             mWakeLockLog.dump(pw);
829         }
830 
831         mWakefulnessSessionObserver.dump(pw);
832     }
833 
updatePendingBroadcastLocked()834     private void updatePendingBroadcastLocked() {
835         if (!mBroadcastInProgress
836                 && mPendingInteractiveState != INTERACTIVE_STATE_UNKNOWN
837                 && (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
838                         || mPendingInteractiveState != mBroadcastedInteractiveState)) {
839             mBroadcastInProgress = true;
840             mSuspendBlocker.acquire();
841             Message msg = mHandler.obtainMessage(MSG_BROADCAST);
842             msg.setAsynchronous(true);
843             mHandler.sendMessage(msg);
844         }
845     }
846 
finishPendingBroadcastLocked()847     private void finishPendingBroadcastLocked() {
848         mBroadcastInProgress = false;
849         mSuspendBlocker.release();
850     }
851 
sendUserActivity(int displayGroupId, int event)852     private void sendUserActivity(int displayGroupId, int event) {
853         synchronized (mLock) {
854             if (!mUserActivityPending) {
855                 return;
856             }
857             mUserActivityPending = false;
858         }
859         TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
860         tm.notifyUserActivity();
861         mInputManagerInternal.notifyUserActivity();
862         mPolicy.userActivity(displayGroupId, event);
863         mFaceDownDetector.userActivity(event);
864         mScreenUndimDetector.userActivity(displayGroupId);
865     }
866 
postEnhancedDischargePredictionBroadcast(long delayMs)867     void postEnhancedDischargePredictionBroadcast(long delayMs) {
868         mHandler.sendEmptyMessageDelayed(MSG_BROADCAST_ENHANCED_PREDICTION, delayMs);
869     }
870 
sendEnhancedDischargePredictionBroadcast()871     private void sendEnhancedDischargePredictionBroadcast() {
872         Intent intent = new Intent(PowerManager.ACTION_ENHANCED_DISCHARGE_PREDICTION_CHANGED)
873                 .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
874         mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
875     }
876 
sendNextBroadcast()877     private void sendNextBroadcast() {
878         final int powerState;
879         synchronized (mLock) {
880             if (mBroadcastedInteractiveState == INTERACTIVE_STATE_UNKNOWN) {
881                 // Broadcasted power state is unknown.
882                 // Send wake up or go to sleep.
883                 switch (mPendingInteractiveState) {
884                     case INTERACTIVE_STATE_ASLEEP:
885                         mPendingGoToSleepBroadcast = false;
886                         mBroadcastedInteractiveState = INTERACTIVE_STATE_ASLEEP;
887                         break;
888 
889                     case INTERACTIVE_STATE_AWAKE:
890                     default:
891                         mPendingWakeUpBroadcast = false;
892                         mBroadcastedInteractiveState = INTERACTIVE_STATE_AWAKE;
893                         break;
894                 }
895             } else if (mBroadcastedInteractiveState == INTERACTIVE_STATE_AWAKE) {
896                 // Broadcasted power state is awake.  Send asleep if needed.
897                 if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
898                         || mPendingInteractiveState == INTERACTIVE_STATE_ASLEEP) {
899                     mPendingGoToSleepBroadcast = false;
900                     mBroadcastedInteractiveState = INTERACTIVE_STATE_ASLEEP;
901                 } else {
902                     finishPendingBroadcastLocked();
903                     return;
904                 }
905             } else {
906                 // Broadcasted power state is asleep.  Send awake if needed.
907                 if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
908                         || mPendingInteractiveState == INTERACTIVE_STATE_AWAKE) {
909                     mPendingWakeUpBroadcast = false;
910                     mBroadcastedInteractiveState = INTERACTIVE_STATE_AWAKE;
911                 } else {
912                     finishPendingBroadcastLocked();
913                     return;
914                 }
915             }
916 
917             mBroadcastStartTime = SystemClock.uptimeMillis();
918             powerState = mBroadcastedInteractiveState;
919         }
920 
921         EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_SEND, 1);
922 
923         if (powerState == INTERACTIVE_STATE_AWAKE) {
924             sendWakeUpBroadcast();
925         } else {
926             sendGoToSleepBroadcast();
927         }
928     }
929 
sendWakeUpBroadcast()930     private void sendWakeUpBroadcast() {
931         if (DEBUG) {
932             Slog.d(TAG, "Sending wake up broadcast.");
933         }
934 
935         if (mActivityManagerInternal.isSystemReady()) {
936             mActivityManagerInternal.broadcastIntentWithCallback(mScreenOnIntent,
937                     mWakeUpBroadcastDone, null, UserHandle.USER_ALL,
938                     null, null, mScreenOnOffOptions);
939         } else {
940             EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 2, 1);
941             sendNextBroadcast();
942         }
943     }
944 
945     private final IIntentReceiver mWakeUpBroadcastDone = new IIntentReceiver.Stub() {
946         @Override
947         public void performReceive(Intent intent, int resultCode, String data, Bundle extras,
948                 boolean ordered, boolean sticky, int sendingUser) {
949             EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 1,
950                     SystemClock.uptimeMillis() - mBroadcastStartTime, 1);
951             sendNextBroadcast();
952         }
953     };
954 
sendGoToSleepBroadcast()955     private void sendGoToSleepBroadcast() {
956         if (DEBUG) {
957             Slog.d(TAG, "Sending go to sleep broadcast.");
958         }
959 
960         if (mActivityManagerInternal.isSystemReady()) {
961             mActivityManagerInternal.broadcastIntentWithCallback(mScreenOffIntent,
962                     mGoToSleepBroadcastDone, null, UserHandle.USER_ALL,
963                     null, null, mScreenOnOffOptions);
964         } else {
965             EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 3, 1);
966             sendNextBroadcast();
967         }
968     }
969 
970     private final IIntentReceiver mGoToSleepBroadcastDone = new IIntentReceiver.Stub() {
971         @Override
972         public void performReceive(Intent intent, int resultCode, String data, Bundle extras,
973                 boolean ordered, boolean sticky, int sendingUser) {
974             EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 0,
975                     SystemClock.uptimeMillis() - mBroadcastStartTime, 1);
976             sendNextBroadcast();
977         }
978     };
979 
playChargingStartedFeedback(@serIdInt int userId, boolean wireless)980     private void playChargingStartedFeedback(@UserIdInt int userId, boolean wireless) {
981         if (!isChargingFeedbackEnabled(userId)) {
982             return;
983         }
984 
985         if (!mIsPlayingChargingStartedFeedback.compareAndSet(false, true)) {
986             // there's already a charging started feedback Runnable scheduled to run on the
987             // background thread, so let's not execute another
988             return;
989         }
990 
991         // vibrate & play sound on a background thread
992         mBackgroundExecutor.execute(() -> {
993             // vibrate
994             final boolean vibrate = Settings.Secure.getIntForUser(mContext.getContentResolver(),
995                     Settings.Secure.CHARGING_VIBRATION_ENABLED, 1, userId) != 0;
996             if (vibrate) {
997                 mVibrator.vibrate(Process.SYSTEM_UID, mContext.getOpPackageName(),
998                         CHARGING_VIBRATION_EFFECT, /* reason= */ "Charging started",
999                         HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES);
1000             }
1001 
1002             // play sound
1003             final String soundPath = Settings.Global.getString(mContext.getContentResolver(),
1004                     wireless ? Settings.Global.WIRELESS_CHARGING_STARTED_SOUND
1005                             : Settings.Global.CHARGING_STARTED_SOUND);
1006             final Uri soundUri = Uri.parse("file://" + soundPath);
1007             if (soundUri != null) {
1008                 final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
1009                 if (sfx != null) {
1010                     sfx.setStreamType(AudioManager.STREAM_SYSTEM);
1011                     sfx.play();
1012                 }
1013             }
1014             mIsPlayingChargingStartedFeedback.set(false);
1015         });
1016     }
1017 
showWirelessChargingStarted(int batteryLevel, @UserIdInt int userId)1018     private void showWirelessChargingStarted(int batteryLevel, @UserIdInt int userId) {
1019         // play sounds + haptics
1020         playChargingStartedFeedback(userId, true /* wireless */);
1021 
1022         // show animation
1023         if (mShowWirelessChargingAnimationConfig && mStatusBarManagerInternal != null) {
1024             mStatusBarManagerInternal.showChargingAnimation(batteryLevel);
1025         }
1026         mSuspendBlocker.release();
1027     }
1028 
showWiredChargingStarted(@serIdInt int userId)1029     private void showWiredChargingStarted(@UserIdInt int userId) {
1030         playChargingStartedFeedback(userId, false /* wireless */);
1031         mSuspendBlocker.release();
1032     }
1033 
screenPolicyChanging(int displayGroupId, int screenPolicy)1034     private void screenPolicyChanging(int displayGroupId, int screenPolicy) {
1035         mScreenUndimDetector.recordScreenPolicy(displayGroupId, screenPolicy);
1036     }
1037 
lockProfile(@serIdInt int userId)1038     private void lockProfile(@UserIdInt int userId) {
1039         mTrustManager.setDeviceLockedForUser(userId, true /*locked*/);
1040     }
1041 
isChargingFeedbackEnabled(@serIdInt int userId)1042     private boolean isChargingFeedbackEnabled(@UserIdInt int userId) {
1043         final boolean enabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
1044                 Settings.Secure.CHARGING_SOUNDS_ENABLED, 1, userId) != 0;
1045         final boolean dndOff = Settings.Global.getInt(mContext.getContentResolver(),
1046                 Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS)
1047                 == Settings.Global.ZEN_MODE_OFF;
1048         return enabled && dndOff;
1049     }
1050 
notifyWakeLockListener(IWakeLockCallback callback, String tag, boolean isEnabled, int ownerUid, int flags)1051     private void notifyWakeLockListener(IWakeLockCallback callback, String tag, boolean isEnabled,
1052             int ownerUid, int flags) {
1053         if (callback != null) {
1054             long currentTime = mInjector.currentTimeMillis();
1055             mHandler.post(() -> {
1056                 try {
1057                     if (mFlags.improveWakelockLatency()) {
1058                         if (isEnabled) {
1059                             mWakeLockLog.onWakeLockAcquired(tag, ownerUid, flags, currentTime);
1060                         } else {
1061                             mWakeLockLog.onWakeLockReleased(tag, ownerUid, currentTime);
1062                         }
1063                     }
1064                     callback.onStateChanged(isEnabled);
1065                 } catch (RemoteException e) {
1066                     Slog.e(TAG, "Wakelock.mCallback [" + tag + "] is already dead.", e);
1067                 }
1068             });
1069         }
1070     }
1071 
1072     private final class NotifierHandler extends Handler {
1073 
NotifierHandler(Looper looper)1074         public NotifierHandler(Looper looper) {
1075             super(looper, null, true /*async*/);
1076         }
1077 
1078         @Override
handleMessage(Message msg)1079         public void handleMessage(Message msg) {
1080             switch (msg.what) {
1081                 case MSG_USER_ACTIVITY:
1082                     sendUserActivity(msg.arg1, msg.arg2);
1083                     break;
1084                 case MSG_BROADCAST:
1085                     sendNextBroadcast();
1086                     break;
1087                 case MSG_WIRELESS_CHARGING_STARTED:
1088                     showWirelessChargingStarted(msg.arg1, msg.arg2);
1089                     break;
1090                 case MSG_BROADCAST_ENHANCED_PREDICTION:
1091                     removeMessages(MSG_BROADCAST_ENHANCED_PREDICTION);
1092                     sendEnhancedDischargePredictionBroadcast();
1093                     break;
1094                 case MSG_PROFILE_TIMED_OUT:
1095                     lockProfile(msg.arg1);
1096                     break;
1097                 case MSG_WIRED_CHARGING_STARTED:
1098                     showWiredChargingStarted(msg.arg1);
1099                     break;
1100                 case MSG_SCREEN_POLICY:
1101                     screenPolicyChanging(msg.arg1, msg.arg2);
1102                     break;
1103             }
1104         }
1105     }
1106 
1107     public interface Injector {
1108         /**
1109          * Gets the current time in millis
1110          */
currentTimeMillis()1111         long currentTimeMillis();
1112 
1113         /**
1114          * Gets the WakeLockLog object
1115          */
getWakeLockLog(Context context)1116         WakeLockLog getWakeLockLog(Context context);
1117     }
1118 
1119     static class RealInjector implements Injector {
1120         @Override
currentTimeMillis()1121         public long currentTimeMillis() {
1122             return System.currentTimeMillis();
1123         }
1124 
1125         @Override
getWakeLockLog(Context context)1126         public WakeLockLog getWakeLockLog(Context context) {
1127             return new WakeLockLog(context);
1128         }
1129     }
1130 }
1131