Home | History | Annotate | Download | only in power
      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.app.ActivityManagerInternal;
     20 import android.app.AppOpsManager;
     21 import android.app.RetailDemoModeServiceInternal;
     22 
     23 import com.android.internal.app.IAppOpsService;
     24 import com.android.internal.app.IBatteryStats;
     25 import com.android.internal.logging.MetricsLogger;
     26 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
     27 import com.android.server.EventLogTags;
     28 import com.android.server.LocalServices;
     29 
     30 import android.content.BroadcastReceiver;
     31 import android.content.Context;
     32 import android.content.Intent;
     33 import android.hardware.input.InputManagerInternal;
     34 import android.media.AudioManager;
     35 import android.media.Ringtone;
     36 import android.media.RingtoneManager;
     37 import android.metrics.LogMaker;
     38 import android.net.Uri;
     39 import android.os.BatteryStats;
     40 import android.os.Handler;
     41 import android.os.Looper;
     42 import android.os.Message;
     43 import android.os.PowerManager;
     44 import android.os.PowerManagerInternal;
     45 import android.os.Process;
     46 import android.os.RemoteException;
     47 import android.os.SystemClock;
     48 import android.os.UserHandle;
     49 import android.os.WorkSource;
     50 import android.provider.Settings;
     51 import android.util.EventLog;
     52 import android.util.Slog;
     53 import android.view.WindowManagerPolicy;
     54 import android.view.inputmethod.InputMethodManagerInternal;
     55 
     56 /**
     57  * Sends broadcasts about important power state changes.
     58  * <p>
     59  * This methods of this class may be called by the power manager service while
     60  * its lock is being held.  Internally it takes care of sending broadcasts to
     61  * notify other components of the system or applications asynchronously.
     62  * </p><p>
     63  * The notifier is designed to collapse unnecessary broadcasts when it is not
     64  * possible for the system to have observed an intermediate state.
     65  * </p><p>
     66  * For example, if the device wakes up, goes to sleep, wakes up again and goes to
     67  * sleep again before the wake up notification is sent, then the system will
     68  * be told about only one wake up and sleep.  However, we always notify the
     69  * fact that at least one transition occurred.  It is especially important to
     70  * tell the system when we go to sleep so that it can lock the keyguard if needed.
     71  * </p>
     72  */
     73 final class Notifier {
     74     private static final String TAG = "PowerManagerNotifier";
     75 
     76     private static final boolean DEBUG = false;
     77 
     78     private static final int INTERACTIVE_STATE_UNKNOWN = 0;
     79     private static final int INTERACTIVE_STATE_AWAKE = 1;
     80     private static final int INTERACTIVE_STATE_ASLEEP = 2;
     81 
     82     private static final int MSG_USER_ACTIVITY = 1;
     83     private static final int MSG_BROADCAST = 2;
     84     private static final int MSG_WIRELESS_CHARGING_STARTED = 3;
     85     private static final int MSG_SCREEN_BRIGHTNESS_BOOST_CHANGED = 4;
     86 
     87     private final Object mLock = new Object();
     88 
     89     private final Context mContext;
     90     private final IBatteryStats mBatteryStats;
     91     private final IAppOpsService mAppOps;
     92     private final SuspendBlocker mSuspendBlocker;
     93     private final WindowManagerPolicy mPolicy;
     94     private final ActivityManagerInternal mActivityManagerInternal;
     95     private final InputManagerInternal mInputManagerInternal;
     96     private final InputMethodManagerInternal mInputMethodManagerInternal;
     97     private final RetailDemoModeServiceInternal mRetailDemoModeServiceInternal;
     98 
     99     private final NotifierHandler mHandler;
    100     private final Intent mScreenOnIntent;
    101     private final Intent mScreenOffIntent;
    102     private final Intent mScreenBrightnessBoostIntent;
    103 
    104     // True if the device should suspend when the screen is off due to proximity.
    105     private final boolean mSuspendWhenScreenOffDueToProximityConfig;
    106 
    107     // The current interactive state.  This is set as soon as an interactive state
    108     // transition begins so as to capture the reason that it happened.  At some point
    109     // this state will propagate to the pending state then eventually to the
    110     // broadcasted state over the course of reporting the transition asynchronously.
    111     private boolean mInteractive = true;
    112     private int mInteractiveChangeReason;
    113     private boolean mInteractiveChanging;
    114 
    115     // The pending interactive state that we will eventually want to broadcast.
    116     // This is designed so that we can collapse redundant sequences of awake/sleep
    117     // transition pairs while still guaranteeing that at least one transition is observed
    118     // whenever this happens.
    119     private int mPendingInteractiveState;
    120     private boolean mPendingWakeUpBroadcast;
    121     private boolean mPendingGoToSleepBroadcast;
    122 
    123     // The currently broadcasted interactive state.  This reflects what other parts of the
    124     // system have observed.
    125     private int mBroadcastedInteractiveState;
    126     private boolean mBroadcastInProgress;
    127     private long mBroadcastStartTime;
    128 
    129     // True if a user activity message should be sent.
    130     private boolean mUserActivityPending;
    131 
    132     public Notifier(Looper looper, Context context, IBatteryStats batteryStats,
    133             IAppOpsService appOps, SuspendBlocker suspendBlocker,
    134             WindowManagerPolicy policy) {
    135         mContext = context;
    136         mBatteryStats = batteryStats;
    137         mAppOps = appOps;
    138         mSuspendBlocker = suspendBlocker;
    139         mPolicy = policy;
    140         mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
    141         mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
    142         mInputMethodManagerInternal = LocalServices.getService(InputMethodManagerInternal.class);
    143         mRetailDemoModeServiceInternal = LocalServices.getService(RetailDemoModeServiceInternal.class);
    144 
    145         mHandler = new NotifierHandler(looper);
    146         mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);
    147         mScreenOnIntent.addFlags(
    148                 Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND
    149                 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
    150         mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF);
    151         mScreenOffIntent.addFlags(
    152                 Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND
    153                 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
    154         mScreenBrightnessBoostIntent =
    155                 new Intent(PowerManager.ACTION_SCREEN_BRIGHTNESS_BOOST_CHANGED);
    156         mScreenBrightnessBoostIntent.addFlags(
    157                 Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
    158 
    159         mSuspendWhenScreenOffDueToProximityConfig = context.getResources().getBoolean(
    160                 com.android.internal.R.bool.config_suspendWhenScreenOffDueToProximity);
    161 
    162         // Initialize interactive state for battery stats.
    163         try {
    164             mBatteryStats.noteInteractive(true);
    165         } catch (RemoteException ex) { }
    166     }
    167 
    168     /**
    169      * Called when a wake lock is acquired.
    170      */
    171     public void onWakeLockAcquired(int flags, String tag, String packageName,
    172             int ownerUid, int ownerPid, WorkSource workSource, String historyTag) {
    173         if (DEBUG) {
    174             Slog.d(TAG, "onWakeLockAcquired: flags=" + flags + ", tag=\"" + tag
    175                     + "\", packageName=" + packageName
    176                     + ", ownerUid=" + ownerUid + ", ownerPid=" + ownerPid
    177                     + ", workSource=" + workSource);
    178         }
    179 
    180         final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
    181         if (monitorType >= 0) {
    182             try {
    183                 final boolean unimportantForLogging = ownerUid == Process.SYSTEM_UID
    184                         && (flags & PowerManager.UNIMPORTANT_FOR_LOGGING) != 0;
    185                 if (workSource != null) {
    186                     mBatteryStats.noteStartWakelockFromSource(workSource, ownerPid, tag,
    187                             historyTag, monitorType, unimportantForLogging);
    188                 } else {
    189                     mBatteryStats.noteStartWakelock(ownerUid, ownerPid, tag, historyTag,
    190                             monitorType, unimportantForLogging);
    191                     // XXX need to deal with disabled operations.
    192                     mAppOps.startOperation(AppOpsManager.getToken(mAppOps),
    193                             AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName);
    194                 }
    195             } catch (RemoteException ex) {
    196                 // Ignore
    197             }
    198         }
    199     }
    200 
    201     public void onLongPartialWakeLockStart(String tag, int ownerUid, WorkSource workSource,
    202             String historyTag) {
    203         if (DEBUG) {
    204             Slog.d(TAG, "onLongPartialWakeLockStart: ownerUid=" + ownerUid
    205                     + ", workSource=" + workSource);
    206         }
    207 
    208         try {
    209             if (workSource != null) {
    210                 final int N = workSource.size();
    211                 for (int i=0; i<N; i++) {
    212                     mBatteryStats.noteLongPartialWakelockStart(tag, historyTag, workSource.get(i));
    213                 }
    214             } else {
    215                 mBatteryStats.noteLongPartialWakelockStart(tag, historyTag, ownerUid);
    216             }
    217         } catch (RemoteException ex) {
    218             // Ignore
    219         }
    220     }
    221 
    222     public void onLongPartialWakeLockFinish(String tag, int ownerUid, WorkSource workSource,
    223             String historyTag) {
    224         if (DEBUG) {
    225             Slog.d(TAG, "onLongPartialWakeLockFinish: ownerUid=" + ownerUid
    226                     + ", workSource=" + workSource);
    227         }
    228 
    229         try {
    230             if (workSource != null) {
    231                 final int N = workSource.size();
    232                 for (int i=0; i<N; i++) {
    233                     mBatteryStats.noteLongPartialWakelockFinish(tag, historyTag, workSource.get(i));
    234                 }
    235             } else {
    236                 mBatteryStats.noteLongPartialWakelockFinish(tag, historyTag, ownerUid);
    237             }
    238         } catch (RemoteException ex) {
    239             // Ignore
    240         }
    241     }
    242 
    243     /**
    244      * Called when a wake lock is changing.
    245      */
    246     public void onWakeLockChanging(int flags, String tag, String packageName,
    247             int ownerUid, int ownerPid, WorkSource workSource, String historyTag,
    248             int newFlags, String newTag, String newPackageName, int newOwnerUid,
    249             int newOwnerPid, WorkSource newWorkSource, String newHistoryTag) {
    250 
    251         final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
    252         final int newMonitorType = getBatteryStatsWakeLockMonitorType(newFlags);
    253         if (workSource != null && newWorkSource != null
    254                 && monitorType >= 0 && newMonitorType >= 0) {
    255             if (DEBUG) {
    256                 Slog.d(TAG, "onWakeLockChanging: flags=" + newFlags + ", tag=\"" + newTag
    257                         + "\", packageName=" + newPackageName
    258                         + ", ownerUid=" + newOwnerUid + ", ownerPid=" + newOwnerPid
    259                         + ", workSource=" + newWorkSource);
    260             }
    261 
    262             final boolean unimportantForLogging = newOwnerUid == Process.SYSTEM_UID
    263                     && (newFlags & PowerManager.UNIMPORTANT_FOR_LOGGING) != 0;
    264             try {
    265                 mBatteryStats.noteChangeWakelockFromSource(workSource, ownerPid, tag, historyTag,
    266                         monitorType, newWorkSource, newOwnerPid, newTag, newHistoryTag,
    267                         newMonitorType, unimportantForLogging);
    268             } catch (RemoteException ex) {
    269                 // Ignore
    270             }
    271         } else {
    272             onWakeLockReleased(flags, tag, packageName, ownerUid, ownerPid, workSource, historyTag);
    273             onWakeLockAcquired(newFlags, newTag, newPackageName, newOwnerUid, newOwnerPid,
    274                     newWorkSource, newHistoryTag);
    275         }
    276     }
    277 
    278     /**
    279      * Called when a wake lock is released.
    280      */
    281     public void onWakeLockReleased(int flags, String tag, String packageName,
    282             int ownerUid, int ownerPid, WorkSource workSource, String historyTag) {
    283         if (DEBUG) {
    284             Slog.d(TAG, "onWakeLockReleased: flags=" + flags + ", tag=\"" + tag
    285                     + "\", packageName=" + packageName
    286                     + ", ownerUid=" + ownerUid + ", ownerPid=" + ownerPid
    287                     + ", workSource=" + workSource);
    288         }
    289 
    290         final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
    291         if (monitorType >= 0) {
    292             try {
    293                 if (workSource != null) {
    294                     mBatteryStats.noteStopWakelockFromSource(workSource, ownerPid, tag,
    295                             historyTag, monitorType);
    296                 } else {
    297                     mBatteryStats.noteStopWakelock(ownerUid, ownerPid, tag,
    298                             historyTag, monitorType);
    299                     mAppOps.finishOperation(AppOpsManager.getToken(mAppOps),
    300                             AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName);
    301                 }
    302             } catch (RemoteException ex) {
    303                 // Ignore
    304             }
    305         }
    306     }
    307 
    308     private int getBatteryStatsWakeLockMonitorType(int flags) {
    309         switch (flags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
    310             case PowerManager.PARTIAL_WAKE_LOCK:
    311                 return BatteryStats.WAKE_TYPE_PARTIAL;
    312 
    313             case PowerManager.SCREEN_DIM_WAKE_LOCK:
    314             case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
    315                 return BatteryStats.WAKE_TYPE_FULL;
    316 
    317             case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
    318                 if (mSuspendWhenScreenOffDueToProximityConfig) {
    319                     return -1;
    320                 }
    321                 return BatteryStats.WAKE_TYPE_PARTIAL;
    322 
    323             case PowerManager.DRAW_WAKE_LOCK:
    324                 return BatteryStats.WAKE_TYPE_DRAW;
    325 
    326             case PowerManager.DOZE_WAKE_LOCK:
    327                 // Doze wake locks are an internal implementation detail of the
    328                 // communication between dream manager service and power manager
    329                 // service.  They have no additive battery impact.
    330                 return -1;
    331 
    332             default:
    333                 return -1;
    334         }
    335     }
    336 
    337     /**
    338      * Notifies that the device is changing wakefulness.
    339      * This function may be called even if the previous change hasn't finished in
    340      * which case it will assume that the state did not fully converge before the
    341      * next transition began and will recover accordingly.
    342      */
    343     public void onWakefulnessChangeStarted(final int wakefulness, int reason) {
    344         final boolean interactive = PowerManagerInternal.isInteractive(wakefulness);
    345         if (DEBUG) {
    346             Slog.d(TAG, "onWakefulnessChangeStarted: wakefulness=" + wakefulness
    347                     + ", reason=" + reason + ", interactive=" + interactive);
    348         }
    349 
    350         // Tell the activity manager about changes in wakefulness, not just interactivity.
    351         // It needs more granularity than other components.
    352         mHandler.post(new Runnable() {
    353             @Override
    354             public void run() {
    355                 mActivityManagerInternal.onWakefulnessChanged(wakefulness);
    356             }
    357         });
    358 
    359         // Handle any early interactive state changes.
    360         // Finish pending incomplete ones from a previous cycle.
    361         if (mInteractive != interactive) {
    362             // Finish up late behaviors if needed.
    363             if (mInteractiveChanging) {
    364                 handleLateInteractiveChange();
    365             }
    366 
    367             // Start input as soon as we start waking up or going to sleep.
    368             mInputManagerInternal.setInteractive(interactive);
    369             mInputMethodManagerInternal.setInteractive(interactive);
    370 
    371             // Notify battery stats.
    372             try {
    373                 mBatteryStats.noteInteractive(interactive);
    374             } catch (RemoteException ex) { }
    375 
    376             // Handle early behaviors.
    377             mInteractive = interactive;
    378             mInteractiveChangeReason = reason;
    379             mInteractiveChanging = true;
    380             handleEarlyInteractiveChange();
    381         }
    382     }
    383 
    384     /**
    385      * Notifies that the device has finished changing wakefulness.
    386      */
    387     public void onWakefulnessChangeFinished() {
    388         if (DEBUG) {
    389             Slog.d(TAG, "onWakefulnessChangeFinished");
    390         }
    391 
    392         if (mInteractiveChanging) {
    393             mInteractiveChanging = false;
    394             handleLateInteractiveChange();
    395         }
    396     }
    397 
    398     /**
    399      * Handle early interactive state changes such as getting applications or the lock
    400      * screen running and ready for the user to see (such as when turning on the screen).
    401      */
    402     private void handleEarlyInteractiveChange() {
    403         synchronized (mLock) {
    404             if (mInteractive) {
    405                 // Waking up...
    406                 mHandler.post(new Runnable() {
    407                     @Override
    408                     public void run() {
    409                         // Note a SCREEN tron event is logged in PowerManagerService.
    410                         mPolicy.startedWakingUp();
    411                     }
    412                 });
    413 
    414                 // Send interactive broadcast.
    415                 mPendingInteractiveState = INTERACTIVE_STATE_AWAKE;
    416                 mPendingWakeUpBroadcast = true;
    417                 updatePendingBroadcastLocked();
    418             } else {
    419                 // Going to sleep...
    420                 // Tell the policy that we started going to sleep.
    421                 final int why = translateOffReason(mInteractiveChangeReason);
    422                 mHandler.post(new Runnable() {
    423                     @Override
    424                     public void run() {
    425                         mPolicy.startedGoingToSleep(why);
    426                     }
    427                 });
    428             }
    429         }
    430     }
    431 
    432     /**
    433      * Handle late interactive state changes once they are finished so that the system can
    434      * finish pending transitions (such as turning the screen off) before causing
    435      * applications to change state visibly.
    436      */
    437     private void handleLateInteractiveChange() {
    438         synchronized (mLock) {
    439             if (mInteractive) {
    440                 // Finished waking up...
    441                 mHandler.post(new Runnable() {
    442                     @Override
    443                     public void run() {
    444                         mPolicy.finishedWakingUp();
    445                     }
    446                 });
    447             } else {
    448                 // Finished going to sleep...
    449                 // This is a good time to make transitions that we don't want the user to see,
    450                 // such as bringing the key guard to focus.  There's no guarantee for this
    451                 // however because the user could turn the device on again at any time.
    452                 // Some things may need to be protected by other mechanisms that defer screen on.
    453 
    454                 // Cancel pending user activity.
    455                 if (mUserActivityPending) {
    456                     mUserActivityPending = false;
    457                     mHandler.removeMessages(MSG_USER_ACTIVITY);
    458                 }
    459 
    460                 // Tell the policy we finished going to sleep.
    461                 final int why = translateOffReason(mInteractiveChangeReason);
    462                 mHandler.post(new Runnable() {
    463                     @Override
    464                     public void run() {
    465                         LogMaker log = new LogMaker(MetricsEvent.SCREEN);
    466                         log.setType(MetricsEvent.TYPE_CLOSE);
    467                         log.setSubtype(why);
    468                         MetricsLogger.action(log);
    469                         EventLogTags.writePowerScreenState(0, why, 0, 0, 0);
    470                         mPolicy.finishedGoingToSleep(why);
    471                     }
    472                 });
    473 
    474                 // Send non-interactive broadcast.
    475                 mPendingInteractiveState = INTERACTIVE_STATE_ASLEEP;
    476                 mPendingGoToSleepBroadcast = true;
    477                 updatePendingBroadcastLocked();
    478             }
    479         }
    480     }
    481 
    482     private static int translateOffReason(int reason) {
    483         switch (reason) {
    484             case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN:
    485                 return WindowManagerPolicy.OFF_BECAUSE_OF_ADMIN;
    486             case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT:
    487                 return WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT;
    488             default:
    489                 return WindowManagerPolicy.OFF_BECAUSE_OF_USER;
    490         }
    491     }
    492 
    493     /**
    494      * Called when screen brightness boost begins or ends.
    495      */
    496     public void onScreenBrightnessBoostChanged() {
    497         if (DEBUG) {
    498             Slog.d(TAG, "onScreenBrightnessBoostChanged");
    499         }
    500 
    501         mSuspendBlocker.acquire();
    502         Message msg = mHandler.obtainMessage(MSG_SCREEN_BRIGHTNESS_BOOST_CHANGED);
    503         msg.setAsynchronous(true);
    504         mHandler.sendMessage(msg);
    505     }
    506 
    507     /**
    508      * Called when there has been user activity.
    509      */
    510     public void onUserActivity(int event, int uid) {
    511         if (DEBUG) {
    512             Slog.d(TAG, "onUserActivity: event=" + event + ", uid=" + uid);
    513         }
    514 
    515         try {
    516             mBatteryStats.noteUserActivity(uid, event);
    517         } catch (RemoteException ex) {
    518             // Ignore
    519         }
    520 
    521         synchronized (mLock) {
    522             if (!mUserActivityPending) {
    523                 mUserActivityPending = true;
    524                 Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY);
    525                 msg.setAsynchronous(true);
    526                 mHandler.sendMessage(msg);
    527             }
    528         }
    529     }
    530 
    531     /**
    532      * Called when the screen has turned on.
    533      */
    534     public void onWakeUp(String reason, int reasonUid, String opPackageName, int opUid) {
    535         if (DEBUG) {
    536             Slog.d(TAG, "onWakeUp: event=" + reason + ", reasonUid=" + reasonUid
    537                     + " opPackageName=" + opPackageName + " opUid=" + opUid);
    538         }
    539 
    540         try {
    541             mBatteryStats.noteWakeUp(reason, reasonUid);
    542             if (opPackageName != null) {
    543                 mAppOps.noteOperation(AppOpsManager.OP_TURN_SCREEN_ON, opUid, opPackageName);
    544             }
    545         } catch (RemoteException ex) {
    546             // Ignore
    547         }
    548 
    549     }
    550 
    551     /**
    552      * Called when wireless charging has started so as to provide user feedback.
    553      */
    554     public void onWirelessChargingStarted() {
    555         if (DEBUG) {
    556             Slog.d(TAG, "onWirelessChargingStarted");
    557         }
    558 
    559         mSuspendBlocker.acquire();
    560         Message msg = mHandler.obtainMessage(MSG_WIRELESS_CHARGING_STARTED);
    561         msg.setAsynchronous(true);
    562         mHandler.sendMessage(msg);
    563     }
    564 
    565     private void updatePendingBroadcastLocked() {
    566         if (!mBroadcastInProgress
    567                 && mPendingInteractiveState != INTERACTIVE_STATE_UNKNOWN
    568                 && (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
    569                         || mPendingInteractiveState != mBroadcastedInteractiveState)) {
    570             mBroadcastInProgress = true;
    571             mSuspendBlocker.acquire();
    572             Message msg = mHandler.obtainMessage(MSG_BROADCAST);
    573             msg.setAsynchronous(true);
    574             mHandler.sendMessage(msg);
    575         }
    576     }
    577 
    578     private void finishPendingBroadcastLocked() {
    579         mBroadcastInProgress = false;
    580         mSuspendBlocker.release();
    581     }
    582 
    583     private void sendUserActivity() {
    584         synchronized (mLock) {
    585             if (!mUserActivityPending) {
    586                 return;
    587             }
    588             mUserActivityPending = false;
    589         }
    590         if (mRetailDemoModeServiceInternal != null) {
    591             mRetailDemoModeServiceInternal.onUserActivity();
    592         }
    593         mPolicy.userActivity();
    594     }
    595 
    596     private void sendNextBroadcast() {
    597         final int powerState;
    598         synchronized (mLock) {
    599             if (mBroadcastedInteractiveState == INTERACTIVE_STATE_UNKNOWN) {
    600                 // Broadcasted power state is unknown.  Send wake up.
    601                 mPendingWakeUpBroadcast = false;
    602                 mBroadcastedInteractiveState = INTERACTIVE_STATE_AWAKE;
    603             } else if (mBroadcastedInteractiveState == INTERACTIVE_STATE_AWAKE) {
    604                 // Broadcasted power state is awake.  Send asleep if needed.
    605                 if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
    606                         || mPendingInteractiveState == INTERACTIVE_STATE_ASLEEP) {
    607                     mPendingGoToSleepBroadcast = false;
    608                     mBroadcastedInteractiveState = INTERACTIVE_STATE_ASLEEP;
    609                 } else {
    610                     finishPendingBroadcastLocked();
    611                     return;
    612                 }
    613             } else {
    614                 // Broadcasted power state is asleep.  Send awake if needed.
    615                 if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
    616                         || mPendingInteractiveState == INTERACTIVE_STATE_AWAKE) {
    617                     mPendingWakeUpBroadcast = false;
    618                     mBroadcastedInteractiveState = INTERACTIVE_STATE_AWAKE;
    619                 } else {
    620                     finishPendingBroadcastLocked();
    621                     return;
    622                 }
    623             }
    624 
    625             mBroadcastStartTime = SystemClock.uptimeMillis();
    626             powerState = mBroadcastedInteractiveState;
    627         }
    628 
    629         EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_SEND, 1);
    630 
    631         if (powerState == INTERACTIVE_STATE_AWAKE) {
    632             sendWakeUpBroadcast();
    633         } else {
    634             sendGoToSleepBroadcast();
    635         }
    636     }
    637 
    638     private void sendBrightnessBoostChangedBroadcast() {
    639         if (DEBUG) {
    640             Slog.d(TAG, "Sending brightness boost changed broadcast.");
    641         }
    642 
    643         mContext.sendOrderedBroadcastAsUser(mScreenBrightnessBoostIntent, UserHandle.ALL, null,
    644                 mScreeBrightnessBoostChangedDone, mHandler, 0, null, null);
    645     }
    646 
    647     private final BroadcastReceiver mScreeBrightnessBoostChangedDone = new BroadcastReceiver() {
    648         @Override
    649         public void onReceive(Context context, Intent intent) {
    650             mSuspendBlocker.release();
    651         }
    652     };
    653 
    654     private void sendWakeUpBroadcast() {
    655         if (DEBUG) {
    656             Slog.d(TAG, "Sending wake up broadcast.");
    657         }
    658 
    659         if (mActivityManagerInternal.isSystemReady()) {
    660             mContext.sendOrderedBroadcastAsUser(mScreenOnIntent, UserHandle.ALL, null,
    661                     mWakeUpBroadcastDone, mHandler, 0, null, null);
    662         } else {
    663             EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 2, 1);
    664             sendNextBroadcast();
    665         }
    666     }
    667 
    668     private final BroadcastReceiver mWakeUpBroadcastDone = new BroadcastReceiver() {
    669         @Override
    670         public void onReceive(Context context, Intent intent) {
    671             EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 1,
    672                     SystemClock.uptimeMillis() - mBroadcastStartTime, 1);
    673             sendNextBroadcast();
    674         }
    675     };
    676 
    677     private void sendGoToSleepBroadcast() {
    678         if (DEBUG) {
    679             Slog.d(TAG, "Sending go to sleep broadcast.");
    680         }
    681 
    682         if (mActivityManagerInternal.isSystemReady()) {
    683             mContext.sendOrderedBroadcastAsUser(mScreenOffIntent, UserHandle.ALL, null,
    684                     mGoToSleepBroadcastDone, mHandler, 0, null, null);
    685         } else {
    686             EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 3, 1);
    687             sendNextBroadcast();
    688         }
    689     }
    690 
    691     private final BroadcastReceiver mGoToSleepBroadcastDone = new BroadcastReceiver() {
    692         @Override
    693         public void onReceive(Context context, Intent intent) {
    694             EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 0,
    695                     SystemClock.uptimeMillis() - mBroadcastStartTime, 1);
    696             sendNextBroadcast();
    697         }
    698     };
    699 
    700     private void playWirelessChargingStartedSound() {
    701         final boolean enabled = Settings.Global.getInt(mContext.getContentResolver(),
    702                 Settings.Global.CHARGING_SOUNDS_ENABLED, 1) != 0;
    703         final String soundPath = Settings.Global.getString(mContext.getContentResolver(),
    704                 Settings.Global.WIRELESS_CHARGING_STARTED_SOUND);
    705         if (enabled && soundPath != null) {
    706             final Uri soundUri = Uri.parse("file://" + soundPath);
    707             if (soundUri != null) {
    708                 final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
    709                 if (sfx != null) {
    710                     sfx.setStreamType(AudioManager.STREAM_SYSTEM);
    711                     sfx.play();
    712                 }
    713             }
    714         }
    715 
    716         mSuspendBlocker.release();
    717     }
    718 
    719     private final class NotifierHandler extends Handler {
    720         public NotifierHandler(Looper looper) {
    721             super(looper, null, true /*async*/);
    722         }
    723 
    724         @Override
    725         public void handleMessage(Message msg) {
    726             switch (msg.what) {
    727                 case MSG_USER_ACTIVITY:
    728                     sendUserActivity();
    729                     break;
    730 
    731                 case MSG_BROADCAST:
    732                     sendNextBroadcast();
    733                     break;
    734 
    735                 case MSG_WIRELESS_CHARGING_STARTED:
    736                     playWirelessChargingStartedSound();
    737                     break;
    738                 case MSG_SCREEN_BRIGHTNESS_BOOST_CHANGED:
    739                     sendBrightnessBoostChangedBroadcast();
    740                     break;
    741             }
    742         }
    743     }
    744 }
    745