Android电源管理
1.电源管理服务–PowerManagerService
PowerManagerService提供Android系统的电源管理服务,主要功能是控制系统的待机状态,控制显示屏的开关和亮度调节,以及查询和控制光线传感器和距离传感器等。
1.1 初始化过程
PowerManagerService是在SystemServer中创建并加入到ServiceManager中的:
Slog.i(TAG, "Power Manager");
power = new PowerManagerService();
ServiceManager.addService(Context.POWER_SERVICE, power);
PowerManagerService的构造方法:
public PowerManagerService() {
synchronized (mLock) {
mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks");
mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display");
mDisplaySuspendBlocker.acquire();
mHoldingDisplaySuspendBlocker = true;
mScreenOnBlocker = new ScreenOnBlockerImpl();
mDisplayBlanker = new DisplayBlankerImpl();
mWakefulness = WAKEFULNESS_AWAKE; //设置PMS的状态
}
nativeInit();
nativeSetPowerState(true, true);
}
PowerManagerService的构造方法首先创建了mWakeLockSuspendBlocker、mDisplaySuspendBlocker对象。变量mWakefulness被设置成WAKEFULNESS_AWAKE,它表示PMS的状态,一共有4种定义。
-
private static final int WAKEFULNESS_ASLEEP = 0; 表示系统目前处于休眠状态,只能被wakeUp()调用唤醒。屏幕应该处于关闭状态或正在由显示控制器关闭的过程中。
-
private static final int WAKEFULNESS_AWAKE = 1; 表示系统处于正常运行状态,可以通过 goToSleep()使其进入睡眠。当用户活动超时到期时,设备可能会开始小睡或进入睡眠状态。
-
private static final int WAKEFULNESS_NAPPING = 2; 系统正在"小睡"。它正在决定是播放屏保还是要睡眠,但还没有确定。可以通过调用wakeUp()来唤醒它,从而结束小睡。 用户活动可能会使屏幕变亮,但不会结束nap。
-
private static final int WAKEFULNESS_DREAMING = 3; 设备正在播放屏保状态。可以通过调用akeUp()来唤醒它,结束播放屏保。 播放屏保结束或拔下电源时,调用goToSleep(),设备进入睡眠状态。 用户活动可能会使屏幕变亮,但并不能结束屏保状态。
然后调用nativeInit:
private native void nativeInit();
它在native层的实现:
static void nativeInit(JNIEnv* env, jobject obj) {
gPowerManagerServiceObj = env->NewGlobalRef(obj);
status_t err = hw_get_module(POWER_HARDWARE_MODULE_ID,
(hw_module_t const**)&gPowerModule);
if (!err) {
gPowerModule->init(gPowerModule);
} else {
ALOGE("Couldn't load %s module (%s)", POWER_HARDWARE_MODULE_ID, strerror(-err));
}
}
nativeInit主要工作是装载“Power”模块,然后调用了模块的初始化函数init。
然后在SystemServer创建PMS后,还会调用它的init方法。
// only initialize the power service after we have started the
// lights service, content providers and the battery service.
power.init(context, lights, ActivityManagerService.self(), battery,
BatteryStatsService.getService(), ActivityManagerService.self().getAppOpsService(), display);
init创建了处理消息的线程和发送消息的PowerManagerHandler对象。
/**
* Initialize the power manager.
* Must be called before any other functions within the power manager are called.
*/
public void init(Context context, LightsService ls,
ActivityManagerService am, BatteryService bs, IBatteryStats bss,
IAppOpsService appOps, DisplayManagerService dm) {
mContext = context;
mLightsService = ls;
mBatteryService = bs;
mBatteryStats = bss;
mAppOps = appOps;
mDisplayManagerService = dm;
mHandlerThread = new HandlerThread(TAG);
mHandlerThread.start();
mHandler = new PowerManagerHandler(mHandlerThread.getLooper());
Watchdog.getInstance().addMonitor(this);
Watchdog.getInstance().addThread(mHandler, mHandlerThread.getName());
// Forcibly turn the screen on at boot so that it is in a known power state.
// We do this in init() rather than in the constructor because setting the
// screen state requires a call into surface flinger which then needs to call back
// into the activity manager to check permissions. Unfortunately the
// activity manager is not running when the constructor is called, so we
// have to defer setting the screen state until this point.
mDisplayBlanker.unblankAllDisplays();
}
SystemServer然后调用PMS的systemReady方法,相当于在系统准备就绪后对PMS再进行一些初始化工作。
1.2 系统准备工作–systemReady
try {
power.systemReady(twilight, dreamy);
} catch (Throwable e) {
reportWtf("making Power Manager Service ready", e);
}
public void systemReady(TwilightService twilight, DreamManagerService dreamManager) {
synchronized (mLock) {
mSystemReady = true;
mDreamManager = dreamManager;
//获取缺省、最大、最小屏幕亮度
PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
mScreenBrightnessSettingMinimum = pm.getMinimumScreenBrightnessSetting();
mScreenBrightnessSettingMaximum = pm.getMaximumScreenBrightnessSetting();
mScreenBrightnessSettingDefault = pm.getDefaultScreenBrightnessSetting();
mhisys.adjustDevState("/proc/inputblock/status","0");
//创建SensorManager对象,用于和SensorService交互
SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper());
// The notifier runs on the system server's main looper so as not to interfere
// with the animations and other critical functions of the power manager.
mNotifier = new Notifier(Looper.getMainLooper(), mContext, mBatteryStats,
mAppOps, createSuspendBlockerLocked("PowerManagerService.Broadcasts"),
mScreenOnBlocker, mPolicy);
// The display power controller runs on the power manager service's
// own handler thread to ensure timely operation.
mDisplayPowerController = new DisplayPowerController(mHandler.getLooper(),
mContext, mNotifier, mLightsService, twilight, sensorManager,
mDisplayManagerService, mDisplaySuspendBlocker, mDisplayBlanker,
mDisplayPowerControllerCallbacks, mHandler);
//创建检测无线充电对象WirelessChargerDetector
mWirelessChargerDetector = new WirelessChargerDetector(sensorManager,
createSuspendBlockerLocked("PowerManagerService.WirelessChargerDetector"),
mHandler);
//创建监听系统设置项变化的对象
mSettingsObserver = new SettingsObserver(mHandler);
mAttentionLight = mLightsService.getLight(LightsService.LIGHT_ID_ATTENTION);
// Register for broadcasts from other components of the system.
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
mContext.registerReceiver(new BatteryReceiver(), filter, null, mHandler);
filter = new IntentFilter();
filter.addAction(Intent.ACTION_BOOT_COMPLETED);
mContext.registerReceiver(new BootCompletedReceiver(), filter, null, mHandler);
filter = new IntentFilter();
filter.addAction(Intent.ACTION_DREAMING_STARTED);
filter.addAction(Intent.ACTION_DREAMING_STOPPED);
mContext.registerReceiver(new DreamReceiver(), filter, null, mHandler);
filter = new IntentFilter();
filter.addAction(Intent.ACTION_USER_SWITCHED);
mContext.registerReceiver(new UserSwitchedReceiver(), filter, null, mHandler);
filter = new IntentFilter();
filter.addAction(Intent.ACTION_DOCK_EVENT);
mContext.registerReceiver(new DockReceiver(), filter, null, mHandler);
// Register for settings changes.
final ContentResolver resolver = mContext.getContentResolver();
resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.SCREENSAVER_ENABLED),
false, mSettingsObserver, UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP),
false, mSettingsObserver, UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK),
false, mSettingsObserver, UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.System.getUriFor(
Settings.System.SCREEN_OFF_TIMEOUT),
false, mSettingsObserver, UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.STAY_ON_WHILE_PLUGGED_IN),
false, mSettingsObserver, UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.System.getUriFor(
Settings.System.SCREEN_BRIGHTNESS),
false, mSettingsObserver, UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.System.getUriFor(
Settings.System.SCREEN_BRIGHTNESS_MODE),
false, mSettingsObserver, UserHandle.USER_ALL);
// Go.
readConfigurationLocked();
updateSettingsLocked();
mDirty |= DIRTY_BATTERY_STATE;
updatePowerStateLocked();
//HISILICON add begin
//framework add doInitSh()
new DelayTask().start();
//HISILICON add end
}
}
创建SystemSensorManager对象,用于和SensorService交互。SensorService是一个native的Service,也存在于SystemServer进程中,它管理着Android上各种传感设备。创建Notifer对象,用于广播系统中和power相关的变化,如屏幕的关闭和打开等。创建WirelessChargerDetector用于无线充电检测的传感器。注册Observer监听系统设置的变化。在Android设置模块中,很多设置项都和PMS有关,如屏幕亮度、自动关闭屏幕时间、能否启动屏保等。监听其它模块广播的Intent。PMS需要关注系统的变化,这里注册很多系统广播接收器。如系统启动完成、屏保启动和关闭、用户切换、Dock插拔等。
1.3 报告用户活动–userActivity
PowerManager是PowerManagerService的代理类,它提供了一些让用户进程可以和PMS交互,下面来分析这些接口的实现来进一步了解PMS的工作。
接口userActivity用于用户进程向PMS报告用户影响系统休眠的活动,例如:用户点击屏幕时,系统会调用该方法来告诉PMS用户点击的时间,这样PMS将更新内部保存的时间值,从而推迟系统休眠的时间。
//frameworks/base/core/java/android/os/PowerManager.java
/**
* Notifies the power manager that user activity happened.
* <p>
* Resets the auto-off timer and brightens the screen if the device
* is not asleep. This is what happens normally when a key or the touch
* screen is pressed or when some other user activity occurs.
* This method does not wake up the device if it has been put to sleep.
* </p><p>
* Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
* </p>
*
* @param when The time of the user activity, in the {@link SystemClock#uptimeMillis()}
* time base. This timestamp is used to correctly order the user activity request with
* other power management functions. It should be set
* to the timestamp of the input event that caused the user activity.
* @param noChangeLights If true, does not cause the keyboard backlight to turn on
* because of this event. This is set when the power key is pressed.
* We want the device to stay on while the button is down, but we're about
* to turn off the screen so we don't want the keyboard backlight to turn on again.
* Otherwise the lights flash on and then off and it looks weird.
*
* @see #wakeUp
* @see #goToSleep
*/
public void userActivity(long when, boolean noChangeLights) {
try {
mService.userActivity(when, USER_ACTIVITY_EVENT_OTHER,
noChangeLights ? USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS : 0);
} catch (RemoteException e) {
}
}
mService通过Binder连接PMS中的userActivity,再来看PMS中userActivity的实现:
//frameworks/base/services/java/com/android/server/power/PowerManagerService.java
@Override // Binder call
public void userActivity(long eventTime, int event, int flags) {
final long now = SystemClock.uptimeMillis();
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER)
!= PackageManager.PERMISSION_GRANTED) {
// Once upon a time applications could call userActivity().
// Now we require the DEVICE_POWER permission. Log a warning and ignore the
// request instead of throwing a SecurityException so we don't break old apps.
synchronized (mLock) {
if (now >= mLastWarningAboutUserActivityPermission + (5 * 60 * 1000)) {
mLastWarningAboutUserActivityPermission = now;
Slog.w(TAG, "Ignoring call to PowerManager.userActivity() because the "
+ "caller does not have DEVICE_POWER permission. "
+ "Please fix your app! "
+ " pid=" + Binder.getCallingPid()
+ " uid=" + Binder.getCallingUid());
}
}
return;
}
if (eventTime > SystemClock.uptimeMillis()) {
throw new IllegalArgumentException("event time must not be in the future");
}
final int uid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity();
try {
userActivityInternal(eventTime, event, flags, uid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
userActivity首先检查调用者的Permission等,然后通过调用内部的userActivityInternal来完成工作:
private void userActivityInternal(long eventTime, int event, int flags, int uid) {
synchronized (mLock) {
if (userActivityNoUpdateLocked(eventTime, event, flags, uid)) {
updatePowerStateLocked();
}
}
}
userActivityInternal先调用userActivityNoUpdateLocked,然后再调用updatePowerStateLocked。userActivityNoUpdateLocked只是把参数保存到内部变量,并不采取任何动作,而PMS中核心方法是updatePowerStateLocked。
private boolean userActivityNoUpdateLocked(long eventTime, int event, int flags, int uid) {
if (DEBUG_SPEW) {
Slog.d(TAG, "userActivityNoUpdateLocked: eventTime=" + eventTime
+ ", event=" + event + ", flags=0x" + Integer.toHexString(flags)
+ ", uid=" + uid);
}
if (eventTime < mLastSleepTime || eventTime < mLastWakeTime
|| mWakefulness == WAKEFULNESS_ASLEEP || !mBootCompleted || !mSystemReady) {
return false;
}
mNotifier.onUserActivity(event, uid); //发出通知
if ((flags & PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS) != 0) {
if (eventTime > mLastUserActivityTimeNoChangeLights
&& eventTime > mLastUserActivityTime) {
mLastUserActivityTimeNoChangeLights = eventTime;
mDirty |= DIRTY_USER_ACTIVITY;
return true;
}
} else {
if (eventTime > mLastUserActivityTime) {
mLastUserActivityTime = eventTime;
mDirty |= DIRTY_USER_ACTIVITY;
return true;
}
}
return false;
}
userActivityNoUpdateLocked主要工作是更新几个内部变量。其中mLastUserActivityTime和mLastUserActivityTimeNoChangeLights用来记录调用userActivity的时间,mDirty表示指示电源状态的哪些部分已更改且需要重新计算的位域,用来记录用户的操作类型,这些变量在updatePow中将会作为示范执行睡眠或唤醒操作的依据。
1.4 强制系统进入休眠模式–gotoSleep接口
gotoSleep用来强制系统进入休眠模式。通常当系统一段时间无人操作后,系统将调用gotoSleep来进入休眠模式。其PowerManager中接口:
/**
* Forces the device to go to sleep.
* <p>
* Overrides all the wake locks that are held.
* This is what happens when the power key is pressed to turn off the screen.
* </p><p>
* Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
* </p>
*
* @param time The time when the request to go to sleep was issued, in the
* {@link SystemClock#uptimeMillis()} time base. This timestamp is used to correctly
* order the go to sleep request with other power management functions. It should be set
* to the timestamp of the input event that caused the request to go to sleep.
*
* @see #userActivity
* @see #wakeUp
*/
public void goToSleep(long time) {
try {
mService.goToSleep(time, GO_TO_SLEEP_REASON_USER);
} catch (RemoteException e) {
}
}
然后调用到PMS中的goToSleep:
@Override // Binder call
public void goToSleep(long eventTime, int reason) {
String onoff = SystemProperties.get("persist.suspend.onoff","on");
if (!"on".equals(onoff) || "off".equals(onoff))
return ;
if (eventTime > SystemClock.uptimeMillis()) {
throw new IllegalArgumentException("event time must not be in the future");
}
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
final long ident = Binder.clearCallingIdentity();
try {
goToSleepInternal(eventTime, reason);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
PMS的gotoSleep主要是调用内部方法gotoSleepInternal来完成其功能:
private void goToSleepInternal(long eventTime, int reason) {
mhisys.adjustDevState("/proc/inputblock/status","1");
mDisplay.setHDMIClose();
mDisplay.setOutputEnable(1,0);
String suspendType = SystemProperties.get("persist.suspend.mode", "deep_restart");
if (suspendType.equals("deep_launcher")) {
Slog.i(TAG, "goToSleepInternal deep_launcher start");
Intent home = new Intent(Intent.ACTION_MAIN);
home.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
home.addCategory(Intent.CATEGORY_HOME);
mContext.startActivity(home);
SystemClock.sleep(1000);
Slog.i(TAG, "goToSleepInternal deep_launcher end");
}
synchronized (mLock) {
if (goToSleepNoUpdateLocked(eventTime, reason)) {
updatePowerStateLocked();
}
}
}
goToSleepInternal结构与userActivity类似,都是先调用另一个内部方法,然后再调用updatePowerStateLocked。先看goToSleepNoUpdateLocked:
@SuppressWarnings("deprecation")
private boolean goToSleepNoUpdateLocked(long eventTime, int reason) {
if (DEBUG_SPEW) {
Slog.d(TAG, "goToSleepNoUpdateLocked: eventTime=" + eventTime + ", reason=" + reason);
}
if (eventTime < mLastWakeTime || mWakefulness == WAKEFULNESS_ASLEEP
|| !mBootCompleted || !mSystemReady) {
return false;
}
switch (reason) {
case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN:
Slog.i(TAG, "Going to sleep due to device administration policy...");
break;
case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT:
Slog.i(TAG, "Going to sleep due to screen timeout...");
//break;
//return false;
if (!mTimeoutShow) {
mPowerTime = eventTime;
showSuspendDialog();
} else {
Slog.i(TAG, "suspending...");
}
return false;
//break;
default:
Slog.i(TAG, "Going to sleep by user request...");
reason = PowerManager.GO_TO_SLEEP_REASON_USER;
break;
}
sendPendingNotificationsLocked();
mNotifier.onGoToSleepStarted(reason);
mSendGoToSleepFinishedNotificationWhenReady = true;
mLastSleepTime = eventTime;
mDirty |= DIRTY_WAKEFULNESS;
mWakefulness = WAKEFULNESS_ASLEEP;
// Report the number of wake locks that will be cleared by going to sleep.
int numWakeLocksCleared = 0;
final int numWakeLocks = mWakeLocks.size();
for (int i = 0; i < numWakeLocks; i++) {
final WakeLock wakeLock = mWakeLocks.get(i);
switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
case PowerManager.FULL_WAKE_LOCK:
case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
case PowerManager.SCREEN_DIM_WAKE_LOCK:
numWakeLocksCleared += 1;
break;
}
}
EventLog.writeEvent(EventLogTags.POWER_SLEEP_REQUESTED, numWakeLocksCleared);
return true;
}
goToSleepNoUpdateLocked只是发送了将要休眠的通知,然后修改成员变量mDirty、mLastSleepTime、mWakefulness。更多的工作还是在updatePowerStateLocked中完成。
2 控制系统休眠的机制
Android的休眠和唤醒主要是基于WakeLock机制。WakeLock是一种上锁机制,只要有进程得了WakeLock锁,系统就不会进入休眠。例如:在下载文件或播放歌曲时,即使睡眠时间到了系统也不会进行休眠。WakeLock可以设置超时,超时到了会自动解锁。
应用在使用WakeLock功能前,需要先使用newWakeLock()接口创建一个WakeLock类的对象,然后通过它的acquire()方法禁止系统休眠,应用完成工作后应该调用release()方法来恢复休眠机制,否则系统将无法休眠,直到耗光电量。
PowerManager中的接口实现:
public void acquire() {
synchronized (mToken) {
acquireLocked();
}
}
/**
* Acquires the wake lock with a timeout.
* <p>
* Ensures that the device is on at the level requested when
* the wake lock was created. The lock will be released after the given timeout
* expires.
* </p>
*
* @param timeout The timeout after which to release the wake lock, in milliseconds.
*/
public void acquire(long timeout) {
synchronized (mToken) {
acquireLocked();
mHandler.postDelayed(mReleaser, timeout);
}
}
private void acquireLocked() {
if (!mRefCounted || mCount++ == 0) {
// Do this even if the wake lock is already thought to be held (mHeld == true)
// because non-reference counted wake locks are not always properly released.
// For example, the keyguard's wake lock might be forcibly released by the
// power manager without the keyguard knowing. A subsequent call to acquire
// should immediately acquire the wake lock once again despite never having
// been explicitly released by the keyguard.
mHandler.removeCallbacks(mReleaser);
try {
mService.acquireWakeLock(mToken, mFlags, mTag, mPackageName, mWorkSource);
} catch (RemoteException e) {
}
mHeld = true;
}
}
/**
* Releases the wake lock.
* <p>
* This method releases your claim to the CPU or screen being on.
* The screen may turn off shortly after you release the wake lock, or it may
* not if there are other wake locks still held.
* </p>
*/
public void release() {
release(0);
}
/**
* Releases the wake lock with flags to modify the release behavior.
* <p>
* This method releases your claim to the CPU or screen being on.
* The screen may turn off shortly after you release the wake lock, or it may
* not if there are other wake locks still held.
* </p>
*
* @param flags Combination of flag values to modify the release behavior.
* Currently only {@link #WAIT_FOR_PROXIMITY_NEGATIVE} is supported.
*
* {@hide}
*/
public void release(int flags) {
synchronized (mToken) {
if (!mRefCounted || --mCount == 0) {
mHandler.removeCallbacks(mReleaser);
if (mHeld) {
try {
mService.releaseWakeLock(mToken, flags);
} catch (RemoteException e) {
}
mHeld = false;
}
}
if (mCount < 0) {
throw new RuntimeException("WakeLock under-locked " + mTag);
}
}
}
2.1 PMS中WakeLock相关接口
WakeLock类中实现了acquire()和release()方法实际上是调用PMS的acquireWakeLock()和releaseWakeLock()方法。
@Override // Binder call
public void acquireWakeLock(IBinder lock, int flags, String tag, String packageName,
WorkSource ws) {
if (lock == null) {
throw new IllegalArgumentException("lock must not be null");
}
if (packageName == null) {
throw new IllegalArgumentException("packageName must not be null");
}
PowerManager.validateWakeLockParameters(flags, tag);
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
if (ws != null && ws.size() != 0) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.UPDATE_DEVICE_STATS, null);
} else {
ws = null;
}
final int uid = Binder.getCallingUid();
final int pid = Binder.getCallingPid();
final long ident = Binder.clearCallingIdentity();
try {
acquireWakeLockInternal(lock, flags, tag, packageName, ws, uid, pid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
acquireWakeLock接口检查完权限后,调用了其内部的acquireWakeLockInternal方法:
private void acquireWakeLockInternal(IBinder lock, int flags, String tag, String packageName,
WorkSource ws, int uid, int pid) {
synchronized (mLock) {
if (DEBUG_SPEW) {
Slog.d(TAG, "acquireWakeLockInternal: lock=" + Objects.hashCode(lock)
+ ", flags=0x" + Integer.toHexString(flags)
+ ", tag=\"" + tag + "\", ws=" + ws + ", uid=" + uid + ", pid=" + pid);
}
WakeLock wakeLock;
int index = findWakeLockIndexLocked(lock); //检查这个lock是否已经存在
if (index >= 0) { //lock已经存在
wakeLock = mWakeLocks.get(index);
if (!wakeLock.hasSameProperties(flags, tag, ws, uid, pid)) {
// Update existing wake lock. This shouldn't happen but is harmless.
notifyWakeLockReleasedLocked(wakeLock);
wakeLock.updateProperties(flags, tag, packageName, ws, uid, pid);
notifyWakeLockAcquiredLocked(wakeLock);
}
} else { //不存在,则创建新的WakeLock对象
wakeLock = new WakeLock(lock, flags, tag, packageName, ws, uid, pid);
try {
lock.linkToDeath(wakeLock, 0);
} catch (RemoteException ex) {
throw new IllegalArgumentException("Wake lock is already dead.");
}
notifyWakeLockAcquiredLocked(wakeLock);
mWakeLocks.add(wakeLock); //将新建的WakeLock加入到mWakeLocks
}
applyWakeLockFlagsOnAcquireLocked(wakeLock);
mDirty |= DIRTY_WAKE_LOCKS;
updatePowerStateLocked();
}
}
acquireWakeLockInternal主要工作是创建WakeLock对象并加入到mWakeLocks列表中,这个列表包含了系统中所有的WakeLock对象。
但是如果mWakeLocks列表中已经存在具有相同token的WakeLock对象,则只更新其属性值,不会再创建对象,这个token是用户进程调用gotoSleep接口时的参数:用户进程中的WakeLock对象。
创建或者更新WakeLock对象后,接下来调用applyWakeLockFlagsOnAcquireLocked:
private void applyWakeLockFlagsOnAcquireLocked(WakeLock wakeLock) {
if ((wakeLock.mFlags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0 && isScreenLock(wakeLock)) {
wakeUpNoUpdateLocked(SystemClock.uptimeMillis());
}
}
这个方法只是调用了wakeUpNoUpdateLocked方法:
private boolean wakeUpNoUpdateLocked(long eventTime) {
//framework if PowerKey was locked, do nothing
if (mPowerKeyLocked) {
return false;
}
if (DEBUG_SPEW) {
Slog.d(TAG, "wakeUpNoUpdateLocked: eventTime=" + eventTime);
}
if (eventTime < mLastSleepTime || mWakefulness == WAKEFULNESS_AWAKE
|| !mBootCompleted || !mSystemReady) {
return false;
}
switch (mWakefulness) {
case WAKEFULNESS_ASLEEP:
Slog.i(TAG, "Waking up from sleep...");
sendPendingNotificationsLocked();
mNotifier.onWakeUpStarted();
mSendWakeUpFinishedNotificationWhenReady = true;
break;
case WAKEFULNESS_DREAMING:
Slog.i(TAG, "Waking up from dream...");
break;
case WAKEFULNESS_NAPPING:
Slog.i(TAG, "Waking up from nap...");
break;
}
mLastWakeTime = eventTime;
mWakefulness = WAKEFULNESS_AWAKE;
mDirty |= DIRTY_WAKEFULNESS;
userActivityNoUpdateLocked(
eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
return true;
}
wakeUpNoUpdateLocked首先调用了 mNotifier.onWakeUpStarted(),然后修改成员变量的值,最后调用userActivityNoUpdateLocked,前面介绍过,它在这里相当于有更新了变量mLastUserActivityTime的值。
再来看releaseWakeLock:
@Override // Binder call
public void releaseWakeLock(IBinder lock, int flags) {
if (lock == null) {
throw new IllegalArgumentException("lock must not be null");
}
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
final long ident = Binder.clearCallingIdentity();
try {
releaseWakeLockInternal(lock, flags);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
同样,PMS的releaseWakeLock接口,也只是调用PMS的releaseWakeLockInternal:
private void releaseWakeLockInternal(IBinder lock, int flags) {
synchronized (mLock) {
int index = findWakeLockIndexLocked(lock);
if (index < 0) {
if (DEBUG_SPEW) {
Slog.d(TAG, "releaseWakeLockInternal: lock=" + Objects.hashCode(lock)
+ " [not found], flags=0x" + Integer.toHexString(flags));
}
return;
}
WakeLock wakeLock = mWakeLocks.get(index);
if (DEBUG_SPEW) {
Slog.d(TAG, "releaseWakeLockInternal: lock=" + Objects.hashCode(lock)
+ " [" + wakeLock.mTag + "], flags=0x" + Integer.toHexString(flags));
}
mWakeLocks.remove(index);
notifyWakeLockReleasedLocked(wakeLock);
wakeLock.mLock.unlinkToDeath(wakeLock, 0);
if ((flags & PowerManager.WAIT_FOR_PROXIMITY_NEGATIVE) != 0) {
mRequestWaitForNegativeProximity = true;
}
applyWakeLockFlagsOnReleaseLocked(wakeLock);
mDirty |= DIRTY_WAKE_LOCKS;
updatePowerStateLocked();
}
}
releaseWakeLockInternal首先查找lock在mWakeLocks中的index,然后从mWakeLocks中得到WakeLock对象,然后从mWakeLocks中移除该WakeLock对象,并发出通知,接着调用applyWakeLockFlagsOnReleaseLocked方法:
private void applyWakeLockFlagsOnReleaseLocked(WakeLock wakeLock) {
if ((wakeLock.mFlags & PowerManager.ON_AFTER_RELEASE) != 0
&& isScreenLock(wakeLock)) {
userActivityNoUpdateLocked(SystemClock.uptimeMillis(),
PowerManager.USER_ACTIVITY_EVENT_OTHER,
PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS,
wakeLock.mOwnerUid);
}
}
该方法只是调用了userActivityNoUpdateLocked来把mLastUserActivityTime更新为当前时间,这样当休眠时间到时,系统就可以休眠。最后mDirty被设置成 DIRTY_WAKE_LOCKS,然后调用updatePowerStateLocked。
2.2 WakeLock的native层实现
在PMS的构造函数中mWakeLockSuspendBlocker和mDisplaySuspendBlocker都是调用createSuspendBlockerLocked来创建的,只是参数不一样,一个是PowerManagerService.WakeLocks,一个是PowerManagerService.Display。
mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks");
mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display");
mDisplaySuspendBlocker.acquire();
createSuspendBlockerLocked的实现:
private SuspendBlocker createSuspendBlockerLocked(String name) {
SuspendBlocker suspendBlocker = new SuspendBlockerImpl(name);
mSuspendBlockers.add(suspendBlocker);
return suspendBlocker;
}
createSuspendBlockerLocked中创建了一个SuspendBlockerImpl对象并返回,因此mWakeLockSuspendBlocker和mDisplaySuspendBlocker实际类型应该是SuspendBlockerImpl,在看它的acquire()和release()方法:
@Override
public void acquire() {
synchronized (this) {
mReferenceCount += 1;
if (mReferenceCount == 1) {
if (DEBUG_SPEW) {
Slog.d(TAG, "Acquiring suspend blocker \"" + mName + "\".");
}
nativeAcquireSuspendBlocker(mName);
}
}
}
@Override
public void release() {
synchronized (this) {
mReferenceCount -= 1;
if (mReferenceCount == 0) {
if (DEBUG_SPEW) {
Slog.d(TAG, "Releasing suspend blocker \"" + mName + "\".");
}
nativeReleaseSuspendBlocker(mName);
} else if (mReferenceCount < 0) {
Log.wtf(TAG, "Suspend blocker \"" + mName
+ "\" was released without being acquired!", new Throwable());
mReferenceCount = 0;
}
}
}
SuspendBlockerImpl类中维护了一个计数器,调用acquire时计数器加1。当计数器的值为1时,调用底层的nativeAcquireSuspendBlocker方法。调用release时计数器减1,当计数器值减为0,调用nativeReleaseSuspendBlocker,对应的native层函数为:
static void nativeAcquireSuspendBlocker(JNIEnv *env, jclass clazz, jstring nameStr) {
ScopedUtfChars name(env, nameStr);
acquire_wake_lock(PARTIAL_WAKE_LOCK, name.c_str());
}
static void nativeReleaseSuspendBlocker(JNIEnv *env, jclass clazz, jstring nameStr) {
ScopedUtfChars name(env, nameStr);
release_wake_lock(name.c_str());
}
其中定义:
enum {
PARTIAL_WAKE_LOCK = 1, // the cpu stays on, but the screen is off
FULL_WAKE_LOCK = 2 // the screen is also on
};
这两个native层的函数又分别调用了acquire_wake_lock和release_wake_lock:
//hardware/libhardware_legacy/power/power.c
int acquire_wake_lock(int lock, const char* id)
{
initialize_fds();
// ALOGI("acquire_wake_lock lock=%d id='%s'\n", lock, id);
if (g_error) return g_error;
int fd;
if (lock == PARTIAL_WAKE_LOCK) {
fd = g_fds[ACQUIRE_PARTIAL_WAKE_LOCK];
}
else {
return EINVAL;
}
return write(fd, id, strlen(id));
}
int release_wake_lock(const char* id)
{
initialize_fds();
// ALOGI("release_wake_lock id='%s'\n", id);
if (g_error) return g_error;
ssize_t len = write(g_fds[RELEASE_WAKE_LOCK], id, strlen(id));
return len >= 0;
}
不管acquire_wake_lock还是release_wake_lock,都是通过向不同的驱动文件写数据来实现其功能,这里的数据就是前面的构造方法中撞见变量时传递的参数PowerManagerService.WakeLocks和PowerManagerService.Display。那么acquire()和release()中使用的文件设备句柄是如何创建的,看看initialize_fds:
static inline void initialize_fds(void)
{
if (g_initialized == 0) {
if(open_file_descriptors(NEW_PATHS) < 0)
open_file_descriptors(OLD_PATHS);
g_initialized = 1;
}
}
initialize_fds就是打开NEW_PATHS或者OLD_PATHS数组中的设备文件,数组定义为:
const char * const OLD_PATHS[] = {
"/sys/android_power/acquire_partial_wake_lock",
"/sys/android_power/release_wake_lock",
};
const char * const NEW_PATHS[] = {
"/sys/power/wake_lock",
"/sys/power/wake_unlock",
};
因此,Android实现防止系统休眠的功能是通过向设备文件"/sys/power/wake_lock"写数据来完成的,如果写的是”PowerManagerService.WakeLocks“,系统将不能进入休眠状态,但是屏幕会关闭,如果写的是”PowerManagerService.Display“,则连屏幕也不会关闭。如果系统要恢复休眠,再向设备文件”/sys/power/wake_unlock“中写入相同的字符串就可以了。
2.3 理解updatePowerStateLocked
updatePowerStateLocked是PMS的核心,前面分析的接口调用都只是在更新服务中的某些成员变量值,最后都需要调用updatePowerStateLocked方法:
/**
* Updates the global power state based on dirty bits recorded in mDirty.
*
* This is the main function that performs power state transitions.
* We centralize them here so that we can recompute the power state completely
* each time something important changes, and ensure that we do it the same
* way each time. The point is to gather all of the transition logic here.
*/
private void updatePowerStateLocked() {
if (!mSystemReady || mDirty == 0) {
return;
}
// Phase 0: Basic state updates. 更新基本状态
updateIsPoweredLocked(mDirty); //更新mIsPowered、mPlugType、mBatteryLevel
updateStayOnLocked(mDirty); //更新mStayOn
// Phase 1: Update wakefulness. 更新wakefulness
// Loop because the wake lock and user activity computations are influenced
// by changes in wakefulness.
final long now = SystemClock.uptimeMillis();
int dirtyPhase2 = 0;
for (;;) {
int dirtyPhase1 = mDirty;
dirtyPhase2 |= dirtyPhase1;
mDirty = 0;
updateWakeLockSummaryLocked(dirtyPhase1);
updateUserActivitySummaryLocked(now, dirtyPhase1);
if (!updateWakefulnessLocked(dirtyPhase1)) {
break;
}
}
// Phase 2: Update dreams and display power state.
updateDreamLocked(dirtyPhase2); //更新屏保状态
updateDisplayPowerStateLocked(dirtyPhase2); //更新显示设备的状态
// Phase 3: Send notifications, if needed.
if (mDisplayReady) {
sendPendingNotificationsLocked(); //发送通知
}
// Phase 4: Update suspend blocker.
// Because we might release the last suspend blocker here, we need to make sure
// we finished everything else first!
updateSuspendBlockerLocked();
}
2.3.1 基本状态更新
(1)updatePowerStateLocked首先调用updateIsPoweredLocked,该方法主要是调用BatteryManager接口来更新几个成员变量的值:
/**
* Updates the value of mIsPowered.
* Sets DIRTY_IS_POWERED if a change occurred.
*/
private void updateIsPoweredLocked(int dirty) {
if ((dirty & DIRTY_BATTERY_STATE) != 0) {
final boolean wasPowered = mIsPowered;
final int oldPlugType = mPlugType;
mIsPowered = mBatteryService.isPowered(BatteryManager.BATTERY_PLUGGED_ANY);
mPlugType = mBatteryService.getPlugType();
mBatteryLevel = mBatteryService.getBatteryLevel();
if (DEBUG) {
Slog.d(TAG, "updateIsPoweredLocked: wasPowered=" + wasPowered
+ ", mIsPowered=" + mIsPowered
+ ", oldPlugType=" + oldPlugType
+ ", mPlugType=" + mPlugType
+ ", mBatteryLevel=" + mBatteryLevel);
}
if (wasPowered != mIsPowered || oldPlugType != mPlugType) {
mDirty |= DIRTY_IS_POWERED;
// Update wireless dock detection state.
final boolean dockedOnWirelessCharger = mWirelessChargerDetector.update(
mIsPowered, mPlugType, mBatteryLevel);
// Treat plugging and unplugging the devices as a user activity.
// Users find it disconcerting when they plug or unplug the device
// and it shuts off right away.
// Some devices also wake the device when plugged or unplugged because
// they don't have a charging LED.
final long now = SystemClock.uptimeMillis();
if (shouldWakeUpWhenPluggedOrUnpluggedLocked(wasPowered, oldPlugType,
dockedOnWirelessCharger)) {
wakeUpNoUpdateLocked(now);
}
userActivityNoUpdateLocked(
now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
// Tell the notifier whether wireless charging has started so that
// it can provide feedback to the user.
if (dockedOnWirelessCharger) {
mNotifier.onWirelessChargingStarted();
}
}
}
}
其中mIsPowered表示是否在充电、mPlugType表示充电的类型、mBatteryLevel表示当前电池电量的等级。
(2)updateStayOnLocked来更新变量mStayOn的值,mStayOn如果为true,屏幕将常亮不灭。在Setting中可以设置充电时屏幕常亮,如果Setting中设置了该选项,updateStayOnLocked函数中如果检测到正在充电,会将mStayOn设为true。
/**
* Updates the value of mStayOn.
* Sets DIRTY_STAY_ON if a change occurred.
*/
private void updateStayOnLocked(int dirty) {
if ((dirty & (DIRTY_BATTERY_STATE | DIRTY_SETTINGS)) != 0) {
final boolean wasStayOn = mStayOn;
if (mStayOnWhilePluggedInSetting != 0
&& !isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked()) {
mStayOn = mBatteryService.isPowered(mStayOnWhilePluggedInSetting);
} else {
mStayOn = false;
}
if (mStayOn != wasStayOn) {
mDirty |= DIRTY_STAY_ON;
}
}
}
2.3.2 更新wakefulness
(3)接下来是一个无限for循环,注意,其实这个无限循环最多两次就结束了。之所以使用循环,是因为唤醒锁和用户活动的计算是通过wakefulness的变化进行的。先看updateWakeLockSummaryLocked:
/**
* Updates the value of mWakeLockSummary to summarize the state of all active wake locks.
* Note that most wake-locks are ignored when the system is asleep.
*
* This function must have no other side-effects.
*/
@SuppressWarnings("deprecation")
private void updateWakeLockSummaryLocked(int dirty) {
if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_WAKEFULNESS)) != 0) {
mWakeLockSummary = 0;
final int numWakeLocks = mWakeLocks.size();
for (int i = 0; i < numWakeLocks; i++) {
final WakeLock wakeLock = mWakeLocks.get(i);
switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
case PowerManager.PARTIAL_WAKE_LOCK:
/*patch hisi support smart_suspend
if(SystemProperties.get("persist.suspend.mode", "deep_restart").equals("deep_resume")) {
mWakeLockSummary |= WAKE_LOCK_CPU;
}
break;*/
case PowerManager.SUSPEND_WAKE_LOCK:
/*patch hisi support smart_suspend
if(SystemProperties.get("persist.suspend.mode", "deep_restart").equals("deep_launcher") |
SystemProperties.get("persist.suspend.mode", "deep_restart").equals("deep_restart")) {*/
mWakeLockSummary |= WAKE_LOCK_CPU;
break;
case PowerManager.FULL_WAKE_LOCK:
if (mWakefulness != WAKEFULNESS_ASLEEP) {
mWakeLockSummary |= WAKE_LOCK_CPU
| WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_BUTTON_BRIGHT;
if (mWakefulness == WAKEFULNESS_AWAKE) {
mWakeLockSummary |= WAKE_LOCK_STAY_AWAKE;
}
}
break;
case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
if (mWakefulness != WAKEFULNESS_ASLEEP) {
mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_SCREEN_BRIGHT;
if (mWakefulness == WAKEFULNESS_AWAKE) {
mWakeLockSummary |= WAKE_LOCK_STAY_AWAKE;
}
}
break;
case PowerManager.SCREEN_DIM_WAKE_LOCK:
if (mWakefulness != WAKEFULNESS_ASLEEP) {
mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_SCREEN_DIM;
if (mWakefulness == WAKEFULNESS_AWAKE) {
mWakeLockSummary |= WAKE_LOCK_STAY_AWAKE;
}
}
break;
case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
if (mWakefulness != WAKEFULNESS_ASLEEP) {
mWakeLockSummary |= WAKE_LOCK_PROXIMITY_SCREEN_OFF;
}
break;
}
}
if (DEBUG_SPEW) {
Slog.d(TAG, "updateWakeLockSummaryLocked: mWakefulness="
+ wakefulnessToString(mWakefulness)
+ ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary));
}
}
}
updateWakeLockSummaryLocked主要作用是根据PMS中所有的WakeLock对象的类型,计算一个最终的类型集合,并保存在变量mWakeLockSummary中。不管系统一个创建了多少个WakeLock对象,一个就足以阻止系统休眠,因此,这里把所有的WakeLock对象的状态总结后放到一个变量中。应用创建WakeLock对象时,会指定对象的类型,这个类型将作为参数传到PMS中,WakeLock的类型:
- PARTIAL_WAKE_LOCK:只保持CPU运行,屏幕背光和键盘背光关闭
- FULL_WAKE_LOCK:CPU、屏幕背光和键盘背光都不关闭
- SUSPEND_WAKE_LOCK
- SCREEN_BRIGHT_WAKE_LOCK:屏幕背光不关闭,但键盘背光关闭
- SCREEN_DIM_WAKE_LOCK:屏幕背光不关闭,键盘背光关闭,但屏幕背光可以变暗
- PROXIMITY_SCREEN_OFF_WAKE_LOCK:打开距离传感器控制屏幕开关的功能,如果应用持有这个类型的WakeLock,当距离传感器被遮挡时,屏幕将被关闭。在打电话时常用这个。
这些类型可以混合使用
(4)循环的第二个是updateUserActivitySummaryLocked:
/**
* Updates the value of mUserActivitySummary to summarize the user requested
* state of the system such as whether the screen should be bright or dim.
* Note that user activity is ignored when the system is asleep.
*
* This function must have no other side-effects.
*/
private void updateUserActivitySummaryLocked(long now, int dirty) {
// Update the status of the user activity timeout timer.
if ((dirty & (DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS | DIRTY_SETTINGS)) != 0) {
mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT);
long nextTimeout = 0;
if (mWakefulness != WAKEFULNESS_ASLEEP) {
final int screenOffTimeout = getScreenOffTimeoutLocked();
final int screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);
mUserActivitySummary = 0;
if (mLastUserActivityTime >= mLastWakeTime) {
nextTimeout = mLastUserActivityTime
+ screenOffTimeout - screenDimDuration;
if (now < nextTimeout) {
mUserActivitySummary |= USER_ACTIVITY_SCREEN_BRIGHT;
} else {
nextTimeout = mLastUserActivityTime + screenOffTimeout;
if (now < nextTimeout) {
mUserActivitySummary |= USER_ACTIVITY_SCREEN_DIM;
}
}
}
if (mUserActivitySummary == 0
&& mLastUserActivityTimeNoChangeLights >= mLastWakeTime) {
nextTimeout = mLastUserActivityTimeNoChangeLights + screenOffTimeout;
if (now < nextTimeout
&& mDisplayPowerRequest.screenState
!= DisplayPowerRequest.SCREEN_STATE_OFF) {
mUserActivitySummary = mDisplayPowerRequest.screenState
== DisplayPowerRequest.SCREEN_STATE_BRIGHT ?
USER_ACTIVITY_SCREEN_BRIGHT : USER_ACTIVITY_SCREEN_DIM;
}
}
if (mUserActivitySummary != 0) {
Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, nextTimeout);
}else{
mSendcast=true;
Slog.d(TAG, "###########################M9");
}
} else {
mUserActivitySummary = 0;
}
if (DEBUG_SPEW) {
Slog.d(TAG, "updateUserActivitySummaryLocked: mWakefulness="
+ wakefulnessToString(mWakefulness)
+ ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary)
+ ", nextTimeout=" + TimeUtils.formatUptime(nextTimeout));
}
}
}
这个方法根据最后一个调用userActivity的时间,计算现在是否可以将表示屏幕状态的变量mUserActivitySummary设置为USER_ACTIVITY_SCREEN_DIM(变暗)或者SCREEN_STATE_OFF(关闭)。如果时间还没到,则发送一个定时消息MSG_USER_ACTIVITY_TIMEOUT。当处理消息的时间到了之后,会在消息的处理方法handleUserActivityTimeout中重新调用updatePowerStateLocked:
/**
* Called when a user activity timeout has occurred.
* Simply indicates that something about user activity has changed so that the new
* state can be recomputed when the power state is updated.
*
* This function must have no other side-effects besides setting the dirty
* bit and calling update power state. Wakefulness transitions are handled elsewhere.
*/
private void handleUserActivityTimeout() { // runs on handler thread
synchronized (mLock) {
if (DEBUG_SPEW) {
Slog.d(TAG, "handleUserActivityTimeout");
}
mDirty |= DIRTY_USER_ACTIVITY;
updatePowerStateLocked();
}
}
再次调用updatePowerStateLocked时,会根据当前的状态重新计算mUserActivitySummary的值。
(5)循环中调用的第三个方法updateWakefulnessLocked,它是结束循环的关键。如果updateWakefulnessLocked返回true,表示PMS的状态发生了变化,将继续循环,然后重新调用前面的两个方法updateWakeLockSummaryLocked和updateUserActivitySummaryLocked来更新。而第二次调用updateWakefulnessLocked通常都会返回false,这样就跳出了循环。
/**
* Updates the wakefulness of the device.
*
* This is the function that decides whether the device should start napping
* based on the current wake locks and user activity state. It may modify mDirty
* if the wakefulness changes.
*
* Returns true if the wakefulness changed and we need to restart power state calculation.
*/
private boolean updateWakefulnessLocked(int dirty) {
boolean changed = false;
if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_BOOT_COMPLETED
| DIRTY_WAKEFULNESS | DIRTY_STAY_ON | DIRTY_PROXIMITY_POSITIVE
| DIRTY_DOCK_STATE)) != 0) {
if (mWakefulness == WAKEFULNESS_AWAKE && isItBedTimeYetLocked()) {
if (DEBUG_SPEW) {
Slog.d(TAG, "updateWakefulnessLocked: Bed time...");
}
final long time = SystemClock.uptimeMillis();
if(DIRTY_USER_ACTIVITY == dirty)
Slog.d(TAG, "SystemClock.uptimeMillis: "+time+" dirty: "+dirty);
if (shouldNapAtBedTimeLocked()) {
changed = napNoUpdateLocked(time);
} else {
changed = goToSleepNoUpdateLocked(time,
PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
}
}
}
return changed;
}
updateWakefulnessLocked首先判断dirty的值,如果是第一次调用,这个条件很容易满足。注意,第二个if语句的判断条件,它要求mWakefulness == WAKEFULNESS_AWAKE,并调用isItBedTimeYetLocked的返回值为true才继续执行,否则结束并返回false,当然返回false就会跳出循环。先假定mWakefulness == WAKEFULNESS_AWAKE(大多数情况如此),下面看isItBedTimeYetLocked什么情况返回true:
/**
* Returns true if the device should go to sleep now.
* Also used when exiting a dream to determine whether we should go back
* to being fully awake or else go to sleep for good.
*/
private boolean isItBedTimeYetLocked() {
return mBootCompleted && !isBeingKeptAwakeLocked();
}
isItBedTimeYetLocked判断了两个条件,(1)mBootCompleted,表示是否启动完成(启动没完成前不能休眠),这个变量启动后就是true了。(2)isBeingKeptAwakeLocked,如果系统目前不能休眠,这个方法将返回true,代码:
/**
* Returns true if the device is being kept awake by a wake lock, user activity
* or the stay on while powered setting. We also keep the phone awake when
* the proximity sensor returns a positive result so that the device does not
* lock while in a phone call. This function only controls whether the device
* will go to sleep or dream which is independent of whether it will be allowed
* to suspend.
*/
private boolean isBeingKeptAwakeLocked() {
return mStayOn
|| mProximityPositive
|| (mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) != 0
|| (mUserActivitySummary & (USER_ACTIVITY_SCREEN_BRIGHT
| USER_ACTIVITY_SCREEN_DIM)) != 0;
}
isBeingKeptAwakeLocked判断系统是否能睡眠的几个变量前面已经讲过,前面一些方法中更新这些变量就为了用在这里。
因此,isBeingKeptAwakeLocked只有在系统能够进入睡眠时才返回true。
回到updateWakefulnessLocked,假如系统能够睡眠,接下来将调用方法shouldNapAtBedTimeLocked,它检查系统有没有设置睡眠时间到时启动屏保。
/**
* Returns true if the device should automatically nap and start dreaming when the user
* activity timeout has expired and it's bedtime.
*/
private boolean shouldNapAtBedTimeLocked() {
return mDreamsActivateOnSleepSetting
|| (mDreamsActivateOnDockSetting
&& mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED);
}
如果设置了,将调用napNoUpdateLocked,没有则调用goToSleepNoUpdateLocked。
先看napNoUpdateLocked:
private boolean napNoUpdateLocked(long eventTime) {
if (DEBUG_SPEW) {
Slog.d(TAG, "napNoUpdateLocked: eventTime=" + eventTime);
}
if (eventTime < mLastWakeTime || mWakefulness != WAKEFULNESS_AWAKE
|| !mBootCompleted || !mSystemReady) {
return false;
}
Slog.i(TAG, "Nap time...");
mDirty |= DIRTY_WAKEFULNESS;
mWakefulness = WAKEFULNESS_NAPPING;
return true;
}
在napNoUpdateLocked中,如果if语句中4项中有一项为true,整个方法返回false,但是如果是循环第一次调用该方法,则4项正常情况下都是false,其实前面已经进行了类似的哦安短,如果成立就不会走到这里。这样执行的结果就是改变mDirty和mWakefulness,既然循环中第二次调用本方法,肯定会返回false,这样就结束了updatePowerStateLocke中的循环。
再来看goToSleepNoUpdateLocked:
@SuppressWarnings("deprecation")
private boolean goToSleepNoUpdateLocked(long eventTime, int reason) {
//HISILICON add begin
//framework lock PowerKey
mPowerKeyLocked = true;
new KeyLock().start();
//HISILICON add end
if (DEBUG_SPEW) {
Slog.d(TAG, "goToSleepNoUpdateLocked: eventTime=" + eventTime + ", reason=" + reason);
}
if (eventTime < mLastWakeTime || mWakefulness == WAKEFULNESS_ASLEEP
|| !mBootCompleted || !mSystemReady) {
return false;
}
switch (reason) {
case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN:
Slog.i(TAG, "Going to sleep due to device administration policy...");
break;
case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT:
Slog.i(TAG, "Going to sleep due to screen timeout...");
//break;
//return false;
if (!mTimeoutShow) {
mPowerTime = eventTime;
showSuspendDialog();
} else {
Slog.i(TAG, "suspending...");
}
return false;
//break;
default:
Slog.i(TAG, "Going to sleep by user request...");
reason = PowerManager.GO_TO_SLEEP_REASON_USER;
break;
}
sendPendingNotificationsLocked();
mNotifier.onGoToSleepStarted(reason);
mSendGoToSleepFinishedNotificationWhenReady = true;
mLastSleepTime = eventTime;
mDirty |= DIRTY_WAKEFULNESS;
mWakefulness = WAKEFULNESS_ASLEEP;
// Report the number of wake locks that will be cleared by going to sleep.
int numWakeLocksCleared = 0;
final int numWakeLocks = mWakeLocks.size();
for (int i = 0; i < numWakeLocks; i++) {
final WakeLock wakeLock = mWakeLocks.get(i);
switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
case PowerManager.FULL_WAKE_LOCK:
case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
case PowerManager.SCREEN_DIM_WAKE_LOCK:
numWakeLocksCleared += 1;
break;
}
}
EventLog.writeEvent(EventLogTags.POWER_SLEEP_REQUESTED, numWakeLocksCleared);
return true;
}
goToSleepNoUpdateLocked作用是通过设置变量mWakefulness,将系统的状态转变成WAKEFULNESS_ASLEEP。回到updatePowerStateLocked:
2.3.3 更新屏保和屏幕的状态、亮度
(6)结束循环后,updatePowerStateLocked又调用了updateDreamLocked来确定是否向Sandman发布消息以更新屏保状态。如果条件合适,这个方法中将启动屏保。
/**
* Determines whether to post a message to the sandman to update the dream state.
*/
private void updateDreamLocked(int dirty) {
if ((dirty & (DIRTY_WAKEFULNESS
| DIRTY_USER_ACTIVITY
| DIRTY_WAKE_LOCKS
| DIRTY_BOOT_COMPLETED
| DIRTY_SETTINGS
| DIRTY_IS_POWERED
| DIRTY_STAY_ON
| DIRTY_PROXIMITY_POSITIVE
| DIRTY_BATTERY_STATE)) != 0) {
scheduleSandmanLocked();
}
}
(7)然后调用updateDisplayPowerStateLocked,其主要作用是根据更新后的mUserActivitySummary来确定屏幕的状态和亮度,并设置到mDisplayPowerController中,2.4节再具体分析updateDisplayPowerStateLocked。
2.3.4 发送通知
if (mDisplayReady) {
sendPendingNotificationsLocked();
}
private void sendPendingNotificationsLocked() {
if (mSendWakeUpFinishedNotificationWhenReady) {
mSendWakeUpFinishedNotificationWhenReady = false;
mNotifier.onWakeUpFinished();
}
if (mSendGoToSleepFinishedNotificationWhenReady) {
mSendGoToSleepFinishedNotificationWhenReady = false;
mNotifier.onGoToSleepFinished();
}
}
2.3.5 更新suspend blocker
(8)接下来调用updateSuspendBlockerLocked:
/**
* Updates the suspend blocker that keeps the CPU alive.
*
* This function must have no other side-effects.
*/
private void updateSuspendBlockerLocked() {
final boolean needWakeLockSuspendBlocker = ((mWakeLockSummary & WAKE_LOCK_CPU) != 0);
final boolean needDisplaySuspendBlocker = needDisplaySuspendBlocker();
// First acquire suspend blockers if needed. 如果不能休眠,调用底层的wake_lock函数
if (needWakeLockSuspendBlocker && !mHoldingWakeLockSuspendBlocker) {
mWakeLockSuspendBlocker.acquire();
mHoldingWakeLockSuspendBlocker = true;
}
//如果需要保存屏幕常亮,调用底层的wake_lock函数
if (needDisplaySuspendBlocker && !mHoldingDisplaySuspendBlocker) {
mDisplaySuspendBlocker.acquire();
mHoldingDisplaySuspendBlocker = true;
}
// Then release suspend blockers if needed. 如果可以休眠,调用底层的解锁函数
if (!needWakeLockSuspendBlocker && mHoldingWakeLockSuspendBlocker) {
mWakeLockSuspendBlocker.release();
mHoldingWakeLockSuspendBlocker = false;
}
//如果不需要保存屏幕常亮,调用底层的解锁函数
if (!needDisplaySuspendBlocker && mHoldingDisplaySuspendBlocker) {
mDisplaySuspendBlocker.release();
mHoldingDisplaySuspendBlocker = false;
}
}
updateSuspendBlockerLocked首先根据变量mWakeLockSummary是否带有WAKE_LOCK_CPU标志,以及needDisplaySuspendBlocker返回值决定是否需要阻止CPU休眠或保持屏幕常亮,然后分别调用mWakeLockSuspendBlocker和mDisplaySuspendBlocker的acquire和release方法来完成CPU和屏幕的锁定和解锁操作。
前面所进行的所有计算和更新操作,最后都汇集到这里来决定是休眠还是更新。
最后来看needDisplaySuspendBlocker如何决定屏幕是否关闭:
/**
* Return true if we must keep a suspend blocker active on behalf of the display.
* We do so if the screen is on or is in transition between states.
*/
private boolean needDisplaySuspendBlocker() {
if (!mDisplayReady) {
return true; //如果显示设备没有准备好,不能关闭屏幕
}
if (mDisplayPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) {
// If we asked for the screen to be on but it is off due to the proximity
// sensor then we may suspend but only if the configuration allows it.
// On some hardware it may not be safe to suspend because the proximity
// sensor may not be correctly configured as a wake-up source.
//如果屏幕开着或者变暗的状态,而且距离传感器没有工作,不能关闭屏幕
if (!mDisplayPowerRequest.useProximitySensor || !mProximityPositive
|| !mSuspendWhenScreenOffDueToProximityConfig) {
return true;
}
}
return false;
}
needDisplaySuspendBlocker主要是根据屏幕的状态来决定,如果屏幕开着胡总恶化处于变暗状态时,距离传感器也没有工作,不能关闭屏幕。
2.4 管理显示设备
updatePowerStateLocked中调用updateDisplayPowerStateLocked:
/**
* Updates the display power state asynchronously.
* When the update is finished, mDisplayReady will be set to true. The display
* controller posts a message to tell us when the actual display power state
* has been updated so we come back here to double-check and finish up.
*
* This function recalculates the display power state each time.
*/
private void updateDisplayPowerStateLocked(int dirty) {
if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS
| DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED | DIRTY_BOOT_COMPLETED
| DIRTY_SETTINGS | DIRTY_SCREEN_ON_BLOCKER_RELEASED)) != 0) {
//根据服务当前的状态获取屏幕的新状态
int newScreenState = getDesiredScreenPowerStateLocked();
if (newScreenState != mDisplayPowerRequest.screenState) {
if (newScreenState == DisplayPowerRequest.SCREEN_STATE_OFF
&& mDisplayPowerRequest.screenState
!= DisplayPowerRequest.SCREEN_STATE_OFF) {
mLastScreenOffEventElapsedRealTime = SystemClock.elapsedRealtime();
}
mDisplayPowerRequest.screenState = newScreenState;
nativeSetPowerState(
newScreenState != DisplayPowerRequest.SCREEN_STATE_OFF,
newScreenState == DisplayPowerRequest.SCREEN_STATE_BRIGHT);
}
int screenBrightness = mScreenBrightnessSettingDefault;
float screenAutoBrightnessAdjustment = 0.0f;
//获取系统是否设置了屏幕亮度模式为自动变化
boolean autoBrightness = (mScreenBrightnessModeSetting ==
Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
//获取屏幕亮度值
if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)) {
//如果WindowManager设置的亮度有效,使用它设置的值
screenBrightness = mScreenBrightnessOverrideFromWindowManager;
autoBrightness = false;
} else if (isValidBrightness(mTemporaryScreenBrightnessSettingOverride)) {
//如果应用中临时设置的亮度有效,使用它设置的值
screenBrightness = mTemporaryScreenBrightnessSettingOverride;
} else if (isValidBrightness(mScreenBrightnessSetting)) {
//最后使用系统设置的值
screenBrightness = mScreenBrightnessSetting;
}
if (autoBrightness) {
//如果是自动调整亮度,如果应用中设置了临时自动亮度,使用它,否则使用系统的值
screenBrightness = mScreenBrightnessSettingDefault;
if (isValidAutoBrightnessAdjustment(
mTemporaryScreenAutoBrightnessAdjustmentSettingOverride)) {
screenAutoBrightnessAdjustment =
mTemporaryScreenAutoBrightnessAdjustmentSettingOverride;
} else if (isValidAutoBrightnessAdjustment(
mScreenAutoBrightnessAdjustmentSetting)) {
screenAutoBrightnessAdjustment = mScreenAutoBrightnessAdjustmentSetting;
}
}
//更新mDisplayPowerRequest对象的值
screenBrightness = Math.max(Math.min(screenBrightness,
mScreenBrightnessSettingMaximum), mScreenBrightnessSettingMinimum);
screenAutoBrightnessAdjustment = Math.max(Math.min(
screenAutoBrightnessAdjustment, 1.0f), -1.0f);
mDisplayPowerRequest.screenBrightness = screenBrightness;
mDisplayPowerRequest.screenAutoBrightnessAdjustment =
screenAutoBrightnessAdjustment;
mDisplayPowerRequest.useAutoBrightness = autoBrightness;
mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();
mDisplayPowerRequest.blockScreenOn = mScreenOnBlocker.isHeld();
mDisplayReady = mDisplayPowerController.requestPowerState(mDisplayPowerRequest,
mRequestWaitForNegativeProximity);
mRequestWaitForNegativeProximity = false;
if (DEBUG_SPEW) {
Slog.d(TAG, "updateScreenStateLocked: mDisplayReady=" + mDisplayReady
+ ", newScreenState=" + newScreenState
+ ", mWakefulness=" + mWakefulness
+ ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary)
+ ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary)
+ ", mBootCompleted=" + mBootCompleted);
}
}
}
updateDisplayPowerStateLocked主要是更新PMS中表示显示屏状态的变量mDisplayPowerRequest.screenState,以及重新确定屏幕的亮度。但是要注意结尾处调用的mDisplayPowerController.requestPowerState,这个方法返回值会赋值给mDisplayReady,上一节分析needDisplaySuspendBlocker时提到,如果mDisplayReady为false,屏幕是不会关闭的。
mDisplayPowerController的类型为DisplayPowerController,这个类用来管理显示设备的Power状态,主要功能是播放屏幕状态变化的动画,通过回调的方法和PMS进行交互。再来看requestPowerState:
/**
* Requests a new power state.
* The controller makes a copy of the provided object and then
* begins adjusting the power state to match what was requested.
*
* @param request The requested power state.
* @param waitForNegativeProximity If true, issues a request to wait for
* negative proximity before turning the screen back on, assuming the screen
* was turned off by the proximity sensor.
* @return True if display is ready, false if there are important changes that must
* be made asynchronously (such as turning the screen on), in which case the caller
* should grab a wake lock, watch for {@link Callbacks#onStateChanged()} then try
* the request again later until the state converges.
*/
public boolean requestPowerState(DisplayPowerRequest request,
boolean waitForNegativeProximity) {
if (DEBUG) {
Slog.d(TAG, "requestPowerState: "
+ request + ", waitForNegativeProximity=" + waitForNegativeProximity);
}
synchronized (mLock) {
boolean changed = false;
if (waitForNegativeProximity
&& !mPendingWaitForNegativeProximityLocked) {
//如果和近距离传感器相关的变量变化,则将changed设置为true
mPendingWaitForNegativeProximityLocked = true;
changed = true;
}
//使用参数更新mPendingRequestLocked对象,如果两者不同,则将changed设为true
if (mPendingRequestLocked == null) {
mPendingRequestLocked = new DisplayPowerRequest(request);
changed = true;
} else if (!mPendingRequestLocked.equals(request)) {
mPendingRequestLocked.copyFrom(request);
changed = true;
}
if (changed) { //如果changed为true,将mDisplayReadyLocked设为false
mDisplayReadyLocked = false;
}
if (changed && !mPendingRequestChangedLocked) {
mPendingRequestChangedLocked = true;
sendUpdatePowerStateLocked(); //发送消息
}
return mDisplayReadyLocked; //返回mDisplayReadyLocked
}
}
requestPowerState会将参数request和waitForNegativeProximity与DisplayPowerController对象中已有的值相比较,如果不同,则会更新DisplayPowerController中的值,然后返回mDisplayReadyLocked中的值(这时为false)。这也就意味着,如果屏幕的状态发生了变化,即使这种变化是要求关闭屏幕也不会在updateSuspendBlockerLocked中立刻关闭屏幕,那么,这个关闭屏幕的操作是在什么地方呢?在requestPowerState中,最后会调用sendUpdatePowerStateLocked,这个方法中会发送消息MSG_UPDATE_POWER_STATE,消息的处理方法是updatePowerState,这个方法主要作用是开始播放各种打开或关闭屏幕的动画,或者屏幕变暗、变亮的动画,然后才会将mDisplayReadyLocked设置为true,这样屏幕就能关闭了。
private void updatePowerState() {
// Update the power state request.
final boolean mustNotify;
boolean mustInitialize = false;
boolean updateAutoBrightness = mTwilightChanged;
boolean wasDim = false;
mTwilightChanged = false;
synchronized (mLock) {
mPendingUpdatePowerStateLocked = false;
if (mPendingRequestLocked == null) {
return; // wait until first actual power request
}
if (mPowerRequest == null) {
mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked);
mWaitingForNegativeProximity = mPendingWaitForNegativeProximityLocked;
mPendingWaitForNegativeProximityLocked = false;
mPendingRequestChangedLocked = false;
mustInitialize = true;
} else if (mPendingRequestChangedLocked) {
if (mPowerRequest.screenAutoBrightnessAdjustment
!= mPendingRequestLocked.screenAutoBrightnessAdjustment) {
updateAutoBrightness = true;
}
wasDim = (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM);
mPowerRequest.copyFrom(mPendingRequestLocked);
mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
mPendingWaitForNegativeProximityLocked = false;
mPendingRequestChangedLocked = false;
mDisplayReadyLocked = false;
}
mustNotify = !mDisplayReadyLocked;
}
// Initialize things the first time the power state is changed.
if (mustInitialize) {
initialize();
}
// Apply the proximity sensor.
if (mProximitySensor != null) {
if (mPowerRequest.useProximitySensor
&& mPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) {
setProximitySensorEnabled(true);
if (!mScreenOffBecauseOfProximity
&& mProximity == PROXIMITY_POSITIVE) {
mScreenOffBecauseOfProximity = true;
sendOnProximityPositiveWithWakelock();
setScreenOn(false);
}
} else if (mWaitingForNegativeProximity
&& mScreenOffBecauseOfProximity
&& mProximity == PROXIMITY_POSITIVE
&& mPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) {
setProximitySensorEnabled(true);
} else {
setProximitySensorEnabled(false);
mWaitingForNegativeProximity = false;
}
if (mScreenOffBecauseOfProximity
&& mProximity != PROXIMITY_POSITIVE) {
mScreenOffBecauseOfProximity = false;
sendOnProximityNegativeWithWakelock();
}
} else {
mWaitingForNegativeProximity = false;
}
// Turn on the light sensor if needed.
if (mLightSensor != null) {
setLightSensorEnabled(mPowerRequest.useAutoBrightness
&& wantScreenOn(mPowerRequest.screenState), updateAutoBrightness);
}
// Set the screen brightness.
if (wantScreenOn(mPowerRequest.screenState)) {
int target;
boolean slow;
if (mScreenAutoBrightness >= 0 && mLightSensorEnabled) {
// Use current auto-brightness value.
target = mScreenAutoBrightness;
slow = mUsingScreenAutoBrightness;
mUsingScreenAutoBrightness = true;
} else {
// Light sensor is disabled or not ready yet.
// Use the current brightness setting from the request, which is expected
// provide a nominal default value for the case where auto-brightness
// is not ready yet.
target = mPowerRequest.screenBrightness;
slow = false;
mUsingScreenAutoBrightness = false;
}
if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM) {
// Dim quickly by at least some minimum amount.
target = Math.min(target - SCREEN_DIM_MINIMUM_REDUCTION,
mScreenBrightnessDimConfig);
slow = false;
} else if (wasDim) {
// Brighten quickly.
slow = false;
}
animateScreenBrightness(clampScreenBrightness(target),
slow ? BRIGHTNESS_RAMP_RATE_SLOW : BRIGHTNESS_RAMP_RATE_FAST);
} else {
// Screen is off. Don't bother changing the brightness.
mUsingScreenAutoBrightness = false;
}
// Animate the screen on or off.
if (!mScreenOffBecauseOfProximity) {
if (wantScreenOn(mPowerRequest.screenState)) {
// Want screen on.
// Wait for previous off animation to complete beforehand.
// It is relatively short but if we cancel it and switch to the
// on animation immediately then the results are pretty ugly.
if (!mElectronBeamOffAnimator.isStarted()) {
// Turn the screen on. The contents of the screen may not yet
// be visible if the electron beam has not been dismissed because
// its last frame of animation is solid black.
setScreenOn(true);
if (mPowerRequest.blockScreenOn
&& mPowerState.getElectronBeamLevel() == 0.0f) {
blockScreenOn();
} else {
unblockScreenOn();
if (USE_ELECTRON_BEAM_ON_ANIMATION) {
if (!mElectronBeamOnAnimator.isStarted()) {
if (mPowerState.getElectronBeamLevel() == 1.0f) {
mPowerState.dismissElectronBeam();
} else if (mPowerState.prepareElectronBeam(
mElectronBeamFadesConfig ?
ElectronBeam.MODE_FADE :
ElectronBeam.MODE_WARM_UP)) {
mElectronBeamOnAnimator.start();
} else {
mElectronBeamOnAnimator.end();
}
}
} else {
mPowerState.setElectronBeamLevel(1.0f);
mPowerState.dismissElectronBeam();
}
}
}
} else {
// Want screen off.
// Wait for previous on animation to complete beforehand.
if (!mElectronBeamOnAnimator.isStarted()) {
if (!mElectronBeamOffAnimator.isStarted()) {
if (mPowerState.getElectronBeamLevel() == 0.0f) {
setScreenOn(false);
} else if (mPowerState.prepareElectronBeam(
mElectronBeamFadesConfig ?
ElectronBeam.MODE_FADE :
ElectronBeam.MODE_COOL_DOWN)
&& mPowerState.isScreenOn()
&& false) {
mElectronBeamOffAnimator.start();
} else {
mElectronBeamOffAnimator.end();
}
}
}
}
}
// Report whether the display is ready for use.
// We mostly care about the screen state here, ignoring brightness changes
// which will be handled asynchronously.
if (mustNotify
&& !mScreenOnWasBlocked
&& !mElectronBeamOnAnimator.isStarted()
&& !mElectronBeamOffAnimator.isStarted()
&& mPowerState.waitUntilClean(mCleanListener)) {
synchronized (mLock) {
if (!mPendingRequestChangedLocked) {
mDisplayReadyLocked = true; //将mDisplayReadyLocked改为true
if (DEBUG) {
Slog.d(TAG, "Display ready!");
}
}
}
sendOnStateChangedWithWakelock(); //发送通知
}
}
updatePowerState最后会调用sendOnStateChangedWithWakelock来发送消息:
private void sendOnStateChangedWithWakelock() {
mDisplaySuspendBlocker.acquire();
mCallbackHandler.post(mOnStateChangedRunnable);
}
post消息的处理函数:
private final Runnable mOnStateChangedRunnable = new Runnable() {
@Override
public void run() {
mCallbacks.onStateChanged();
mDisplaySuspendBlocker.release();
}
}
处理消息的run方法中会调用mCallbacks的onStateChanged方法。在PMS中定义了Callback方法:
private final DisplayPowerController.Callbacks mDisplayPowerControllerCallbacks =
new DisplayPowerController.Callbacks() {
@Override
public void onStateChanged() {
synchronized (mLock) {
mDirty |= DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED;
updatePowerStateLocked();
}
}
在onStateChanged中又调用了updatePowerStateLocked,重新开始处理Power系统的状态更新。
3 电池管理服务
在PMS中调用了BatteryService类的一些接口来获取电池的状态。
3.1 BatteryService的作用
BatteryService的构造函数:
public BatteryService(Context context, LightsService lights) {
mContext = context;
mHandler = new Handler(true /*async*/);
mLed = new Led(context, lights);
mBatteryStats = BatteryStatsService.getService(); //获取BatteryStatsService对象
//读取系统设定的各种低电量报警值
mCriticalBatteryLevel = mContext.getResources().getInteger(
com.android.internal.R.integer.config_criticalBatteryWarningLevel);
mLowBatteryWarningLevel = mContext.getResources().getInteger(
com.android.internal.R.integer.config_lowBatteryWarningLevel);
mLowBatteryCloseWarningLevel = mContext.getResources().getInteger(
com.android.internal.R.integer.config_lowBatteryCloseWarningLevel);
mShutdownBatteryTemperature = mContext.getResources().getInteger(
com.android.internal.R.integer.config_shutdownBatteryTemperature);
//监听下面的设备文件:无效的充电设备
// watch for invalid charger messages if the invalid_charger switch exists
if (new File("/sys/devices/virtual/switch/invalid_charger/state").exists()) {
mInvalidChargerObserver.startObserving(
"DEVPATH=/devices/virtual/switch/invalid_charger");
}
mBatteryPropertiesListener = new BatteryListener();
//连接batterypropreg服务
IBinder b = ServiceManager.getService("batterypropreg");
mBatteryPropertiesRegistrar = IBatteryPropertiesRegistrar.Stub.asInterface(b);
try { //设置batterypropreg服务的回调接口
mBatteryPropertiesRegistrar.registerListener(mBatteryPropertiesListener);
} catch (RemoteException e) {
// Should never happen.
}
}
BatteryService构造方法首先获取BatteryStateService对象,BatteryStateService对象的主要功能是收集系统中各个模块和进程的耗电情况。通过BatteryStateService记录的数据,可以找到耗电量最大的模块,然后加以改进。
接下来读取了系统设定的各种低电量报警值:
- mCriticalBatteryLevel:表示电量严重不足时的值,低于这个值系统将关闭
- mLowBatteryWarningLevel:表示电量不足时的值,低于这个值系统将发出警告
- mLowBatteryCloseWarningLevel:表示停止电量不足警告的值。电量高于这个值后系统将停止电量不足的警告
- mShutdownBatteryTemperature:表示电池温度太高的值,高于这个温度系统将关机
再接下来是创建mInvalidChargerObserver对象,这个对象是一个用于监听UEvent事件的对象,这里主要是用于监听设备插入了无效充电器的事件,事件发生时将会调用该对象的onUEvent设备文件方法:
private final UEventObserver mInvalidChargerObserver = new UEventObserver() {
@Override
public void onUEvent(UEventObserver.UEvent event) {
final int invalidCharger = "1".equals(event.get("SWITCH_STATE")) ? 1 : 0;
synchronized (mLock) {
if (mInvalidCharger != invalidCharger) {
mInvalidCharger = invalidCharger;
}
}
}
};
onUEvent中将设置BatterService的成员变量的值mInvalidCharger。这样外界通过BatterService就能查询充电器是否匹配。
最后,构造方法中创建了一个BatteryListener对象,并把它加入batterypropreg服务的回调接口中。batterypropreg服务下一节再分析,这里先看看BatteryListener的定义:
private final class BatteryListener extends IBatteryPropertiesListener.Stub {
public void batteryPropertiesChanged(BatteryProperties props) {
BatteryService.this.update(props);
}
}
BatteryListener是一个Binder服务 类,因此,batterypropreg服务能通过它传递回数据。这里传递回来的数据类型是BatteryProperties,定义如下:
public class BatteryProperties implements Parcelable {
public boolean chargerAcOnline; //正在用AC充电器充电
public boolean chargerUsbOnline; //正在用USB充电器充电
public boolean chargerWirelessOnline; //正在用无限充电器充电
public int batteryStatus; //电池状态值
public int batteryHealth; //电池的健康度
public boolean batteryPresent; //设备是否在使用电池供电
public int batteryLevel; //电量级别
public int batteryVoltage; //电压值
public int batteryCurrentNow; //当前电流值
public int batteryChargeCounter; //充电的时间
public int batteryTemperature; //电池温度
public String batteryTechnology; //电池的制造商信息
3.2 Healthd守护进程
BatteryService中使用的batterypropreg服务位于healthd守护进程中,healthd在init.rc中定义如下:
service healthd /sbin/healthd
class core
critical
seclabel u:r:healthd:s0
service healthd-charger /sbin/healthd -n
class charger
critical
seclabel u:r:healthd:s0
这里定义了两个服务。服务healthd属于core分组,因此,系统初始化时就会启动它。服务healthd-charger只会在充电时启动。
healthd的main函数:
int main(int argc, char **argv) {
int ch;
klog_set_level(KLOG_LEVEL);
while ((ch = getopt(argc, argv, "n")) != -1) {
switch (ch) {
case 'n':
nosvcmgr = true;
break;
case '?':
default:
KLOG_WARNING(LOG_TAG, "Unrecognized healthd option: %c\n", ch);
}
}
healthd_board_init(&healthd_config);
wakealarm_init(); //创建一个定时器
uevent_init(); //初始化uevent环境
binder_init();
gBatteryMonitor = new BatteryMonitor(); //创建BatteryMonitor对象
gBatteryMonitor->init(&healthd_config, nosvcmgr);
healthd_mainloop();
return 0;
}
wakealarm_init是创建一个定时器的文件句柄:
static void wakealarm_init(void) {
wakealarm_fd = timerfd_create(CLOCK_BOOTTIME_ALARM, TFD_NONBLOCK);
wakealarm_fd = -1;
if (wakealarm_fd == -1) {
KLOG_ERROR(LOG_TAG, "wakealarm_init: timerfd_create failed\n");
return;
}
//设置时间
wakealarm_set_interval(healthd_config.periodic_chores_interval_fast);
}
wakealarm_init调用timerfd_create创建了一个定时器的文件句柄,并保存在全局变量wakealarm_fd中,然后通过wakealarm_set_interval来设置定时器的超时时间。
这个定时器的作用看healthd_mainloop就知道了:
static void healthd_mainloop(void) {
struct epoll_event ev;
int epollfd;
int maxevents = 0;
epollfd = epoll_create(MAX_EPOLL_EVENTS);
if (epollfd == -1) {
KLOG_ERROR(LOG_TAG,
"healthd_mainloop: epoll_create failed; errno=%d\n",
errno);
return;
}
if (uevent_fd >= 0) { //把uevent_fd加入到poll监听列表
ev.events = EPOLLIN;
ev.data.ptr = (void *)uevent_event;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, uevent_fd, &ev) == -1)
KLOG_ERROR(LOG_TAG,
"healthd_mainloop: epoll_ctl for uevent_fd failed; errno=%d\n",
errno);
else
maxevents++;
}
if (wakealarm_fd >= 0) { //把wakealarm_fd加入到poll的监听列表
ev.events = EPOLLIN;
ev.data.ptr = (void *)wakealarm_event;//定时器的处理函数
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, wakealarm_fd, &ev) == -1)
KLOG_ERROR(LOG_TAG,
"healthd_mainloop: epoll_ctl for wakealarm_fd failed; errno=%d\n",
errno);
else
maxevents++;
}
if (binder_fd >= 0) { //把binder_fd加入到poll监听列表
ev.events = EPOLLIN | EPOLLWAKEUP;
ev.data.ptr= (void *)binder_event;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, binder_fd, &ev) == -1)
KLOG_ERROR(LOG_TAG,
"healthd_mainloop: epoll_ctl for binder_fd failed; errno=%d\n",
errno);
else
maxevents++;
}
while (1) {
struct epoll_event events[maxevents];
int nevents;
IPCThreadState::self()->flushCommands();
nevents = epoll_wait(epollfd, events, maxevents, awake_poll_interval);
if (nevents == -1) {
if (errno == EINTR)
continue;
KLOG_ERROR(LOG_TAG, "healthd_mainloop: epoll_wait failed\n");
break;
}
for (int n = 0; n < nevents; ++n) {
if (events[n].data.ptr)
(*(void (*)())events[n].data.ptr)(); //调用时间的处理函数
}
if (!nevents) //nevents等于0表示没有Event
periodic_chores(); //这时调用periodic_chores
}
return;
}
healthd_mainloop通过epoll来监听uevent_fd、wekealarm_fd和binder_fd这3个句柄的状态,一旦有数据到来就会从epoll_wait()调用中返回。当监听到定时器的事件后,定时器事件的处理函数wakealarm_event就会被调用:
static void wakealarm_event(void) {
unsigned long long wakeups;
if (wakealarm_fd == -1) {
return;
}
if (read(wakealarm_fd, &wakeups, sizeof(wakeups)) == -1) {
KLOG_ERROR(LOG_TAG, "wakealarm_event: read wakealarm_fd failed\n");
return;
}
periodic_chores();
}
wakealarm_event清空了wakealarm_fd中的数据后,调用了函数periodic_chores:
static void periodic_chores() {
battery_update();
}
static void battery_update(void) {
// Fast wake interval when on charger (watch for overheat);
// slow wake interval when on battery (watch for drained battery).
int new_wake_interval = gBatteryMonitor->update() ?
healthd_config.periodic_chores_interval_fast :
healthd_config.periodic_chores_interval_slow;
//调整定时器的时间
if (new_wake_interval != wakealarm_wake_interval)
wakealarm_set_interval(new_wake_interval);
// During awake periods poll at fast rate. If wake alarm is set at fast
// rate then just use the alarm; if wake alarm is set at slow rate then
// poll at fast rate while awake and let alarm wake up at slow rate when
// asleep.
if (healthd_config.periodic_chores_interval_fast == -1)
awake_poll_interval = -1;
else
awake_poll_interval =
new_wake_interval == healthd_config.periodic_chores_interval_fast ?
-1 : healthd_config.periodic_chores_interval_fast * 1000;
}
battery_update函数中调用gBatteryMonitor的update来读取电池的状态,然后根据返回值决定是否更新定时器的时间周期。这样在定时器的作用下,系统中的电池状态会持续更新。
3.3 读取电池的各种参数–BatteryMonitor
BatteryMonitor的作用是从设备文件中读取电池的各种参数,并返回给上层应用。在healthd的main中会创建BatteryMonitor对象,并调用它的init函数:
void BatteryMonitor::init(struct healthd_config *hc, bool nosvcmgr) {
String8 path;
mHealthdConfig = hc;
DIR* dir = opendir(POWER_SUPPLY_SYSFS_PATH); //打开目录/sys/class/power_supply
if (dir == NULL) {
KLOG_ERROR(LOG_TAG, "Could not open %s\n", POWER_SUPPLY_SYSFS_PATH);
} else {
struct dirent* entry;
while ((entry = readdir(dir))) { //读取目录的文件
const char* name = entry->d_name;
if (!strcmp(name, ".") || !strcmp(name, ".."))
continue;
char buf[20];
// Look for "type" file in each subdirectory
path.clear();
path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, name);
switch(readPowerSupplyType(path)) {
case ANDROID_POWER_SUPPLY_TYPE_AC:
case ANDROID_POWER_SUPPLY_TYPE_USB:
case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
path.clear();
path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);
if (access(path.string(), R_OK) == 0)
mChargerNames.add(String8(name));
break;
case ANDROID_POWER_SUPPLY_TYPE_BATTERY:
if (mHealthdConfig->batteryStatusPath.isEmpty()) {
path.clear();
path.appendFormat("%s/%s/status", POWER_SUPPLY_SYSFS_PATH,
name);
if (access(path, R_OK) == 0)
mHealthdConfig->batteryStatusPath = path;
}
if (mHealthdConfig->batteryHealthPath.isEmpty()) {
path.clear();
path.appendFormat("%s/%s/health", POWER_SUPPLY_SYSFS_PATH,
name);
if (access(path, R_OK) == 0)
mHealthdConfig->batteryHealthPath = path;
}
if (mHealthdConfig->batteryPresentPath.isEmpty()) {
path.clear();
path.appendFormat("%s/%s/present", POWER_SUPPLY_SYSFS_PATH,
name);
if (access(path, R_OK) == 0)
mHealthdConfig->batteryPresentPath = path;
}
if (mHealthdConfig->batteryCapacityPath.isEmpty()) {
path.clear();
path.appendFormat("%s/%s/capacity", POWER_SUPPLY_SYSFS_PATH,
name);
if (access(path, R_OK) == 0)
mHealthdConfig->batteryCapacityPath = path;
}
if (mHealthdConfig->batteryVoltagePath.isEmpty()) {
path.clear();
path.appendFormat("%s/%s/voltage_now",
POWER_SUPPLY_SYSFS_PATH, name);
if (access(path, R_OK) == 0) {
mHealthdConfig->batteryVoltagePath = path;
} else {
path.clear();
path.appendFormat("%s/%s/batt_vol",
POWER_SUPPLY_SYSFS_PATH, name);
if (access(path, R_OK) == 0)
mHealthdConfig->batteryVoltagePath = path;
}
}
if (mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
path.clear();
path.appendFormat("%s/%s/current_now",
POWER_SUPPLY_SYSFS_PATH, name);
if (access(path, R_OK) == 0)
mHealthdConfig->batteryCurrentNowPath = path;
}
if (mHealthdConfig->batteryChargeCounterPath.isEmpty()) {
path.clear();
path.appendFormat("%s/%s/charge_counter",
POWER_SUPPLY_SYSFS_PATH, name);
if (access(path, R_OK) == 0)
mHealthdConfig->batteryChargeCounterPath = path;
}
if (mHealthdConfig->batteryTemperaturePath.isEmpty()) {
path.clear();
path.appendFormat("%s/%s/temp", POWER_SUPPLY_SYSFS_PATH,
name);
if (access(path, R_OK) == 0) {
mHealthdConfig->batteryTemperaturePath = path;
} else {
path.clear();
path.appendFormat("%s/%s/batt_temp",
POWER_SUPPLY_SYSFS_PATH, name);
if (access(path, R_OK) == 0)
mHealthdConfig->batteryTemperaturePath = path;
}
}
if (mHealthdConfig->batteryTechnologyPath.isEmpty()) {
path.clear();
path.appendFormat("%s/%s/technology",
POWER_SUPPLY_SYSFS_PATH, name);
if (access(path, R_OK) == 0)
mHealthdConfig->batteryTechnologyPath = path;
}
break;
case ANDROID_POWER_SUPPLY_TYPE_UNKNOWN:
break;
}
}
closedir(dir);
}
if (!mChargerNames.size())
KLOG_ERROR(LOG_TAG, "No charger supplies found\n");
if (mHealthdConfig->batteryStatusPath.isEmpty())
KLOG_WARNING(LOG_TAG, "BatteryStatusPath not found\n");
if (mHealthdConfig->batteryHealthPath.isEmpty())
KLOG_WARNING(LOG_TAG, "BatteryHealthPath not found\n");
if (mHealthdConfig->batteryPresentPath.isEmpty())
KLOG_WARNING(LOG_TAG, "BatteryPresentPath not found\n");
if (mHealthdConfig->batteryCapacityPath.isEmpty())
KLOG_WARNING(LOG_TAG, "BatteryCapacityPath not found\n");
if (mHealthdConfig->batteryVoltagePath.isEmpty())
KLOG_WARNING(LOG_TAG, "BatteryVoltagePath not found\n");
if (mHealthdConfig->batteryTemperaturePath.isEmpty())
KLOG_WARNING(LOG_TAG, "BatteryTemperaturePath not found\n");
if (mHealthdConfig->batteryTechnologyPath.isEmpty())
KLOG_WARNING(LOG_TAG, "BatteryTechnologyPath not found\n");
if (nosvcmgr == false) {
mBatteryPropertiesRegistrar = new BatteryPropertiesRegistrar(this);
mBatteryPropertiesRegistrar->publish();
}
}
init函数首先打开/sys/class/power_supply,该目录下包含了一些子目录,其中battery目录存放的是电池信息,这个目录下有很多文件,每个文件对应电池的一种属性,文件的内容就是各个属性的当前值。usb目录便是USB充电器的信息,里面的online文件内容为1表示正在用usb充电。同样wireless目录保存的是无限充电器的信息。usb、usb_dcp、usb_cdp和usb_aca目录则分别表示不同类型的AC充电器的信息。
init主要功能是生成所有这些文件的文件名并保存到成员变量中,以便以后读取。完成这个工作后,init创建了BatteryPropertiesRegistrar对象,这个对象是一个Binder服务对象,它就是在BatteryService中使用的batterypropreg服务。
BatteryMonitor类的update()用来读取电池的信息,在healthd的health_mainloop()中会周期性的调用这个函数。
bool BatteryMonitor::update(void) {
struct BatteryProperties props;
bool logthis;
props.chargerAcOnline = false;
props.chargerUsbOnline = false;
props.chargerWirelessOnline = false;
props.batteryStatus = BATTERY_STATUS_UNKNOWN;
props.batteryHealth = BATTERY_HEALTH_UNKNOWN;
props.batteryCurrentNow = INT_MIN;
props.batteryChargeCounter = INT_MIN;
if (!mHealthdConfig->batteryPresentPath.isEmpty())
props.batteryPresent = getBooleanField(mHealthdConfig->batteryPresentPath);
else
props.batteryPresent = true;
props.batteryLevel = getIntField(mHealthdConfig->batteryCapacityPath);
props.batteryVoltage = getIntField(mHealthdConfig->batteryVoltagePath) / 1000;
if (!mHealthdConfig->batteryCurrentNowPath.isEmpty())
props.batteryCurrentNow = getIntField(mHealthdConfig->batteryCurrentNowPath);
if (!mHealthdConfig->batteryChargeCounterPath.isEmpty())
props.batteryChargeCounter = getIntField(mHealthdConfig->batteryChargeCounterPath);
props.batteryTemperature = getIntField(mHealthdConfig->batteryTemperaturePath);
const int SIZE = 128;
char buf[SIZE];
String8 btech;
if (readFromFile(mHealthdConfig->batteryStatusPath, buf, SIZE) > 0)
props.batteryStatus = getBatteryStatus(buf);
if (readFromFile(mHealthdConfig->batteryHealthPath, buf, SIZE) > 0)
props.batteryHealth = getBatteryHealth(buf);
if (readFromFile(mHealthdConfig->batteryTechnologyPath, buf, SIZE) > 0)
props.batteryTechnology = String8(buf);
unsigned int i;
for (i = 0; i < mChargerNames.size(); i++) {
String8 path;
path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH,
mChargerNames[i].string());
if (readFromFile(path, buf, SIZE) > 0) {
if (buf[0] != '0') {
path.clear();
path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH,
mChargerNames[i].string());
switch(readPowerSupplyType(path)) {
case ANDROID_POWER_SUPPLY_TYPE_AC:
props.chargerAcOnline = true;
break;
case ANDROID_POWER_SUPPLY_TYPE_USB:
props.chargerUsbOnline = true;
break;
case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
props.chargerWirelessOnline = true;
break;
default:
KLOG_WARNING(LOG_TAG, "%s: Unknown power supply type\n",
mChargerNames[i].string());
}
}
}
}
logthis = !healthd_board_battery_update(&props);
if (logthis) {
char dmesgline[256];
snprintf(dmesgline, sizeof(dmesgline),
"battery l=%d v=%d t=%s%d.%d h=%d st=%d",
props.batteryLevel, props.batteryVoltage,
props.batteryTemperature < 0 ? "-" : "",
abs(props.batteryTemperature / 10),
abs(props.batteryTemperature % 10), props.batteryHealth,
props.batteryStatus);
if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
char b[20];
snprintf(b, sizeof(b), " c=%d", props.batteryCurrentNow / 1000);
strlcat(dmesgline, b, sizeof(dmesgline));
}
KLOG_INFO(LOG_TAG, "%s chg=%s%s%s\n", dmesgline,
props.chargerAcOnline ? "a" : "",
props.chargerUsbOnline ? "u" : "",
props.chargerWirelessOnline ? "w" : "");
}
if (mBatteryPropertiesRegistrar != NULL)
mBatteryPropertiesRegistrar->notifyListeners(props);
return props.chargerAcOnline | props.chargerUsbOnline |
props.chargerWirelessOnline;
}
update主要是读取各种文件的内容。然后会调用mBatteryPropertiesRegistrar变量的notifyListeners把保存在props中的电池信息传递到BatteryService中。
g8 path;
path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH,
mChargerNames[i].string());
if (readFromFile(path, buf, SIZE) > 0) {
if (buf[0] != '0') {
path.clear();
path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH,
mChargerNames[i].string());
switch(readPowerSupplyType(path)) {
case ANDROID_POWER_SUPPLY_TYPE_AC:
props.chargerAcOnline = true;
break;
case ANDROID_POWER_SUPPLY_TYPE_USB:
props.chargerUsbOnline = true;
break;
case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
props.chargerWirelessOnline = true;
break;
default:
KLOG_WARNING(LOG_TAG, "%s: Unknown power supply type\n",
mChargerNames[i].string());
}
}
}
}
logthis = !healthd_board_battery_update(&props);
if (logthis) {
char dmesgline[256];
snprintf(dmesgline, sizeof(dmesgline),
"battery l=%d v=%d t=%s%d.%d h=%d st=%d",
props.batteryLevel, props.batteryVoltage,
props.batteryTemperature < 0 ? "-" : "",
abs(props.batteryTemperature / 10),
abs(props.batteryTemperature % 10), props.batteryHealth,
props.batteryStatus);
if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
char b[20];
snprintf(b, sizeof(b), " c=%d", props.batteryCurrentNow / 1000);
strlcat(dmesgline, b, sizeof(dmesgline));
}
KLOG_INFO(LOG_TAG, "%s chg=%s%s%s\n", dmesgline,
props.chargerAcOnline ? "a" : "",
props.chargerUsbOnline ? "u" : "",
props.chargerWirelessOnline ? "w" : "");
}
if (mBatteryPropertiesRegistrar != NULL)
mBatteryPropertiesRegistrar->notifyListeners(props);
return props.chargerAcOnline | props.chargerUsbOnline |
props.chargerWirelessOnline;
}
update主要是读取各种文件的内容。然后会调用mBatteryPropertiesRegistrar变量的notifyListeners把保存在props中的电池信息传递到BatteryService中。