• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.SuppressLint;
22 import android.annotation.UserIdInt;
23 import android.app.ActivityManagerInternal;
24 import android.app.AppOpsManager;
25 import android.app.BroadcastOptions;
26 import android.app.trust.TrustManager;
27 import android.content.Context;
28 import android.content.IIntentReceiver;
29 import android.content.Intent;
30 import android.hardware.display.DisplayManagerInternal;
31 import android.media.AudioManager;
32 import android.media.Ringtone;
33 import android.media.RingtoneManager;
34 import android.metrics.LogMaker;
35 import android.net.Uri;
36 import android.os.BatteryStats;
37 import android.os.BatteryStatsInternal;
38 import android.os.Bundle;
39 import android.os.Handler;
40 import android.os.IScreenTimeoutPolicyListener;
41 import android.os.IWakeLockCallback;
42 import android.os.Looper;
43 import android.os.Message;
44 import android.os.PowerManager;
45 import android.os.PowerManager.ScreenTimeoutPolicy;
46 import android.os.PowerManagerInternal;
47 import android.os.Process;
48 import android.os.RemoteCallbackList;
49 import android.os.RemoteException;
50 import android.os.SystemClock;
51 import android.os.UserHandle;
52 import android.os.VibrationAttributes;
53 import android.os.VibrationEffect;
54 import android.os.Vibrator;
55 import android.os.WorkSource;
56 import android.os.WorkSource.WorkChain;
57 import android.provider.Settings;
58 import android.telephony.TelephonyManager;
59 import android.util.ArrayMap;
60 import android.util.EventLog;
61 import android.util.Slog;
62 import android.util.SparseArray;
63 import android.util.SparseBooleanArray;
64 import android.view.WindowManagerPolicyConstants;
65 
66 import com.android.internal.annotations.VisibleForTesting;
67 import com.android.internal.app.IBatteryStats;
68 import com.android.internal.logging.MetricsLogger;
69 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
70 import com.android.internal.util.FrameworkStatsLog;
71 import com.android.internal.util.IndentingPrintWriter;
72 import com.android.server.EventLogTags;
73 import com.android.server.LocalServices;
74 import com.android.server.input.InputManagerInternal;
75 import com.android.server.inputmethod.InputMethodManagerInternal;
76 import com.android.server.policy.WindowManagerPolicy;
77 import com.android.server.power.FrameworkStatsLogger.WakelockEventType;
78 import com.android.server.power.feature.PowerManagerFlags;
79 import com.android.server.statusbar.StatusBarManagerInternal;
80 
81 import java.io.PrintWriter;
82 import java.util.List;
83 import java.util.UUID;
84 import java.util.concurrent.Executor;
85 import java.util.concurrent.atomic.AtomicBoolean;
86 
87 /**
88  * Sends broadcasts about important power state changes.
89  * <p>
90  * This methods of this class may be called by the power manager service while
91  * its lock is being held.  Internally it takes care of sending broadcasts to
92  * notify other components of the system or applications asynchronously.
93  * </p><p>
94  * The notifier is designed to collapse unnecessary broadcasts when it is not
95  * possible for the system to have observed an intermediate state.
96  * </p><p>
97  * For example, if the device wakes up, goes to sleep, wakes up again and goes to
98  * sleep again before the wake up notification is sent, then the system will
99  * be told about only one wake up and sleep.  However, we always notify the
100  * fact that at least one transition occurred.  It is especially important to
101  * tell the system when we go to sleep so that it can lock the keyguard if needed.
102  * </p>
103  */
104 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED)
105 public class Notifier {
106     private static final String TAG = "PowerManagerNotifier";
107 
108     private static final boolean DEBUG = false;
109 
110     private static final int INTERACTIVE_STATE_UNKNOWN = 0;
111     private static final int INTERACTIVE_STATE_AWAKE = 1;
112     private static final int INTERACTIVE_STATE_ASLEEP = 2;
113 
114     private static final int MSG_USER_ACTIVITY = 1;
115     private static final int MSG_BROADCAST = 2;
116     private static final int MSG_WIRELESS_CHARGING_STARTED = 3;
117     private static final int MSG_BROADCAST_ENHANCED_PREDICTION = 4;
118     private static final int MSG_PROFILE_TIMED_OUT = 5;
119     private static final int MSG_WIRED_CHARGING_STARTED = 6;
120     private static final int MSG_SCREEN_POLICY = 7;
121 
122     private static final long[] CHARGING_VIBRATION_TIME = {
123             40, 40, 40, 40, 40, 40, 40, 40, 40, // ramp-up sampling rate = 40ms
124             40, 40, 40, 40, 40, 40, 40 // ramp-down sampling rate = 40ms
125     };
126     private static final int[] CHARGING_VIBRATION_AMPLITUDE = {
127             1, 4, 11, 25, 44, 67, 91, 114, 123, // ramp-up amplitude (from 0 to 50%)
128             103, 79, 55, 34, 17, 7, 2 // ramp-up amplitude
129     };
130     private static final VibrationEffect CHARGING_VIBRATION_EFFECT =
131             VibrationEffect.createWaveform(CHARGING_VIBRATION_TIME, CHARGING_VIBRATION_AMPLITUDE,
132                     -1);
133     private static final VibrationAttributes HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES =
134             VibrationAttributes.createForUsage(VibrationAttributes.USAGE_HARDWARE_FEEDBACK);
135 
136     private final Object mLock = new Object();
137 
138     private final Context mContext;
139     private final IBatteryStats mBatteryStats;
140     private final AppOpsManager mAppOps;
141     private final SuspendBlocker mSuspendBlocker;
142     private final WindowManagerPolicy mPolicy;
143     private final FaceDownDetector mFaceDownDetector;
144     private final ScreenUndimDetector mScreenUndimDetector;
145     private final WakefulnessSessionObserver mWakefulnessSessionObserver;
146     private final ActivityManagerInternal mActivityManagerInternal;
147     private final InputManagerInternal mInputManagerInternal;
148     private final InputMethodManagerInternal mInputMethodManagerInternal;
149     @Nullable private final StatusBarManagerInternal mStatusBarManagerInternal;
150     private final TrustManager mTrustManager;
151     private final Vibrator mVibrator;
152     @NonNull private final WakeLockLog mPartialWakeLockLog;
153     @NonNull private final WakeLockLog mFullWakeLockLog;
154     private final DisplayManagerInternal mDisplayManagerInternal;
155 
156     private final NotifierHandler mHandler;
157     private final Executor mBackgroundExecutor;
158     private final Intent mScreenOnIntent;
159     private final Intent mScreenOffIntent;
160     private final Bundle mScreenOnOffOptions;
161 
162     // Display id -> ScreenTimeoutPolicyListenersContainer that contains list of screen
163     // wake lock listeners
164     private final SparseArray<ScreenTimeoutPolicyListenersContainer> mScreenTimeoutPolicyListeners
165             = new SparseArray<>();
166 
167     // True if the device should suspend when the screen is off due to proximity.
168     private final boolean mSuspendWhenScreenOffDueToProximityConfig;
169 
170     // True if the device should show the wireless charging animation when the device
171     // begins charging wirelessly
172     private final boolean mShowWirelessChargingAnimationConfig;
173 
174     // Encapsulates interactivity information about a particular display group.
175     private static class Interactivity {
176         public boolean isInteractive = true;
177         public int changeReason;
178         public long changeStartTime; // In SystemClock.uptimeMillis()
179         public boolean isChanging;
180     }
181 
182     private final SparseArray<Interactivity> mInteractivityByGroupId = new SparseArray<>();
183     private SparseBooleanArray mDisplayInteractivities = new SparseBooleanArray();
184 
185     // The current global interactive state.  This is set as soon as an interactive state
186     // transition begins so as to capture the reason that it happened.  At some point
187     // this state will propagate to the pending state then eventually to the
188     // broadcasted state over the course of reporting the transition asynchronously.
189     private Interactivity mGlobalInteractivity = new Interactivity();
190 
191     // The pending interactive state that we will eventually want to broadcast.
192     // This is designed so that we can collapse redundant sequences of awake/sleep
193     // transition pairs while still guaranteeing that at least one transition is observed
194     // whenever this happens.
195     private int mPendingInteractiveState;
196     private boolean mPendingWakeUpBroadcast;
197     private boolean mPendingGoToSleepBroadcast;
198 
199     // The currently broadcasted interactive state.  This reflects what other parts of the
200     // system have observed.
201     private int mBroadcastedInteractiveState;
202     private boolean mBroadcastInProgress;
203     private long mBroadcastStartTime;
204 
205     // True if a user activity message should be sent.
206     private boolean mUserActivityPending;
207 
208     private final AtomicBoolean mIsPlayingChargingStartedFeedback = new AtomicBoolean(false);
209 
210     private final Injector mInjector;
211 
212     private final PowerManagerFlags mFlags;
213 
214     private final BatteryStatsInternal mBatteryStatsInternal;
215     private final FrameworkStatsLogger mFrameworkStatsLogger;
216 
Notifier(Looper looper, Context context, IBatteryStats batteryStats, SuspendBlocker suspendBlocker, WindowManagerPolicy policy, FaceDownDetector faceDownDetector, ScreenUndimDetector screenUndimDetector, Executor backgroundExecutor, PowerManagerFlags powerManagerFlags, Injector injector)217     public Notifier(Looper looper, Context context, IBatteryStats batteryStats,
218             SuspendBlocker suspendBlocker, WindowManagerPolicy policy,
219             FaceDownDetector faceDownDetector, ScreenUndimDetector screenUndimDetector,
220             Executor backgroundExecutor, PowerManagerFlags powerManagerFlags, Injector injector) {
221         mContext = context;
222         mInjector = (injector == null) ? new RealInjector() : injector;
223         mFlags = powerManagerFlags;
224         mBatteryStats = batteryStats;
225         mAppOps = mInjector.getAppOpsManager(context);
226         mSuspendBlocker = suspendBlocker;
227         mPolicy = policy;
228         mFaceDownDetector = faceDownDetector;
229         mScreenUndimDetector = screenUndimDetector;
230         mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
231         mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
232         mInputMethodManagerInternal = LocalServices.getService(InputMethodManagerInternal.class);
233         mStatusBarManagerInternal = LocalServices.getService(StatusBarManagerInternal.class);
234         mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
235         mTrustManager = mContext.getSystemService(TrustManager.class);
236         mVibrator = mContext.getSystemService(Vibrator.class);
237         mWakefulnessSessionObserver = new WakefulnessSessionObserver(mContext, null);
238 
239         mHandler = new NotifierHandler(looper);
240         mBackgroundExecutor = backgroundExecutor;
241         mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);
242         mScreenOnIntent.addFlags(
243                 Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND
244                 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
245         mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF);
246         mScreenOffIntent.addFlags(
247                 Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND
248                 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
249         mScreenOnOffOptions = createScreenOnOffBroadcastOptions();
250 
251         mSuspendWhenScreenOffDueToProximityConfig = context.getResources().getBoolean(
252                 com.android.internal.R.bool.config_suspendWhenScreenOffDueToProximity);
253         mShowWirelessChargingAnimationConfig = context.getResources().getBoolean(
254                 com.android.internal.R.bool.config_showBuiltinWirelessChargingAnim);
255 
256         mFullWakeLockLog = mInjector.getWakeLockLog(context);
257         mPartialWakeLockLog = mInjector.getWakeLockLog(context);
258 
259         // Initialize interactive state for battery stats.
260         try {
261             mBatteryStats.noteInteractive(true);
262         } catch (RemoteException ex) { }
263         FrameworkStatsLog.write(FrameworkStatsLog.INTERACTIVE_STATE_CHANGED,
264                 FrameworkStatsLog.INTERACTIVE_STATE_CHANGED__STATE__ON);
265 
266         if (mFlags.isMoveWscLoggingToNotifierEnabled()) {
267             mBatteryStatsInternal = mInjector.getBatteryStatsInternal();
268             mFrameworkStatsLogger = mInjector.getFrameworkStatsLogger();
269         } else {
270             mBatteryStatsInternal = null;
271             mFrameworkStatsLogger = null;
272         }
273     }
274 
275     /**
276      * Create the {@link BroadcastOptions} bundle that will be used with sending the
277      * {@link Intent#ACTION_SCREEN_ON} and {@link Intent#ACTION_SCREEN_OFF} broadcasts.
278      */
createScreenOnOffBroadcastOptions()279     private Bundle createScreenOnOffBroadcastOptions() {
280         final BroadcastOptions options = BroadcastOptions.makeBasic();
281         // This allows the broadcasting system to discard any older broadcasts
282         // waiting to be delivered to a process.
283         options.setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT);
284         // Set namespace and key to identify which older broadcasts can be discarded.
285         // We could use any strings here but namespace needs to be unlikely to be reused with in
286         // the system_server process, as that could result in potentially discarding some
287         // non-screen on/off related broadcast.
288         options.setDeliveryGroupMatchingKey(
289                 UUID.randomUUID().toString(),
290                 Intent.ACTION_SCREEN_ON);
291         // This allows the broadcast delivery to be delayed to apps in the Cached state.
292         options.setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE);
293         return options.toBundle();
294     }
295 
296     /**
297      * Called when a wake lock is acquired.
298      */
299     @SuppressLint("AndroidFrameworkRequiresPermission")
onWakeLockAcquired(int flags, String tag, String packageName, int ownerUid, int ownerPid, WorkSource workSource, String historyTag, IWakeLockCallback callback)300     public void onWakeLockAcquired(int flags, String tag, String packageName,
301             int ownerUid, int ownerPid, WorkSource workSource, String historyTag,
302             IWakeLockCallback callback) {
303         if (DEBUG) {
304             Slog.d(TAG, "onWakeLockAcquired: flags=" + flags + ", tag=\"" + tag
305                     + "\", packageName=" + packageName
306                     + ", ownerUid=" + ownerUid + ", ownerPid=" + ownerPid
307                     + ", workSource=" + workSource);
308         }
309         logWakelockStateChanged(flags, tag, ownerUid, workSource, WakelockEventType.ACQUIRE);
310         notifyWakeLockListener(callback, tag, true, ownerUid, ownerPid, flags, workSource,
311                 packageName, historyTag);
312         if (!mFlags.improveWakelockLatency()) {
313             final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
314             if (monitorType >= 0) {
315                 try {
316                     final boolean unimportantForLogging = ownerUid == Process.SYSTEM_UID
317                             && (flags & PowerManager.UNIMPORTANT_FOR_LOGGING) != 0;
318                     if (workSource != null) {
319                         mBatteryStats.noteStartWakelockFromSource(workSource, ownerPid, tag,
320                                 historyTag, monitorType, unimportantForLogging);
321                     } else {
322                         mBatteryStats.noteStartWakelock(ownerUid, ownerPid, tag, historyTag,
323                                 monitorType, unimportantForLogging);
324                         // XXX need to deal with disabled operations.
325                         mAppOps.startOpNoThrow(AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName,
326                                 false, null, null);
327                     }
328                 } catch (RemoteException ex) {
329                     // Ignore
330                 }
331             }
332             getWakeLockLog(flags).onWakeLockAcquired(tag,
333                     getUidForWakeLockLog(ownerUid, workSource), flags, /*eventTime=*/ -1);
334         }
335         mWakefulnessSessionObserver.onWakeLockAcquired(flags);
336     }
337 
onLongPartialWakeLockStart(String tag, int ownerUid, WorkSource workSource, String historyTag)338     public void onLongPartialWakeLockStart(String tag, int ownerUid, WorkSource workSource,
339             String historyTag) {
340         if (DEBUG) {
341             Slog.d(TAG, "onLongPartialWakeLockStart: ownerUid=" + ownerUid
342                     + ", workSource=" + workSource);
343         }
344 
345         try {
346             if (workSource != null) {
347                 mBatteryStats.noteLongPartialWakelockStartFromSource(tag, historyTag, workSource);
348                 FrameworkStatsLog.write(FrameworkStatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED,
349                         workSource, tag, historyTag,
350                         FrameworkStatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__ON);
351             } else {
352                 mBatteryStats.noteLongPartialWakelockStart(tag, historyTag, ownerUid);
353                 FrameworkStatsLog.write_non_chained(
354                         FrameworkStatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED, ownerUid, null, tag,
355                         historyTag,
356                         FrameworkStatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__ON);
357             }
358         } catch (RemoteException ex) {
359             // Ignore
360         }
361     }
362 
onLongPartialWakeLockFinish(String tag, int ownerUid, WorkSource workSource, String historyTag)363     public void onLongPartialWakeLockFinish(String tag, int ownerUid, WorkSource workSource,
364             String historyTag) {
365         if (DEBUG) {
366             Slog.d(TAG, "onLongPartialWakeLockFinish: ownerUid=" + ownerUid
367                     + ", workSource=" + workSource);
368         }
369 
370         try {
371             if (workSource != null) {
372                 mBatteryStats.noteLongPartialWakelockFinishFromSource(tag, historyTag, workSource);
373                 FrameworkStatsLog.write(FrameworkStatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED,
374                         workSource, tag, historyTag,
375                         FrameworkStatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__OFF);
376             } else {
377                 mBatteryStats.noteLongPartialWakelockFinish(tag, historyTag, ownerUid);
378                 FrameworkStatsLog.write_non_chained(
379                         FrameworkStatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED, ownerUid, null, tag,
380                         historyTag,
381                         FrameworkStatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED__STATE__OFF);
382             }
383         } catch (RemoteException ex) {
384             // Ignore
385         }
386     }
387 
388     /**
389      * Called when a wake lock is changing.
390      */
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)391     public void onWakeLockChanging(int flags, String tag, String packageName,
392             int ownerUid, int ownerPid, WorkSource workSource, String historyTag,
393             IWakeLockCallback callback, int newFlags, String newTag, String newPackageName,
394             int newOwnerUid, int newOwnerPid, WorkSource newWorkSource, String newHistoryTag,
395             IWakeLockCallback newCallback) {
396         // Todo(b/359154665): We do this because the newWorkSource can potentially be updated
397         // before the request is processed on the notifier thread. This would generally happen is
398         // the Worksource's set method is called, which as of this comment happens only in
399         // PowerManager#setWorksource and WifiManager#WifiLock#setWorksource. Both these places
400         // need to be updated and the WorkSource#set should be deprecated to avoid falling into
401         // such traps
402         newWorkSource = (newWorkSource == null) ? null : new WorkSource(newWorkSource);
403         final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
404         final int newMonitorType = getBatteryStatsWakeLockMonitorType(newFlags);
405         if (workSource != null && newWorkSource != null
406                 && monitorType >= 0 && newMonitorType >= 0) {
407             if (DEBUG) {
408                 Slog.d(TAG, "onWakeLockChanging: flags=" + newFlags + ", tag=\"" + newTag
409                         + "\", packageName=" + newPackageName
410                         + ", ownerUid=" + newOwnerUid + ", ownerPid=" + newOwnerPid
411                         + ", workSource=" + newWorkSource);
412             }
413 
414             logWakelockStateChanged(flags, tag, ownerUid, workSource, WakelockEventType.RELEASE);
415             logWakelockStateChanged(
416                     newFlags, newTag, newOwnerUid, newWorkSource, WakelockEventType.ACQUIRE);
417 
418             final boolean unimportantForLogging = newOwnerUid == Process.SYSTEM_UID
419                     && (newFlags & PowerManager.UNIMPORTANT_FOR_LOGGING) != 0;
420             try {
421                 notifyWakelockChanging(workSource, ownerPid, tag,
422                             historyTag, monitorType, newWorkSource, newOwnerPid, newTag,
423                             newHistoryTag, newMonitorType, unimportantForLogging);
424             } catch (RemoteException ex) {
425                 // Ignore
426             }
427         } else if (!PowerManagerService.isSameCallback(callback, newCallback)) {
428             onWakeLockReleased(flags, tag, packageName, ownerUid, ownerPid, workSource, historyTag,
429                     null /* Do not notify the old callback */);
430             onWakeLockAcquired(newFlags, newTag, newPackageName, newOwnerUid, newOwnerPid,
431                     newWorkSource, newHistoryTag, newCallback /* notify the new callback */);
432         } else {
433             onWakeLockReleased(flags, tag, packageName, ownerUid, ownerPid, workSource, historyTag,
434                     callback);
435             onWakeLockAcquired(newFlags, newTag, newPackageName, newOwnerUid, newOwnerPid,
436                     newWorkSource, newHistoryTag, newCallback);
437         }
438     }
439 
440     /**
441      * Called when a wake lock is released.
442      */
onWakeLockReleased(int flags, String tag, String packageName, int ownerUid, int ownerPid, WorkSource workSource, String historyTag, IWakeLockCallback callback)443     public void onWakeLockReleased(int flags, String tag, String packageName,
444             int ownerUid, int ownerPid, WorkSource workSource, String historyTag,
445             IWakeLockCallback callback) {
446         onWakeLockReleased(flags, tag, packageName, ownerUid, ownerPid, workSource, historyTag,
447                 callback, ScreenTimeoutOverridePolicy.RELEASE_REASON_UNKNOWN);
448     }
449 
450     /**
451      * Called when a wake lock is released.
452      */
453     @SuppressLint("AndroidFrameworkRequiresPermission")
onWakeLockReleased(int flags, String tag, String packageName, int ownerUid, int ownerPid, WorkSource workSource, String historyTag, IWakeLockCallback callback, int releaseReason)454     public void onWakeLockReleased(int flags, String tag, String packageName,
455             int ownerUid, int ownerPid, WorkSource workSource, String historyTag,
456             IWakeLockCallback callback, int releaseReason) {
457         if (DEBUG) {
458             Slog.d(TAG, "onWakeLockReleased: flags=" + flags + ", tag=\"" + tag
459                     + "\", packageName=" + packageName
460                     + ", ownerUid=" + ownerUid + ", ownerPid=" + ownerPid
461                     + ", workSource=" + workSource);
462         }
463         logWakelockStateChanged(flags, tag, ownerUid, workSource, WakelockEventType.RELEASE);
464         notifyWakeLockListener(callback, tag, false, ownerUid, ownerPid, flags, workSource,
465                 packageName, historyTag);
466         if (!mFlags.improveWakelockLatency()) {
467             final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
468             if (monitorType >= 0) {
469                 try {
470                     if (workSource != null) {
471                         mBatteryStats.noteStopWakelockFromSource(workSource, ownerPid, tag,
472                                 historyTag, monitorType);
473                     } else {
474                         mBatteryStats.noteStopWakelock(ownerUid, ownerPid, tag,
475                                 historyTag, monitorType);
476                         mAppOps.finishOp(AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName, null);
477                     }
478                 } catch (RemoteException ex) {
479                     // Ignore
480                 }
481             }
482             getWakeLockLog(flags).onWakeLockReleased(tag,
483                     getUidForWakeLockLog(ownerUid, workSource), /*eventTime=*/ -1);
484         }
485         mWakefulnessSessionObserver.onWakeLockReleased(flags, releaseReason);
486     }
487 
488     /** Shows the keyguard without requesting the device to immediately lock. */
showDismissibleKeyguard()489     public void showDismissibleKeyguard() {
490         mPolicy.showDismissibleKeyguard();
491     }
492 
getBatteryStatsWakeLockMonitorType(int flags)493     private int getBatteryStatsWakeLockMonitorType(int flags) {
494         switch (flags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
495             case PowerManager.PARTIAL_WAKE_LOCK:
496                 return BatteryStats.WAKE_TYPE_PARTIAL;
497 
498             case PowerManager.FULL_WAKE_LOCK:
499             case PowerManager.SCREEN_DIM_WAKE_LOCK:
500             case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
501                 return BatteryStats.WAKE_TYPE_FULL;
502 
503             case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
504                 if (mSuspendWhenScreenOffDueToProximityConfig) {
505                     return -1;
506                 }
507                 return BatteryStats.WAKE_TYPE_PARTIAL;
508 
509             case PowerManager.DRAW_WAKE_LOCK:
510                 return BatteryStats.WAKE_TYPE_DRAW;
511 
512             case PowerManager.DOZE_WAKE_LOCK:
513                 // Doze wake locks are an internal implementation detail of the
514                 // communication between dream manager service and power manager
515                 // service.  They have no additive battery impact.
516                 return -1;
517 
518             default:
519                 return -1;
520         }
521     }
522 
523     @VisibleForTesting
getWakelockMonitorTypeForLogging(int flags)524     int getWakelockMonitorTypeForLogging(int flags) {
525         switch (flags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
526             case PowerManager.FULL_WAKE_LOCK, PowerManager.SCREEN_DIM_WAKE_LOCK,
527                  PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
528                 return PowerManager.FULL_WAKE_LOCK;
529             case PowerManager.DRAW_WAKE_LOCK:
530                 return PowerManager.DRAW_WAKE_LOCK;
531             case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
532                 if (mSuspendWhenScreenOffDueToProximityConfig) {
533                     return -1;
534                 }
535                 return PowerManager.PARTIAL_WAKE_LOCK;
536             case PowerManager.PARTIAL_WAKE_LOCK:
537                 return PowerManager.PARTIAL_WAKE_LOCK;
538             case PowerManager.DOZE_WAKE_LOCK:
539                 // Doze wake locks are an internal implementation detail of the
540                 // communication between dream manager service and power manager
541                 // service.  They have no additive battery impact.
542                 return -1;
543             default:
544                 return -1;
545         }
546     }
547 
548     /**
549      * Notifies that the device is changing wakefulness.
550      * This function may be called even if the previous change hasn't finished in
551      * which case it will assume that the state did not fully converge before the
552      * next transition began and will recover accordingly.
553      */
onGlobalWakefulnessChangeStarted(final int wakefulness, int reason, long eventTime)554     public void onGlobalWakefulnessChangeStarted(final int wakefulness, int reason,
555             long eventTime) {
556         final boolean interactive = PowerManagerInternal.isInteractive(wakefulness);
557         if (DEBUG) {
558             Slog.d(TAG, "onWakefulnessChangeStarted: wakefulness=" + wakefulness
559                     + ", reason=" + reason + ", interactive=" + interactive);
560         }
561 
562         // Tell the activity manager about changes in wakefulness, not just interactivity.
563         // It needs more granularity than other components.
564         mHandler.post(new Runnable() {
565             @Override
566             public void run() {
567                 mActivityManagerInternal.onWakefulnessChanged(wakefulness);
568             }
569         });
570 
571         // Handle any early interactive state changes.
572         // Finish pending incomplete ones from a previous cycle.
573         if (mGlobalInteractivity.isInteractive != interactive) {
574             // Finish up late behaviors if needed.
575             if (mGlobalInteractivity.isChanging) {
576                 handleLateGlobalInteractiveChange();
577             }
578 
579             // Start input as soon as we start waking up or going to sleep.
580             mInputMethodManagerInternal.setInteractive(interactive);
581             if (!mFlags.isPerDisplayWakeByTouchEnabled()) {
582                 // Since wakefulness is a global property in original logic, all displays should
583                 // be set to the same interactive state, matching system's global wakefulness
584                 SparseBooleanArray displayInteractivities = new SparseBooleanArray();
585                 int[] displayIds = mDisplayManagerInternal.getDisplayIds().toArray();
586                 for (int displayId : displayIds) {
587                     displayInteractivities.put(displayId, interactive);
588                 }
589                 mInputManagerInternal.setDisplayInteractivities(displayInteractivities);
590             }
591 
592             // Notify battery stats.
593             try {
594                 mBatteryStats.noteInteractive(interactive);
595             } catch (RemoteException ex) { }
596             FrameworkStatsLog.write(FrameworkStatsLog.INTERACTIVE_STATE_CHANGED,
597                     interactive ? FrameworkStatsLog.INTERACTIVE_STATE_CHANGED__STATE__ON :
598                             FrameworkStatsLog.INTERACTIVE_STATE_CHANGED__STATE__OFF);
599 
600             // Handle early behaviors.
601             mGlobalInteractivity.isInteractive = interactive;
602             mGlobalInteractivity.isChanging = true;
603             mGlobalInteractivity.changeReason = reason;
604             mGlobalInteractivity.changeStartTime = eventTime;
605             handleEarlyGlobalInteractiveChange();
606         }
607     }
608 
609     /**
610      * Notifies that the device has finished changing wakefulness.
611      */
onWakefulnessChangeFinished()612     public void onWakefulnessChangeFinished() {
613         if (DEBUG) {
614             Slog.d(TAG, "onWakefulnessChangeFinished");
615         }
616         for (int i = 0; i < mInteractivityByGroupId.size(); i++) {
617             int groupId = mInteractivityByGroupId.keyAt(i);
618             Interactivity interactivity = mInteractivityByGroupId.valueAt(i);
619             if (interactivity.isChanging) {
620                 interactivity.isChanging = false;
621                 handleLateInteractiveChange(groupId);
622             }
623         }
624         if (mGlobalInteractivity.isChanging) {
625             mGlobalInteractivity.isChanging = false;
626             handleLateGlobalInteractiveChange();
627         }
628     }
629 
630 
handleEarlyInteractiveChange(int groupId)631     private void handleEarlyInteractiveChange(int groupId) {
632         synchronized (mLock) {
633             Interactivity interactivity = mInteractivityByGroupId.get(groupId);
634             if (interactivity == null) {
635                 Slog.e(TAG, "no Interactivity entry for groupId:" + groupId);
636                 return;
637             }
638             final int changeReason = interactivity.changeReason;
639             if (interactivity.isInteractive) {
640                 mHandler.post(() -> mPolicy.startedWakingUp(groupId, changeReason));
641             } else {
642                 mHandler.post(() -> mPolicy.startedGoingToSleep(groupId, changeReason));
643             }
644         }
645     }
646 
647     /**
648      * Handle early interactive state changes such as getting applications or the lock
649      * screen running and ready for the user to see (such as when turning on the screen).
650      */
handleEarlyGlobalInteractiveChange()651     private void handleEarlyGlobalInteractiveChange() {
652         synchronized (mLock) {
653             if (mGlobalInteractivity.isInteractive) {
654                 // Waking up...
655                 mHandler.post(() -> {
656                     mDisplayManagerInternal.onEarlyInteractivityChange(true /*isInteractive*/);
657                     mPolicy.startedWakingUpGlobal(mGlobalInteractivity.changeReason);
658                 });
659 
660                 // Send interactive broadcast.
661                 mPendingInteractiveState = INTERACTIVE_STATE_AWAKE;
662                 mPendingWakeUpBroadcast = true;
663                 updatePendingBroadcastLocked();
664             } else {
665                 // Going to sleep...
666                 mHandler.post(() -> {
667                     mDisplayManagerInternal.onEarlyInteractivityChange(false /*isInteractive*/);
668                     mPolicy.startedGoingToSleepGlobal(mGlobalInteractivity.changeReason);
669                 });
670             }
671         }
672     }
673 
674     /**
675      * Handle late global interactive state changes. Also see
676      * {@link #handleLateInteractiveChange(int)}.
677      */
handleLateGlobalInteractiveChange()678     private void handleLateGlobalInteractiveChange() {
679         synchronized (mLock) {
680             final int interactiveChangeLatency =
681                     (int) (SystemClock.uptimeMillis() - mGlobalInteractivity.changeStartTime);
682             if (mGlobalInteractivity.isInteractive) {
683                 // Finished waking up...
684                 mHandler.post(() -> {
685                     LogMaker log = new LogMaker(MetricsEvent.SCREEN);
686                     log.setType(MetricsEvent.TYPE_OPEN);
687                     log.setSubtype(WindowManagerPolicyConstants.translateWakeReasonToOnReason(
688                             mGlobalInteractivity.changeReason));
689                     log.setLatency(interactiveChangeLatency);
690                     log.addTaggedData(MetricsEvent.FIELD_SCREEN_WAKE_REASON,
691                             mGlobalInteractivity.changeReason);
692                     MetricsLogger.action(log);
693                     EventLogTags.writePowerScreenState(1, 0, 0, 0, interactiveChangeLatency);
694 
695                     mPolicy.finishedWakingUpGlobal(mGlobalInteractivity.changeReason);
696                 });
697             } else {
698                 // Finished going to sleep...
699                 // This is a good time to make transitions that we don't want the user to see,
700                 // such as bringing the key guard to focus.  There's no guarantee for this
701                 // however because the user could turn the device on again at any time.
702                 // Some things may need to be protected by other mechanisms that defer screen on.
703 
704                 // Cancel pending user activity.
705                 if (mUserActivityPending) {
706                     mUserActivityPending = false;
707                     mHandler.removeMessages(MSG_USER_ACTIVITY);
708                 }
709 
710                 // Tell the policy we finished going to sleep.
711                 final int offReason = WindowManagerPolicyConstants.translateSleepReasonToOffReason(
712                         mGlobalInteractivity.changeReason);
713                 mHandler.post(() -> {
714                     LogMaker log = new LogMaker(MetricsEvent.SCREEN);
715                     log.setType(MetricsEvent.TYPE_CLOSE);
716                     log.setSubtype(offReason);
717                     log.setLatency(interactiveChangeLatency);
718                     log.addTaggedData(MetricsEvent.FIELD_SCREEN_SLEEP_REASON,
719                             mGlobalInteractivity.changeReason);
720                     MetricsLogger.action(log);
721                     EventLogTags.writePowerScreenState(
722                             0, offReason, 0, 0, interactiveChangeLatency);
723 
724                     mPolicy.finishedGoingToSleepGlobal(mGlobalInteractivity.changeReason);
725                 });
726 
727                 // Send non-interactive broadcast.
728                 mPendingInteractiveState = INTERACTIVE_STATE_ASLEEP;
729                 mPendingGoToSleepBroadcast = true;
730                 updatePendingBroadcastLocked();
731             }
732         }
733     }
734 
735     /**
736      * Handle late interactive state changes once they are finished so that the system can
737      * finish pending transitions (such as turning the screen off) before causing
738      * applications to change state visibly.
739      */
handleLateInteractiveChange(int groupId)740     private void handleLateInteractiveChange(int groupId) {
741         synchronized (mLock) {
742             Interactivity interactivity = mInteractivityByGroupId.get(groupId);
743             if (interactivity == null) {
744                 Slog.e(TAG, "no Interactivity entry for groupId:" + groupId);
745                 return;
746             }
747             final int changeReason = interactivity.changeReason;
748             if (interactivity.isInteractive) {
749                 mHandler.post(() -> mPolicy.finishedWakingUp(groupId, changeReason));
750             } else {
751                 mHandler.post(() -> mPolicy.finishedGoingToSleep(groupId, changeReason));
752             }
753         }
754     }
755 
756     /**
757      * Update the interactivities of the displays in given DisplayGroup.
758      *
759      * @param groupId The group id of the DisplayGroup to update display interactivities for.
760      */
updateDisplayInteractivities(int groupId, boolean interactive)761     private void updateDisplayInteractivities(int groupId, boolean interactive) {
762         final int[] displayIds = mDisplayManagerInternal.getDisplayIdsForGroup(groupId);
763         for (int displayId : displayIds) {
764             mDisplayInteractivities.put(displayId, interactive);
765         }
766 
767     }
768 
resetDisplayInteractivities()769     private void resetDisplayInteractivities() {
770         final SparseArray<int[]> displaysByGroupId =
771                 mDisplayManagerInternal.getDisplayIdsByGroupsIds();
772         SparseBooleanArray newDisplayInteractivities = new SparseBooleanArray();
773         for (int i = 0; i < displaysByGroupId.size(); i++) {
774             final int groupId = displaysByGroupId.keyAt(i);
775             for (int displayId : displaysByGroupId.get(groupId)) {
776                 // If we already know display interactivity, use that
777                 if (mDisplayInteractivities.indexOfKey(displayId) > 0) {
778                     newDisplayInteractivities.put(
779                             displayId, mDisplayInteractivities.get(displayId));
780                 } else { // If display is new to Notifier, use the power group's interactive value
781                     final Interactivity groupInteractivity = mInteractivityByGroupId.get(groupId);
782                     // If group Interactivity hasn't been initialized, assume group is interactive
783                     final boolean groupInteractive =
784                             groupInteractivity == null || groupInteractivity.isInteractive;
785                     newDisplayInteractivities.put(displayId, groupInteractive);
786                 }
787             }
788         }
789         mDisplayInteractivities = newDisplayInteractivities;
790     }
791 
792     /**
793      * Called when an individual PowerGroup changes wakefulness.
794      */
onGroupWakefulnessChangeStarted(int groupId, int wakefulness, int changeReason, long eventTime)795     public void onGroupWakefulnessChangeStarted(int groupId, int wakefulness, int changeReason,
796             long eventTime) {
797         final boolean isInteractive = PowerManagerInternal.isInteractive(wakefulness);
798 
799         boolean isNewGroup = false;
800         Interactivity interactivity = mInteractivityByGroupId.get(groupId);
801         if (interactivity == null) {
802             isNewGroup = true;
803             interactivity = new Interactivity();
804             mInteractivityByGroupId.put(groupId, interactivity);
805         }
806         if (isNewGroup || interactivity.isInteractive != isInteractive) {
807             // Finish up late behaviors if needed.
808             if (interactivity.isChanging) {
809                 handleLateInteractiveChange(groupId);
810             }
811 
812             // Handle early behaviors.
813             interactivity.isInteractive = isInteractive;
814             interactivity.changeReason = changeReason;
815             interactivity.changeStartTime = eventTime;
816             interactivity.isChanging = true;
817             handleEarlyInteractiveChange(groupId);
818             mWakefulnessSessionObserver.onWakefulnessChangeStarted(groupId, wakefulness,
819                     changeReason, eventTime);
820 
821             // Update input on which displays are interactive
822             if (mFlags.isPerDisplayWakeByTouchEnabled()) {
823                 updateDisplayInteractivities(groupId, isInteractive);
824                 mInputManagerInternal.setDisplayInteractivities(mDisplayInteractivities);
825             }
826         }
827     }
828 
829     /**
830      * Called when a PowerGroup has been removed.
831      *
832      * @param groupId which group was removed
833      */
onGroupRemoved(int groupId)834     public void onGroupRemoved(int groupId) {
835         mInteractivityByGroupId.remove(groupId);
836         mWakefulnessSessionObserver.removePowerGroup(groupId);
837         if (mFlags.isPerDisplayWakeByTouchEnabled()) {
838             resetDisplayInteractivities();
839             mInputManagerInternal.setDisplayInteractivities(mDisplayInteractivities);
840         }
841     }
842 
843     /**
844      * Called when a PowerGroup has been changed.
845      */
onGroupChanged()846     public void onGroupChanged() {
847         if (mFlags.isPerDisplayWakeByTouchEnabled()) {
848             resetDisplayInteractivities();
849             mInputManagerInternal.setDisplayInteractivities(mDisplayInteractivities);
850         }
851     }
852 
853     /**
854      * Called when there has been user activity.
855      */
onUserActivity(int displayGroupId, @PowerManager.UserActivityEvent int event, int uid)856     public void onUserActivity(int displayGroupId, @PowerManager.UserActivityEvent int event,
857             int uid) {
858         if (DEBUG) {
859             Slog.d(TAG, "onUserActivity: event=" + event + ", uid=" + uid);
860         }
861 
862         try {
863             mBatteryStats.noteUserActivity(uid, event);
864             mWakefulnessSessionObserver.notifyUserActivity(
865                     SystemClock.uptimeMillis(), displayGroupId, event);
866         } catch (RemoteException ex) {
867             // Ignore
868         }
869 
870         synchronized (mLock) {
871             if (!mUserActivityPending) {
872                 mUserActivityPending = true;
873                 Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY);
874                 msg.arg1 = displayGroupId;
875                 msg.arg2 = event;
876                 msg.setAsynchronous(true);
877                 mHandler.sendMessage(msg);
878             }
879         }
880     }
881 
882     /**
883      * Called when the screen has turned on.
884      */
onWakeUp(int reason, String details, int reasonUid, String opPackageName, int opUid)885     public void onWakeUp(int reason, String details, int reasonUid, String opPackageName,
886             int opUid) {
887         if (DEBUG) {
888             Slog.d(TAG, "onWakeUp: reason=" + PowerManager.wakeReasonToString(reason)
889                     + ", details=" + details + ", reasonUid=" + reasonUid
890                     + " opPackageName=" + opPackageName + " opUid=" + opUid);
891         }
892 
893         try {
894             mBatteryStats.noteWakeUp(details, reasonUid);
895             if (opPackageName != null) {
896                 mAppOps.noteOpNoThrow(AppOpsManager.OP_TURN_SCREEN_ON, opUid, opPackageName);
897             }
898         } catch (RemoteException ex) {
899             // Ignore
900         }
901         FrameworkStatsLog.write(FrameworkStatsLog.DISPLAY_WAKE_REPORTED, reason, reasonUid);
902     }
903 
904     /**
905      * Called when profile screen lock timeout has expired.
906      */
onProfileTimeout(@serIdInt int userId)907     public void onProfileTimeout(@UserIdInt int userId) {
908         final Message msg = mHandler.obtainMessage(MSG_PROFILE_TIMED_OUT);
909         msg.setAsynchronous(true);
910         msg.arg1 = userId;
911         mHandler.sendMessage(msg);
912     }
913 
914     /**
915      * Called when wireless charging has started - to provide user feedback (sound and visual).
916      */
onWirelessChargingStarted(int batteryLevel, @UserIdInt int userId)917     public void onWirelessChargingStarted(int batteryLevel, @UserIdInt int userId) {
918         if (DEBUG) {
919             Slog.d(TAG, "onWirelessChargingStarted");
920         }
921 
922         mSuspendBlocker.acquire();
923         Message msg = mHandler.obtainMessage(MSG_WIRELESS_CHARGING_STARTED);
924         msg.setAsynchronous(true);
925         msg.arg1 = batteryLevel;
926         msg.arg2 = userId;
927         mHandler.sendMessage(msg);
928     }
929 
930     /**
931      * Called when wired charging has started - to provide user feedback
932      */
onWiredChargingStarted(@serIdInt int userId)933     public void onWiredChargingStarted(@UserIdInt int userId) {
934         if (DEBUG) {
935             Slog.d(TAG, "onWiredChargingStarted");
936         }
937 
938         mSuspendBlocker.acquire();
939         Message msg = mHandler.obtainMessage(MSG_WIRED_CHARGING_STARTED);
940         msg.setAsynchronous(true);
941         msg.arg1 = userId;
942         mHandler.sendMessage(msg);
943     }
944 
945     /**
946      * Called when the screen policy changes.
947      */
onScreenPolicyUpdate(int displayGroupId, int newPolicy)948     public void onScreenPolicyUpdate(int displayGroupId, int newPolicy) {
949         if (DEBUG) {
950             Slog.d(TAG, "onScreenPolicyUpdate: newPolicy=" + newPolicy);
951         }
952         mWakefulnessSessionObserver.onScreenPolicyUpdate(
953                 SystemClock.uptimeMillis(), displayGroupId, newPolicy);
954 
955         synchronized (mLock) {
956             Message msg = mHandler.obtainMessage(MSG_SCREEN_POLICY);
957             msg.arg1 = displayGroupId;
958             msg.arg2 = newPolicy;
959             msg.setAsynchronous(true);
960             mHandler.sendMessage(msg);
961         }
962     }
963 
964     /**
965      * Dumps data for bugreports.
966      *
967      * @param pw The stream to print to.
968      */
dump(PrintWriter pw)969     public void dump(PrintWriter pw) {
970         pw.println("Notifier:");
971 
972         IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
973         ipw.println("Partial Wakelock Log:");
974         mPartialWakeLockLog.dump(ipw);
975 
976         ipw.println("");
977         ipw.println("Full Wakelock Log:");
978         mFullWakeLockLog.dump(ipw);
979 
980         ipw.println("");
981         mWakefulnessSessionObserver.dump(ipw);
982     }
983 
updatePendingBroadcastLocked()984     private void updatePendingBroadcastLocked() {
985         if (!mBroadcastInProgress
986                 && mPendingInteractiveState != INTERACTIVE_STATE_UNKNOWN
987                 && (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
988                         || mPendingInteractiveState != mBroadcastedInteractiveState)) {
989             mBroadcastInProgress = true;
990             mSuspendBlocker.acquire();
991             Message msg = mHandler.obtainMessage(MSG_BROADCAST);
992             msg.setAsynchronous(true);
993             mHandler.sendMessage(msg);
994         }
995     }
996 
finishPendingBroadcastLocked()997     private void finishPendingBroadcastLocked() {
998         mBroadcastInProgress = false;
999         mSuspendBlocker.release();
1000     }
1001 
sendUserActivity(int displayGroupId, int event)1002     private void sendUserActivity(int displayGroupId, int event) {
1003         synchronized (mLock) {
1004             if (!mUserActivityPending) {
1005                 return;
1006             }
1007             mUserActivityPending = false;
1008         }
1009         TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
1010         tm.notifyUserActivity();
1011         mInputManagerInternal.notifyUserActivity();
1012         mPolicy.userActivity(displayGroupId, event);
1013         mFaceDownDetector.userActivity(event);
1014         mScreenUndimDetector.userActivity(displayGroupId);
1015     }
1016 
postEnhancedDischargePredictionBroadcast(long delayMs)1017     void postEnhancedDischargePredictionBroadcast(long delayMs) {
1018         mHandler.sendEmptyMessageDelayed(MSG_BROADCAST_ENHANCED_PREDICTION, delayMs);
1019     }
1020 
sendEnhancedDischargePredictionBroadcast()1021     private void sendEnhancedDischargePredictionBroadcast() {
1022         Intent intent = new Intent(PowerManager.ACTION_ENHANCED_DISCHARGE_PREDICTION_CHANGED)
1023                 .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1024         mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
1025     }
1026 
sendNextBroadcast()1027     private void sendNextBroadcast() {
1028         final int powerState;
1029         synchronized (mLock) {
1030             if (mBroadcastedInteractiveState == INTERACTIVE_STATE_UNKNOWN) {
1031                 // Broadcasted power state is unknown.
1032                 // Send wake up or go to sleep.
1033                 switch (mPendingInteractiveState) {
1034                     case INTERACTIVE_STATE_ASLEEP:
1035                         mPendingGoToSleepBroadcast = false;
1036                         mBroadcastedInteractiveState = INTERACTIVE_STATE_ASLEEP;
1037                         break;
1038 
1039                     case INTERACTIVE_STATE_AWAKE:
1040                     default:
1041                         mPendingWakeUpBroadcast = false;
1042                         mBroadcastedInteractiveState = INTERACTIVE_STATE_AWAKE;
1043                         break;
1044                 }
1045             } else if (mBroadcastedInteractiveState == INTERACTIVE_STATE_AWAKE) {
1046                 // Broadcasted power state is awake.  Send asleep if needed.
1047                 if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
1048                         || mPendingInteractiveState == INTERACTIVE_STATE_ASLEEP) {
1049                     mPendingGoToSleepBroadcast = false;
1050                     mBroadcastedInteractiveState = INTERACTIVE_STATE_ASLEEP;
1051                 } else {
1052                     finishPendingBroadcastLocked();
1053                     return;
1054                 }
1055             } else {
1056                 // Broadcasted power state is asleep.  Send awake if needed.
1057                 if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
1058                         || mPendingInteractiveState == INTERACTIVE_STATE_AWAKE) {
1059                     mPendingWakeUpBroadcast = false;
1060                     mBroadcastedInteractiveState = INTERACTIVE_STATE_AWAKE;
1061                 } else {
1062                     finishPendingBroadcastLocked();
1063                     return;
1064                 }
1065             }
1066 
1067             mBroadcastStartTime = SystemClock.uptimeMillis();
1068             powerState = mBroadcastedInteractiveState;
1069         }
1070 
1071         EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_SEND, 1);
1072 
1073         if (powerState == INTERACTIVE_STATE_AWAKE) {
1074             sendWakeUpBroadcast();
1075         } else {
1076             sendGoToSleepBroadcast();
1077         }
1078     }
1079 
sendWakeUpBroadcast()1080     private void sendWakeUpBroadcast() {
1081         if (DEBUG) {
1082             Slog.d(TAG, "Sending wake up broadcast.");
1083         }
1084 
1085         if (mActivityManagerInternal.isSystemReady()) {
1086             mActivityManagerInternal.broadcastIntentWithCallback(mScreenOnIntent,
1087                     mWakeUpBroadcastDone, null, UserHandle.USER_ALL,
1088                     null, null, mScreenOnOffOptions);
1089         } else {
1090             EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 2, 1);
1091             sendNextBroadcast();
1092         }
1093     }
1094 
1095     private final IIntentReceiver mWakeUpBroadcastDone = new IIntentReceiver.Stub() {
1096         @Override
1097         public void performReceive(Intent intent, int resultCode, String data, Bundle extras,
1098                 boolean ordered, boolean sticky, int sendingUser) {
1099             EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 1,
1100                     SystemClock.uptimeMillis() - mBroadcastStartTime, 1);
1101             sendNextBroadcast();
1102         }
1103     };
1104 
sendGoToSleepBroadcast()1105     private void sendGoToSleepBroadcast() {
1106         if (DEBUG) {
1107             Slog.d(TAG, "Sending go to sleep broadcast.");
1108         }
1109 
1110         if (mActivityManagerInternal.isSystemReady()) {
1111             mActivityManagerInternal.broadcastIntentWithCallback(mScreenOffIntent,
1112                     mGoToSleepBroadcastDone, null, UserHandle.USER_ALL,
1113                     null, null, mScreenOnOffOptions);
1114         } else {
1115             EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 3, 1);
1116             sendNextBroadcast();
1117         }
1118     }
1119 
1120     private final IIntentReceiver mGoToSleepBroadcastDone = new IIntentReceiver.Stub() {
1121         @Override
1122         public void performReceive(Intent intent, int resultCode, String data, Bundle extras,
1123                 boolean ordered, boolean sticky, int sendingUser) {
1124             EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 0,
1125                     SystemClock.uptimeMillis() - mBroadcastStartTime, 1);
1126             sendNextBroadcast();
1127         }
1128     };
1129 
playChargingStartedFeedback(@serIdInt int userId, boolean wireless)1130     private void playChargingStartedFeedback(@UserIdInt int userId, boolean wireless) {
1131         if (!isChargingFeedbackEnabled(userId)) {
1132             return;
1133         }
1134 
1135         if (!mIsPlayingChargingStartedFeedback.compareAndSet(false, true)) {
1136             // there's already a charging started feedback Runnable scheduled to run on the
1137             // background thread, so let's not execute another
1138             return;
1139         }
1140 
1141         // vibrate & play sound on a background thread
1142         mBackgroundExecutor.execute(() -> {
1143             // vibrate
1144             final boolean vibrate = Settings.Secure.getIntForUser(mContext.getContentResolver(),
1145                     Settings.Secure.CHARGING_VIBRATION_ENABLED, 1, userId) != 0;
1146             if (vibrate) {
1147                 mVibrator.vibrate(Process.SYSTEM_UID, mContext.getOpPackageName(),
1148                         CHARGING_VIBRATION_EFFECT, /* reason= */ "Charging started",
1149                         HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES);
1150             }
1151 
1152             // play sound
1153             final String soundPath = Settings.Global.getString(mContext.getContentResolver(),
1154                     wireless ? Settings.Global.WIRELESS_CHARGING_STARTED_SOUND
1155                             : Settings.Global.CHARGING_STARTED_SOUND);
1156             final Uri soundUri = Uri.parse("file://" + soundPath);
1157             if (soundUri != null) {
1158                 final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
1159                 if (sfx != null) {
1160                     sfx.setStreamType(AudioManager.STREAM_SYSTEM);
1161                     sfx.play();
1162                 }
1163             }
1164             mIsPlayingChargingStartedFeedback.set(false);
1165         });
1166     }
1167 
showWirelessChargingStarted(int batteryLevel, @UserIdInt int userId)1168     private void showWirelessChargingStarted(int batteryLevel, @UserIdInt int userId) {
1169         // play sounds + haptics
1170         playChargingStartedFeedback(userId, true /* wireless */);
1171 
1172         // show animation
1173         if (mShowWirelessChargingAnimationConfig && mStatusBarManagerInternal != null) {
1174             mStatusBarManagerInternal.showChargingAnimation(batteryLevel);
1175         }
1176         mSuspendBlocker.release();
1177     }
1178 
showWiredChargingStarted(@serIdInt int userId)1179     private void showWiredChargingStarted(@UserIdInt int userId) {
1180         playChargingStartedFeedback(userId, false /* wireless */);
1181         mSuspendBlocker.release();
1182     }
1183 
screenPolicyChanging(int displayGroupId, int screenPolicy)1184     private void screenPolicyChanging(int displayGroupId, int screenPolicy) {
1185         mScreenUndimDetector.recordScreenPolicy(displayGroupId, screenPolicy);
1186     }
1187 
lockProfile(@serIdInt int userId)1188     private void lockProfile(@UserIdInt int userId) {
1189         mTrustManager.setDeviceLockedForUser(userId, true /*locked*/);
1190     }
1191 
isChargingFeedbackEnabled(@serIdInt int userId)1192     private boolean isChargingFeedbackEnabled(@UserIdInt int userId) {
1193         final boolean enabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
1194                 Settings.Secure.CHARGING_SOUNDS_ENABLED, 1, userId) != 0;
1195         final boolean dndOff = Settings.Global.getInt(mContext.getContentResolver(),
1196                 Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS)
1197                 == Settings.Global.ZEN_MODE_OFF;
1198         return enabled && dndOff;
1199     }
1200 
notifyWakeLockListener(IWakeLockCallback callback, String tag, boolean isEnabled, int ownerUid, int ownerPid, int flags, WorkSource workSource, String packageName, String historyTag)1201     private void notifyWakeLockListener(IWakeLockCallback callback, String tag, boolean isEnabled,
1202             int ownerUid, int ownerPid, int flags, WorkSource workSource, String packageName,
1203             String historyTag) {
1204         long currentTime = mInjector.currentTimeMillis();
1205         mHandler.post(() -> {
1206             if (mFlags.improveWakelockLatency()) {
1207                 if (isEnabled) {
1208                     notifyWakelockAcquisition(tag, ownerUid, ownerPid, flags,
1209                             workSource, packageName, historyTag, currentTime);
1210                 } else {
1211                     notifyWakelockRelease(tag, ownerUid, ownerPid, flags,
1212                             workSource, packageName, historyTag, currentTime);
1213                 }
1214             }
1215 
1216             if (callback != null) {
1217                 try {
1218                     callback.onStateChanged(isEnabled);
1219                 } catch (RemoteException e) {
1220                     Slog.e(TAG, "Wakelock.mCallback [" + tag + "] is already dead.", e);
1221                 }
1222             }
1223         });
1224     }
1225 
1226     @SuppressLint("AndroidFrameworkRequiresPermission")
notifyWakelockAcquisition(String tag, int ownerUid, int ownerPid, int flags, WorkSource workSource, String packageName, String historyTag, long currentTime)1227     private void notifyWakelockAcquisition(String tag, int ownerUid, int ownerPid, int flags,
1228             WorkSource workSource, String packageName, String historyTag, long currentTime) {
1229         final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
1230         if (monitorType >= 0) {
1231             try {
1232                 final boolean unimportantForLogging = ownerUid == Process.SYSTEM_UID
1233                         && (flags & PowerManager.UNIMPORTANT_FOR_LOGGING) != 0;
1234                 if (workSource != null) {
1235                     mBatteryStats.noteStartWakelockFromSource(workSource, ownerPid, tag,
1236                             historyTag, monitorType, unimportantForLogging);
1237                 } else {
1238                     mBatteryStats.noteStartWakelock(ownerUid, ownerPid, tag, historyTag,
1239                             monitorType, unimportantForLogging);
1240                     // XXX need to deal with disabled operations.
1241                     mAppOps.startOpNoThrow(
1242                             AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName,
1243                             false, null, null);
1244                 }
1245             } catch (RemoteException ex) {
1246                 // Do Nothing
1247             }
1248         }
1249 
1250         getWakeLockLog(flags).onWakeLockAcquired(tag, getUidForWakeLockLog(ownerUid, workSource),
1251                 flags, currentTime);
1252     }
1253 
1254     @SuppressLint("AndroidFrameworkRequiresPermission")
notifyWakelockRelease(String tag, int ownerUid, int ownerPid, int flags, WorkSource workSource, String packageName, String historyTag, long currentTime)1255     private void notifyWakelockRelease(String tag, int ownerUid, int ownerPid, int flags,
1256             WorkSource workSource, String packageName, String historyTag, long currentTime) {
1257         final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
1258         if (monitorType >= 0) {
1259             try {
1260                 if (workSource != null) {
1261                     mBatteryStats.noteStopWakelockFromSource(workSource, ownerPid, tag,
1262                             historyTag, monitorType);
1263                 } else {
1264                     mBatteryStats.noteStopWakelock(ownerUid, ownerPid, tag,
1265                             historyTag, monitorType);
1266                     mAppOps.finishOp(AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName, null);
1267                 }
1268             } catch (RemoteException ex) {
1269                 // Ignore
1270             }
1271         }
1272         getWakeLockLog(flags).onWakeLockReleased(tag, getUidForWakeLockLog(ownerUid, workSource),
1273                 currentTime);
1274     }
1275 
1276     @SuppressLint("AndroidFrameworkRequiresPermission")
notifyWakelockChanging(WorkSource workSource, int ownerPid, String tag, String historyTag, int monitorType, WorkSource newWorkSource, int newOwnerPid, String newTag, String newHistoryTag, int newMonitorType, boolean unimportantForLogging)1277     private void notifyWakelockChanging(WorkSource workSource, int ownerPid, String tag,
1278             String historyTag, int monitorType, WorkSource newWorkSource, int newOwnerPid,
1279             String newTag, String newHistoryTag, int newMonitorType, boolean unimportantForLogging)
1280             throws RemoteException {
1281         if (!mFlags.improveWakelockLatency()) {
1282             mBatteryStats.noteChangeWakelockFromSource(workSource, ownerPid, tag,
1283                     historyTag, monitorType, newWorkSource, newOwnerPid, newTag,
1284                     newHistoryTag, newMonitorType, unimportantForLogging);
1285         } else {
1286             mHandler.post(() -> {
1287                 try {
1288                     mBatteryStats.noteChangeWakelockFromSource(workSource, ownerPid, tag,
1289                             historyTag, monitorType, newWorkSource, newOwnerPid, newTag,
1290                             newHistoryTag, newMonitorType, unimportantForLogging);
1291                 } catch (RemoteException e) {
1292                     Slog.e(TAG, "Failed to notify the wakelock changing from source via "
1293                             + "Notifier." + e.getLocalizedMessage());
1294                 }
1295             });
1296         }
1297     }
1298 
1299     /**
1300      * Adds a listener for the screen timeout policy
1301      * @param displayId display ID
1302      * @param screenTimeoutPolicy initial state of the timeout policy
1303      * @param listener callback to receive screen timeout policy updates
1304      */
addScreenTimeoutPolicyListener(int displayId, @ScreenTimeoutPolicy int screenTimeoutPolicy, IScreenTimeoutPolicyListener listener)1305     void addScreenTimeoutPolicyListener(int displayId, @ScreenTimeoutPolicy int screenTimeoutPolicy,
1306             IScreenTimeoutPolicyListener listener) {
1307         synchronized (mLock) {
1308             ScreenTimeoutPolicyListenersContainer listenersContainer =
1309                     mScreenTimeoutPolicyListeners.get(displayId);
1310             if (listenersContainer == null) {
1311                 listenersContainer = new ScreenTimeoutPolicyListenersContainer(
1312                         screenTimeoutPolicy);
1313                 mScreenTimeoutPolicyListeners.set(displayId, listenersContainer);
1314             }
1315 
1316             listenersContainer.addListener(listener);
1317         }
1318     }
1319 
1320     /**
1321      * Removes a listener for the screen timeout policy
1322      * @param displayId display id from which the listener should be removed
1323      * @param listener the instance of the listener
1324      */
removeScreenTimeoutPolicyListener(int displayId, IScreenTimeoutPolicyListener listener)1325     void removeScreenTimeoutPolicyListener(int displayId,
1326             IScreenTimeoutPolicyListener listener) {
1327         synchronized (mLock) {
1328             ScreenTimeoutPolicyListenersContainer listenersContainer =
1329                     mScreenTimeoutPolicyListeners.get(displayId);
1330             if (listenersContainer == null) {
1331                 return;
1332             }
1333 
1334             listenersContainer.removeListener(listener);
1335 
1336             if (listenersContainer.isEmpty()) {
1337                 mScreenTimeoutPolicyListeners.remove(displayId);
1338             }
1339         }
1340     }
1341 
1342     /**
1343      * Clears all screen timeout policy listeners for the specified display id
1344      * @param displayId display id from which the listeners should be cleared
1345      */
clearScreenTimeoutPolicyListeners(int displayId)1346     void clearScreenTimeoutPolicyListeners(int displayId) {
1347         synchronized (mLock) {
1348             mScreenTimeoutPolicyListeners.remove(displayId);
1349         }
1350     }
1351 
1352     /**
1353      * Notifies about screen timeout policy changes of the corresponding display group if
1354      * it has changed
1355      * @param displayGroupId the id of the display group to report
1356      * @param screenTimeoutPolicy screen timeout policy
1357      */
notifyScreenTimeoutPolicyChanges(int displayGroupId, @ScreenTimeoutPolicy int screenTimeoutPolicy)1358     void notifyScreenTimeoutPolicyChanges(int displayGroupId,
1359             @ScreenTimeoutPolicy int screenTimeoutPolicy) {
1360         synchronized (mLock) {
1361             for (int idx = 0; idx < mScreenTimeoutPolicyListeners.size(); idx++) {
1362                 final int displayId = mScreenTimeoutPolicyListeners.keyAt(idx);
1363                 if (mDisplayManagerInternal.getGroupIdForDisplay(displayId) == displayGroupId) {
1364                     final ScreenTimeoutPolicyListenersContainer container =
1365                             mScreenTimeoutPolicyListeners.valueAt(idx);
1366                     container.updateScreenTimeoutPolicyAndNotifyIfNeeded(screenTimeoutPolicy);
1367                 }
1368             }
1369         }
1370     }
1371 
1372     private final class ScreenTimeoutPolicyListenersContainer {
1373         private final RemoteCallbackList<IScreenTimeoutPolicyListener> mListeners;
1374         private final ArrayMap<IScreenTimeoutPolicyListener, Integer> mLastReportedState =
1375                 new ArrayMap<>();
1376 
1377         @ScreenTimeoutPolicy
1378         private volatile int mScreenTimeoutPolicy;
1379 
ScreenTimeoutPolicyListenersContainer(int screenTimeoutPolicy)1380         ScreenTimeoutPolicyListenersContainer(int screenTimeoutPolicy) {
1381             mScreenTimeoutPolicy = screenTimeoutPolicy;
1382             mListeners = new RemoteCallbackList<IScreenTimeoutPolicyListener>() {
1383                 @Override
1384                 public void onCallbackDied(IScreenTimeoutPolicyListener callbackInterface) {
1385                     mLastReportedState.remove(callbackInterface);
1386                 }
1387             };
1388         }
1389 
updateScreenTimeoutPolicyAndNotifyIfNeeded( @creenTimeoutPolicy int screenTimeoutPolicy)1390         void updateScreenTimeoutPolicyAndNotifyIfNeeded(
1391                 @ScreenTimeoutPolicy int screenTimeoutPolicy) {
1392             mScreenTimeoutPolicy = screenTimeoutPolicy;
1393 
1394             mHandler.post(() -> {
1395                 for (int i = mListeners.beginBroadcast() - 1; i >= 0; i--) {
1396                     final IScreenTimeoutPolicyListener listener = mListeners.getBroadcastItem(i);
1397                     notifyListenerIfNeeded(listener);
1398                 }
1399                 mListeners.finishBroadcast();
1400             });
1401         }
1402 
addListener(IScreenTimeoutPolicyListener listener)1403         void addListener(IScreenTimeoutPolicyListener listener) {
1404             mListeners.register(listener);
1405             mHandler.post(() -> notifyListenerIfNeeded(listener));
1406         }
1407 
removeListener(IScreenTimeoutPolicyListener listener)1408         void removeListener(IScreenTimeoutPolicyListener listener) {
1409             mListeners.unregister(listener);
1410             mLastReportedState.remove(listener);
1411         }
1412 
isEmpty()1413         boolean isEmpty() {
1414             return mListeners.getRegisteredCallbackCount() == 0;
1415         }
1416 
notifyListenerIfNeeded(IScreenTimeoutPolicyListener listener)1417         private void notifyListenerIfNeeded(IScreenTimeoutPolicyListener listener) {
1418             final int currentScreenTimeoutPolicy = mScreenTimeoutPolicy;
1419             final Integer reportedScreenTimeoutPolicy = mLastReportedState.get(listener);
1420             final boolean needsReporting = reportedScreenTimeoutPolicy == null
1421                     || !reportedScreenTimeoutPolicy.equals(currentScreenTimeoutPolicy);
1422 
1423             if (!needsReporting) return;
1424 
1425             try {
1426                 listener.onScreenTimeoutPolicyChanged(currentScreenTimeoutPolicy);
1427                 mLastReportedState.put(listener, currentScreenTimeoutPolicy);
1428             } catch (RemoteException e) {
1429                 // The RemoteCallbackList will take care of removing
1430                 // the dead object for us.
1431                 Slog.e(TAG, "Remote exception when notifying screen timeout policy change", e);
1432             } catch (Throwable e) {
1433                 Slog.e(TAG, "Exception when notifying screen timeout policy change", e);
1434                 removeListener(listener);
1435             }
1436         }
1437     }
1438 
getWakeLockLog(int flags)1439     private @NonNull WakeLockLog getWakeLockLog(int flags) {
1440         return PowerManagerService.isScreenLock(flags) ? mFullWakeLockLog : mPartialWakeLockLog;
1441     }
1442 
getUidForWakeLockLog(int ownerUid, WorkSource workSource)1443     private int getUidForWakeLockLog(int ownerUid, WorkSource workSource) {
1444         int attributionUid = workSource != null ? workSource.getAttributionUid() : -1;
1445         return attributionUid != -1 ? attributionUid : ownerUid;
1446     }
1447 
1448     private final class NotifierHandler extends Handler {
1449 
NotifierHandler(Looper looper)1450         public NotifierHandler(Looper looper) {
1451             super(looper, null, true /*async*/);
1452         }
1453 
1454         @Override
handleMessage(Message msg)1455         public void handleMessage(Message msg) {
1456             switch (msg.what) {
1457                 case MSG_USER_ACTIVITY:
1458                     sendUserActivity(msg.arg1, msg.arg2);
1459                     break;
1460                 case MSG_BROADCAST:
1461                     sendNextBroadcast();
1462                     break;
1463                 case MSG_WIRELESS_CHARGING_STARTED:
1464                     showWirelessChargingStarted(msg.arg1, msg.arg2);
1465                     break;
1466                 case MSG_BROADCAST_ENHANCED_PREDICTION:
1467                     removeMessages(MSG_BROADCAST_ENHANCED_PREDICTION);
1468                     sendEnhancedDischargePredictionBroadcast();
1469                     break;
1470                 case MSG_PROFILE_TIMED_OUT:
1471                     lockProfile(msg.arg1);
1472                     break;
1473                 case MSG_WIRED_CHARGING_STARTED:
1474                     showWiredChargingStarted(msg.arg1);
1475                     break;
1476                 case MSG_SCREEN_POLICY:
1477                     screenPolicyChanging(msg.arg1, msg.arg2);
1478                     break;
1479             }
1480         }
1481     }
1482 
logWakelockStateChanged( int flags, String tag, int ownerUid, WorkSource workSource, WakelockEventType eventType)1483     private void logWakelockStateChanged(
1484             int flags,
1485             String tag,
1486             int ownerUid,
1487             WorkSource workSource,
1488             WakelockEventType eventType) {
1489         if (mBatteryStatsInternal == null) {
1490             return;
1491         }
1492         final int type = getWakelockMonitorTypeForLogging(flags);
1493         if (workSource == null || workSource.isEmpty()) {
1494             final int mappedUid = mBatteryStatsInternal.getOwnerUid(ownerUid);
1495             mFrameworkStatsLogger.wakelockStateChanged(mappedUid, tag, type, eventType);
1496         } else {
1497             for (int i = 0; i < workSource.size(); ++i) {
1498                 final int mappedUid = mBatteryStatsInternal.getOwnerUid(workSource.getUid(i));
1499                 mFrameworkStatsLogger.wakelockStateChanged(mappedUid, tag, type, eventType);
1500             }
1501 
1502             List<WorkChain> workChains = workSource.getWorkChains();
1503             if (workChains != null) {
1504                 for (WorkChain workChain : workChains) {
1505                     WorkChain mappedWorkChain = new WorkChain();
1506                     // Cache getUids() and getTags() because they make an arraycopy.
1507                     int[] uids = workChain.getUids();
1508                     String[] tags = workChain.getTags();
1509 
1510                     for (int i = 0; i < workChain.getSize(); ++i) {
1511                         final int mappedUid = mBatteryStatsInternal.getOwnerUid(uids[i]);
1512                         mappedWorkChain.addNode(mappedUid, tags[i]);
1513                     }
1514                     mFrameworkStatsLogger.wakelockStateChanged(
1515                             tag, mappedWorkChain, type, eventType);
1516                 }
1517             }
1518         }
1519     }
1520 
1521     public interface Injector {
1522         /**
1523          * Gets the current time in millis
1524          */
currentTimeMillis()1525         long currentTimeMillis();
1526 
1527         /**
1528          * Gets the WakeLockLog object
1529          */
getWakeLockLog(Context context)1530         @NonNull WakeLockLog getWakeLockLog(Context context);
1531 
1532         /**
1533          * Gets the AppOpsManager system service
1534          */
getAppOpsManager(Context context)1535         AppOpsManager getAppOpsManager(Context context);
1536 
1537         /** Gets the BatteryStatsInternal object */
getBatteryStatsInternal()1538         BatteryStatsInternal getBatteryStatsInternal();
1539 
1540         /** Get the FrameworkStatsLogger object */
getFrameworkStatsLogger()1541         FrameworkStatsLogger getFrameworkStatsLogger();
1542     }
1543 
1544     class RealInjector implements Injector {
1545         @Override
currentTimeMillis()1546         public long currentTimeMillis() {
1547             return System.currentTimeMillis();
1548         }
1549 
1550         @Override
getWakeLockLog(Context context)1551         public @NonNull WakeLockLog getWakeLockLog(Context context) {
1552             return new WakeLockLog(context);
1553         }
1554 
1555         @Override
getAppOpsManager(Context context)1556         public AppOpsManager getAppOpsManager(Context context) {
1557             return context.getSystemService(AppOpsManager.class);
1558         }
1559 
1560         @Override
getBatteryStatsInternal()1561         public BatteryStatsInternal getBatteryStatsInternal() {
1562             return LocalServices.getService(BatteryStatsInternal.class);
1563         }
1564 
1565         @Override
getFrameworkStatsLogger()1566         public FrameworkStatsLogger getFrameworkStatsLogger() {
1567             return new FrameworkStatsLogger();
1568         }
1569     }
1570 }
1571