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.AppOpsManager;
     20 import com.android.internal.app.IAppOpsService;
     21 import com.android.internal.app.IBatteryStats;
     22 import com.android.server.EventLogTags;
     23 
     24 import android.app.ActivityManagerNative;
     25 import android.content.BroadcastReceiver;
     26 import android.content.Context;
     27 import android.content.Intent;
     28 import android.media.AudioManager;
     29 import android.media.Ringtone;
     30 import android.media.RingtoneManager;
     31 import android.net.Uri;
     32 import android.os.BatteryStats;
     33 import android.os.Handler;
     34 import android.os.Looper;
     35 import android.os.Message;
     36 import android.os.PowerManager;
     37 import android.os.RemoteException;
     38 import android.os.SystemClock;
     39 import android.os.UserHandle;
     40 import android.os.WorkSource;
     41 import android.provider.Settings;
     42 import android.util.EventLog;
     43 import android.util.Slog;
     44 import android.view.WindowManagerPolicy;
     45 
     46 /**
     47  * Sends broadcasts about important power state changes.
     48  * <p>
     49  * This methods of this class may be called by the power manager service while
     50  * its lock is being held.  Internally it takes care of sending broadcasts to
     51  * notify other components of the system or applications asynchronously.
     52  * </p><p>
     53  * The notifier is designed to collapse unnecessary broadcasts when it is not
     54  * possible for the system to have observed an intermediate state.
     55  * </p><p>
     56  * For example, if the device wakes up, goes to sleep, wakes up again and goes to
     57  * sleep again before the wake up notification is sent, then the system will
     58  * be told about only one wake up and sleep.  However, we always notify the
     59  * fact that at least one transition occurred.  It is especially important to
     60  * tell the system when we go to sleep so that it can lock the keyguard if needed.
     61  * </p>
     62  */
     63 final class Notifier {
     64     private static final String TAG = "PowerManagerNotifier";
     65 
     66     private static final boolean DEBUG = false;
     67 
     68     private static final int POWER_STATE_UNKNOWN = 0;
     69     private static final int POWER_STATE_AWAKE = 1;
     70     private static final int POWER_STATE_ASLEEP = 2;
     71 
     72     private static final int MSG_USER_ACTIVITY = 1;
     73     private static final int MSG_BROADCAST = 2;
     74     private static final int MSG_WIRELESS_CHARGING_STARTED = 3;
     75 
     76     private final Object mLock = new Object();
     77 
     78     private final Context mContext;
     79     private final IBatteryStats mBatteryStats;
     80     private final IAppOpsService mAppOps;
     81     private final SuspendBlocker mSuspendBlocker;
     82     private final ScreenOnBlocker mScreenOnBlocker;
     83     private final WindowManagerPolicy mPolicy;
     84 
     85     private final NotifierHandler mHandler;
     86     private final Intent mScreenOnIntent;
     87     private final Intent mScreenOffIntent;
     88 
     89     // The current power state.
     90     private int mActualPowerState;
     91     private int mLastGoToSleepReason;
     92 
     93     // True if there is a pending transition that needs to be reported.
     94     private boolean mPendingWakeUpBroadcast;
     95     private boolean mPendingGoToSleepBroadcast;
     96 
     97     // The currently broadcasted power state.  This reflects what other parts of the
     98     // system have observed.
     99     private int mBroadcastedPowerState;
    100     private boolean mBroadcastInProgress;
    101     private long mBroadcastStartTime;
    102 
    103     // True if a user activity message should be sent.
    104     private boolean mUserActivityPending;
    105 
    106     // True if the screen on blocker has been acquired.
    107     private boolean mScreenOnBlockerAcquired;
    108 
    109     public Notifier(Looper looper, Context context, IBatteryStats batteryStats,
    110             IAppOpsService appOps, SuspendBlocker suspendBlocker, ScreenOnBlocker screenOnBlocker,
    111             WindowManagerPolicy policy) {
    112         mContext = context;
    113         mBatteryStats = batteryStats;
    114         mAppOps = appOps;
    115         mSuspendBlocker = suspendBlocker;
    116         mScreenOnBlocker = screenOnBlocker;
    117         mPolicy = policy;
    118 
    119         mHandler = new NotifierHandler(looper);
    120         mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);
    121         mScreenOnIntent.addFlags(
    122                 Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
    123         mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF);
    124         mScreenOffIntent.addFlags(
    125                 Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
    126     }
    127 
    128     /**
    129      * Called when a wake lock is acquired.
    130      */
    131     public void onWakeLockAcquired(int flags, String tag, String packageName,
    132             int ownerUid, int ownerPid, WorkSource workSource) {
    133         if (DEBUG) {
    134             Slog.d(TAG, "onWakeLockAcquired: flags=" + flags + ", tag=\"" + tag
    135                     + "\", packageName=" + packageName
    136                     + ", ownerUid=" + ownerUid + ", ownerPid=" + ownerPid
    137                     + ", workSource=" + workSource);
    138         }
    139 
    140         try {
    141             final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
    142             if (workSource != null) {
    143                 mBatteryStats.noteStartWakelockFromSource(workSource, ownerPid, tag, monitorType);
    144             } else {
    145                 mBatteryStats.noteStartWakelock(ownerUid, ownerPid, tag, monitorType);
    146                 // XXX need to deal with disabled operations.
    147                 mAppOps.startOperation(AppOpsManager.getToken(mAppOps),
    148                         AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName);
    149             }
    150         } catch (RemoteException ex) {
    151             // Ignore
    152         }
    153     }
    154 
    155     /**
    156      * Called when a wake lock is released.
    157      */
    158     public void onWakeLockReleased(int flags, String tag, String packageName,
    159             int ownerUid, int ownerPid, WorkSource workSource) {
    160         if (DEBUG) {
    161             Slog.d(TAG, "onWakeLockReleased: flags=" + flags + ", tag=\"" + tag
    162                     + "\", packageName=" + packageName
    163                     + ", ownerUid=" + ownerUid + ", ownerPid=" + ownerPid
    164                     + ", workSource=" + workSource);
    165         }
    166 
    167         try {
    168             final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
    169             if (workSource != null) {
    170                 mBatteryStats.noteStopWakelockFromSource(workSource, ownerPid, tag, monitorType);
    171             } else {
    172                 mBatteryStats.noteStopWakelock(ownerUid, ownerPid, tag, monitorType);
    173                 mAppOps.finishOperation(AppOpsManager.getToken(mAppOps),
    174                         AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName);
    175             }
    176         } catch (RemoteException ex) {
    177             // Ignore
    178         }
    179     }
    180 
    181     private static int getBatteryStatsWakeLockMonitorType(int flags) {
    182         switch (flags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
    183             case PowerManager.PARTIAL_WAKE_LOCK:
    184             case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
    185                 return BatteryStats.WAKE_TYPE_PARTIAL;
    186             default:
    187                 return BatteryStats.WAKE_TYPE_FULL;
    188         }
    189     }
    190 
    191     /**
    192      * Called when the screen is turned on.
    193      */
    194     public void onScreenOn() {
    195         if (DEBUG) {
    196             Slog.d(TAG, "onScreenOn");
    197         }
    198 
    199         try {
    200             mBatteryStats.noteScreenOn();
    201         } catch (RemoteException ex) {
    202             // Ignore
    203         }
    204     }
    205 
    206     /**
    207      * Called when the screen is turned off.
    208      */
    209     public void onScreenOff() {
    210         if (DEBUG) {
    211             Slog.d(TAG, "onScreenOff");
    212         }
    213 
    214         try {
    215             mBatteryStats.noteScreenOff();
    216         } catch (RemoteException ex) {
    217             // Ignore
    218         }
    219     }
    220 
    221     /**
    222      * Called when the screen changes brightness.
    223      */
    224     public void onScreenBrightness(int brightness) {
    225         if (DEBUG) {
    226             Slog.d(TAG, "onScreenBrightness: brightness=" + brightness);
    227         }
    228 
    229         try {
    230             mBatteryStats.noteScreenBrightness(brightness);
    231         } catch (RemoteException ex) {
    232             // Ignore
    233         }
    234     }
    235 
    236     /**
    237      * Called when the device is waking up from sleep and the
    238      * display is about to be turned on.
    239      */
    240     public void onWakeUpStarted() {
    241         if (DEBUG) {
    242             Slog.d(TAG, "onWakeUpStarted");
    243         }
    244 
    245         synchronized (mLock) {
    246             if (mActualPowerState != POWER_STATE_AWAKE) {
    247                 mActualPowerState = POWER_STATE_AWAKE;
    248                 mPendingWakeUpBroadcast = true;
    249                 if (!mScreenOnBlockerAcquired) {
    250                     mScreenOnBlockerAcquired = true;
    251                     mScreenOnBlocker.acquire();
    252                 }
    253                 updatePendingBroadcastLocked();
    254             }
    255         }
    256     }
    257 
    258     /**
    259      * Called when the device has finished waking up from sleep
    260      * and the display has been turned on.
    261      */
    262     public void onWakeUpFinished() {
    263         if (DEBUG) {
    264             Slog.d(TAG, "onWakeUpFinished");
    265         }
    266     }
    267 
    268     /**
    269      * Called when the device is going to sleep.
    270      */
    271     public void onGoToSleepStarted(int reason) {
    272         if (DEBUG) {
    273             Slog.d(TAG, "onGoToSleepStarted");
    274         }
    275 
    276         synchronized (mLock) {
    277             mLastGoToSleepReason = reason;
    278         }
    279     }
    280 
    281     /**
    282      * Called when the device has finished going to sleep and the
    283      * display has been turned off.
    284      *
    285      * This is a good time to make transitions that we don't want the user to see,
    286      * such as bringing the key guard to focus.  There's no guarantee for this,
    287      * however because the user could turn the device on again at any time.
    288      * Some things may need to be protected by other mechanisms that defer screen on.
    289      */
    290     public void onGoToSleepFinished() {
    291         if (DEBUG) {
    292             Slog.d(TAG, "onGoToSleepFinished");
    293         }
    294 
    295         synchronized (mLock) {
    296             if (mActualPowerState != POWER_STATE_ASLEEP) {
    297                 mActualPowerState = POWER_STATE_ASLEEP;
    298                 mPendingGoToSleepBroadcast = true;
    299                 if (mUserActivityPending) {
    300                     mUserActivityPending = false;
    301                     mHandler.removeMessages(MSG_USER_ACTIVITY);
    302                 }
    303                 updatePendingBroadcastLocked();
    304             }
    305         }
    306     }
    307 
    308     /**
    309      * Called when there has been user activity.
    310      */
    311     public void onUserActivity(int event, int uid) {
    312         if (DEBUG) {
    313             Slog.d(TAG, "onUserActivity: event=" + event + ", uid=" + uid);
    314         }
    315 
    316         try {
    317             mBatteryStats.noteUserActivity(uid, event);
    318         } catch (RemoteException ex) {
    319             // Ignore
    320         }
    321 
    322         synchronized (mLock) {
    323             if (!mUserActivityPending) {
    324                 mUserActivityPending = true;
    325                 Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY);
    326                 msg.setAsynchronous(true);
    327                 mHandler.sendMessage(msg);
    328             }
    329         }
    330     }
    331 
    332     /**
    333      * Called when wireless charging has started so as to provide user feedback.
    334      */
    335     public void onWirelessChargingStarted() {
    336         if (DEBUG) {
    337             Slog.d(TAG, "onWirelessChargingStarted");
    338         }
    339 
    340         mSuspendBlocker.acquire();
    341         Message msg = mHandler.obtainMessage(MSG_WIRELESS_CHARGING_STARTED);
    342         msg.setAsynchronous(true);
    343         mHandler.sendMessage(msg);
    344     }
    345 
    346     private void updatePendingBroadcastLocked() {
    347         if (!mBroadcastInProgress
    348                 && mActualPowerState != POWER_STATE_UNKNOWN
    349                 && (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
    350                         || mActualPowerState != mBroadcastedPowerState)) {
    351             mBroadcastInProgress = true;
    352             mSuspendBlocker.acquire();
    353             Message msg = mHandler.obtainMessage(MSG_BROADCAST);
    354             msg.setAsynchronous(true);
    355             mHandler.sendMessage(msg);
    356         }
    357     }
    358 
    359     private void finishPendingBroadcastLocked() {
    360         mBroadcastInProgress = false;
    361         mSuspendBlocker.release();
    362     }
    363 
    364     private void sendUserActivity() {
    365         synchronized (mLock) {
    366             if (!mUserActivityPending) {
    367                 return;
    368             }
    369             mUserActivityPending = false;
    370         }
    371 
    372         mPolicy.userActivity();
    373     }
    374 
    375     private void sendNextBroadcast() {
    376         final int powerState;
    377         final int goToSleepReason;
    378         synchronized (mLock) {
    379             if (mBroadcastedPowerState == POWER_STATE_UNKNOWN) {
    380                 // Broadcasted power state is unknown.  Send wake up.
    381                 mPendingWakeUpBroadcast = false;
    382                 mBroadcastedPowerState = POWER_STATE_AWAKE;
    383             } else if (mBroadcastedPowerState == POWER_STATE_AWAKE) {
    384                 // Broadcasted power state is awake.  Send asleep if needed.
    385                 if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
    386                         || mActualPowerState == POWER_STATE_ASLEEP) {
    387                     mPendingGoToSleepBroadcast = false;
    388                     mBroadcastedPowerState = POWER_STATE_ASLEEP;
    389                 } else {
    390                     finishPendingBroadcastLocked();
    391                     return;
    392                 }
    393             } else {
    394                 // Broadcasted power state is asleep.  Send awake if needed.
    395                 if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
    396                         || mActualPowerState == POWER_STATE_AWAKE) {
    397                     mPendingWakeUpBroadcast = false;
    398                     mBroadcastedPowerState = POWER_STATE_AWAKE;
    399                 } else {
    400                     finishPendingBroadcastLocked();
    401                     return;
    402                 }
    403             }
    404 
    405             mBroadcastStartTime = SystemClock.uptimeMillis();
    406             powerState = mBroadcastedPowerState;
    407             goToSleepReason = mLastGoToSleepReason;
    408         }
    409 
    410         EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_SEND, 1);
    411 
    412         if (powerState == POWER_STATE_AWAKE) {
    413             sendWakeUpBroadcast();
    414         } else {
    415             sendGoToSleepBroadcast(goToSleepReason);
    416         }
    417     }
    418 
    419     private void sendWakeUpBroadcast() {
    420         if (DEBUG) {
    421             Slog.d(TAG, "Sending wake up broadcast.");
    422         }
    423 
    424         EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, 0, 0, 0);
    425 
    426         mPolicy.screenTurningOn(mScreenOnListener);
    427 
    428         try {
    429             ActivityManagerNative.getDefault().wakingUp();
    430         } catch (RemoteException e) {
    431             // ignore it
    432         }
    433 
    434         if (ActivityManagerNative.isSystemReady()) {
    435             mContext.sendOrderedBroadcastAsUser(mScreenOnIntent, UserHandle.ALL, null,
    436                     mWakeUpBroadcastDone, mHandler, 0, null, null);
    437         } else {
    438             EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 2, 1);
    439             sendNextBroadcast();
    440         }
    441     }
    442 
    443     private final WindowManagerPolicy.ScreenOnListener mScreenOnListener =
    444             new WindowManagerPolicy.ScreenOnListener() {
    445         @Override
    446         public void onScreenOn() {
    447             synchronized (mLock) {
    448                 if (mScreenOnBlockerAcquired && !mPendingWakeUpBroadcast) {
    449                     mScreenOnBlockerAcquired = false;
    450                     mScreenOnBlocker.release();
    451                 }
    452             }
    453         }
    454     };
    455 
    456     private final BroadcastReceiver mWakeUpBroadcastDone = new BroadcastReceiver() {
    457         @Override
    458         public void onReceive(Context context, Intent intent) {
    459             EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 1,
    460                     SystemClock.uptimeMillis() - mBroadcastStartTime, 1);
    461             sendNextBroadcast();
    462         }
    463     };
    464 
    465     private void sendGoToSleepBroadcast(int reason) {
    466         if (DEBUG) {
    467             Slog.d(TAG, "Sending go to sleep broadcast.");
    468         }
    469 
    470         int why = WindowManagerPolicy.OFF_BECAUSE_OF_USER;
    471         switch (reason) {
    472             case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN:
    473                 why = WindowManagerPolicy.OFF_BECAUSE_OF_ADMIN;
    474                 break;
    475             case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT:
    476                 why = WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT;
    477                 break;
    478         }
    479 
    480         EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0, why, 0, 0);
    481 
    482         mPolicy.screenTurnedOff(why);
    483         try {
    484             ActivityManagerNative.getDefault().goingToSleep();
    485         } catch (RemoteException e) {
    486             // ignore it.
    487         }
    488 
    489         if (ActivityManagerNative.isSystemReady()) {
    490             mContext.sendOrderedBroadcastAsUser(mScreenOffIntent, UserHandle.ALL, null,
    491                     mGoToSleepBroadcastDone, mHandler, 0, null, null);
    492         } else {
    493             EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 3, 1);
    494             sendNextBroadcast();
    495         }
    496     }
    497 
    498     private final BroadcastReceiver mGoToSleepBroadcastDone = new BroadcastReceiver() {
    499         @Override
    500         public void onReceive(Context context, Intent intent) {
    501             EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 0,
    502                     SystemClock.uptimeMillis() - mBroadcastStartTime, 1);
    503             sendNextBroadcast();
    504         }
    505     };
    506 
    507     private void playWirelessChargingStartedSound() {
    508         final String soundPath = Settings.Global.getString(mContext.getContentResolver(),
    509                 Settings.Global.WIRELESS_CHARGING_STARTED_SOUND);
    510         if (soundPath != null) {
    511             final Uri soundUri = Uri.parse("file://" + soundPath);
    512             if (soundUri != null) {
    513                 final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
    514                 if (sfx != null) {
    515                     sfx.setStreamType(AudioManager.STREAM_SYSTEM);
    516                     sfx.play();
    517                 }
    518             }
    519         }
    520 
    521         mSuspendBlocker.release();
    522     }
    523 
    524     private final class NotifierHandler extends Handler {
    525         public NotifierHandler(Looper looper) {
    526             super(looper, null, true /*async*/);
    527         }
    528 
    529         @Override
    530         public void handleMessage(Message msg) {
    531             switch (msg.what) {
    532                 case MSG_USER_ACTIVITY:
    533                     sendUserActivity();
    534                     break;
    535 
    536                 case MSG_BROADCAST:
    537                     sendNextBroadcast();
    538                     break;
    539 
    540                 case MSG_WIRELESS_CHARGING_STARTED:
    541                     playWirelessChargingStartedSound();
    542                     break;
    543             }
    544         }
    545     }
    546 }
    547