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