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