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