PowerManagerService是负责管理、协调设备电源管理的系统服务之一,它在Framework层建立起一个策略控制方案,向下决策HAL层以及kernel层来控制设备待机状态,控制显示屏,背光灯,距离传感器,光线传感器等硬件设备的状态。

Android的电源管理主要是通过wakelock机制来管理系统的状态,整个android电源管理,可以分为四个层次:

  • 应用接口层(PowerManager.java)
  • Framework层(PowerManagerService.java)
  • HAL层(Power.c)
  • 内核层(kernel/Power)

PowerManagerService一些重要成员变量介绍

变量名 介绍
mDirty 记录电源状态有哪些部分已更改,需要更新
mWakefulness 记录设备电源状态
mWakeLockSuspendBlocker CPU锁
mDisplaySuspendBlocker 屏幕锁
mWakeLocks 应用程序获取的所有唤醒锁数组
mWakeLockSummary 所有有效的锁的bit位组合
mUserActivitySummary 用户活动计时器bit位组合
mNotifier 电源状态改变, 发送相应的通知等
mWakefulness有如下四种状态
// 休眠状态
public static final int WAKEFULNESS_ASLEEP = 0;
// 亮屏状态
public static final int WAKEFULNESS_AWAKE = 1;
// 屏保状态
public static final int WAKEFULNESS_DREAMING = 2;
// 打盹状态
public static final int WAKEFULNESS_DOZING = 3;

PowerManagerService初始化

PowerManagerService的初始化主要涉及到两个函数,PowerManagerService构造函数和systemReady函数

PowerManagerService构造函数所完成的工作如下:

  • 1 创建ServiceThread和PowerManagerHandler(PowerManagerHandler用来处理用户活动超时,屏保,长锁检测等)
  • 2 电池信息相关的初始化,电池状态的记录
  • 3 创建CPU和屏幕锁
  • 4 获取屏幕锁,不让屏幕关闭
  • 5 设置mWakefulness为亮屏状态
public PowerManagerService(Context context) {super(context);mContext = context;mHandlerThread = new ServiceThread(TAG,Process.THREAD_PRIORITY_DISPLAY, false /*allowIo*/);mHandlerThread.start();// PowerManagerHandler 处理用户活动超时,屏保, 长锁检测mHandler = new PowerManagerHandler(mHandlerThread.getLooper());// 电池信息相关的初始化mBatterySavingStats = new BatterySavingStats(mLock);mBatterySaverPolicy = new BatterySaverPolicy(mLock, mContext, mBatterySavingStats);mBatterySaverController = new BatterySaverController(mLock, mContext,BackgroundThread.get().getLooper(), mBatterySaverPolicy, mBatterySavingStats);mBatterySaverStateMachine = new BatterySaverStateMachine(mLock, mContext, mBatterySaverController);synchronized (mLock) {// new cpu锁mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks");// new 屏幕锁mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display");// 获取屏幕锁,不让屏幕关闭mDisplaySuspendBlocker.acquire();mHoldingDisplaySuspendBlocker = true;mHalAutoSuspendModeEnabled = false;mHalInteractiveModeEnabled = true;// 设置状态为亮屏状态mWakefulness = WAKEFULNESS_AWAKE;sQuiescent = SystemProperties.get(SYSTEM_PROPERTY_QUIESCENT, "0").equals("1");// 初始化 powerHalnativeInit();}
}

PowerManagerService::systemReady函数所完成的工作如下:

  • 1 屏保服务获取
  • 2 显示服务获取
  • 3 给mPolicy赋值(mPolicy == PhoneWindowManager)
  • 4 电池服务获取
  • 5 mNotifier对象创建
  • 6 灯光服务获取
  • 7 初始化显示器电源
  • 8 读取配置信息, 更新配置信息
  • 9 更新电源状态(updatePowerStateLocked方法是整个PMS中的核心方法)
  • 10 注册设置改变的监听事件
  • 11 注册屏保,电池状态改变等广播事件
public void systemReady(IAppOpsService appOps) {synchronized (mLock) {mSystemReady = true;mAppOps = appOps;// 屏保服务获取mDreamManager = getLocalService(DreamManagerInternal.class);// 显示服务获取mDisplayManagerInternal = getLocalService(DisplayManagerInternal.class);// mPolicy = PhoneWindowManagermPolicy = getLocalService(WindowManagerPolicy.class);// 电池服务获取mBatteryManagerInternal = getLocalService(BatteryManagerInternal.class);mBatteryStats = BatteryStatsService.getService();// 用于通知系统中电源状态的改变mNotifier = new Notifier(Looper.getMainLooper(), mContext, mBatteryStats,createSuspendBlockerLocked("PowerManagerService.Broadcasts"), mPolicy);mWirelessChargerDetector = new WirelessChargerDetector(sensorManager,createSuspendBlockerLocked("PowerManagerService.WirelessChargerDetector"),mHandler);mSettingsObserver = new SettingsObserver(mHandler);// 灯光服务获取mLightsManager = getLocalService(LightsManager.class);mAttentionLight = mLightsManager.getLight(LightsManager.LIGHT_ID_ATTENTION);// Initialize display power management.// 初始化显示器电源mDisplayManagerInternal.initPowerManagement(mDisplayPowerCallbacks, mHandler, sensorManager);try {final ForegroundProfileObserver observeupdateIsPoweredLockedr = new ForegroundProfileObserver();ActivityManager.getService().registerUserSwitchObserver(observer, TAG);} catch (RemoteException e) {// Shouldn't happen since in-process.}// Go.// 读取配置信息readConfigurationLocked();// 更新配置信息updateSettingsLocked();mDirty |= DIRTY_BATTERY_STATE;// 更新电源状态updatePowerStateLocked();}final ContentResolver resolver = mContext.getContentResolver();mConstants.start(resolver);mBatterySaverController.systemReady();mBatterySaverPolicy.systemReady();// Register for settings changes.// 监听setting数据库的某些字段变化resolver.registerContentObserver(Settings.Secure.getUriFor(Settings.Secure.SCREENSAVER_ENABLED),false, mSettingsObserver, UserHandle.USER_ALL);// Register for broadcasts from other components of the system.// 注册监听电池相关信息改变, 屏保等广播IntentFilter filter = new IntentFilter();filter.addAction(Intent.ACTION_BATTERY_CHANGED);filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);mContext.registerReceiver(new BatteryReceiver(), 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);
}

updatePowerStateLocked

updatePowerStateLocked方法是整个PMS中的核心方法,它用来更新整个电源状态的改变。PMS中使用一个int值mDirty作为标志位判断电源状态是否发生变化,当电源状态发生改变时,如亮灭屏、电池状态改变、暗屏等都会调用该方法
PowerManagerService::updatePowerStateLocked函数所完成的工作如下:

  • 1 充电以及电池状态更新,插拔电源会亮屏在这里更新
  • 2 更新 mStayOn
  • 3 更新统计wakelock的标记值到mWakeLockSummary
  • 4 更新mUserActivitySummary和重新计算休眠到达时间
  • 5 更新mWakefulness状态 (休眠,唤醒,屏保, 打盹)
  • 6 更新显示服务相关信息, 没有具体分析, 涉及到显示相关服务
  • 7 更新屏保状态
  • 8 通过mNotifier发送相关状态变化广播和回调相关接口
  • 9 根据mWakeLockSummary的bit位来判断是否需要释放CPU锁(updateSuspendBlockerLocked)
  • 10 根据显示服务是否需要释放或者获取屏幕锁(updateSuspendBlockerLocked)
private void updatePowerStateLocked() {// 系统没有ready 或者mDirty没有bit位更新,直接返回if (!mSystemReady || mDirty == 0) {return;}try {// Phase 0: Basic state updates.// 0 充电以及电池状态更新updateIsPoweredLocked(mDirty);// 0 更新 mStayOnupdateStayOnLocked(mDirty);// 0updateScreenBrightnessBoostLocked(mDirty);// Phase 1: Update wakefulness.// Loop because the wake lock and user activity computations are influenced// by changes in wakefulness.final long now = SystemClock.uptimeMillis();int dirtyPhase2 = 0;// 1 循环最多跑两次for (;;) {int dirtyPhase1 = mDirty;dirtyPhase2 |= dirtyPhase1;// 1 清除mDirty bit位mDirty = 0;// 1 更新统计wakelock的标记值到mWakeLockSummaryupdateWakeLockSummaryLocked(dirtyPhase1);// 1 更新mUserActivitySummary和重新计算休眠到达时间updateUserActivitySummaryLocked(now, dirtyPhase1);// 1 根据dirtyPhase1更新 mWakefulness (休眠,唤醒,或其他状态)if (!updateWakefulnessLocked(dirtyPhase1)) {break;}}// Phase 2: Lock profiles that became inactive/not kept awake.updateProfilesLocked(now);// Phase 3: Update display power state.// 3 更新显示服务相关信息, 没有具体分析, 涉及到显示相关服务final boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);// Phase 4: Update dream state (depends on display ready signal).// 4 更新屏保状态updateDreamLocked(dirtyPhase2, displayBecameReady);// Phase 5: Send notifications, if needed.// 5 当mWakefulness改变时,发送相应的广播finishWakefulnessChangeIfNeededLocked();// Phase 6: Update suspend blocker.// Because we might release the last suspend blocker here, we need to make sure// we finished everything else first!// 6 获取或者释放cpu锁和屏幕锁updateSuspendBlockerLocked();} finally {Trace.traceEnd(Trace.TRACE_TAG_POWER);}
}

updateIsPoweredLocked

PowerManagerService::updateIsPoweredLocked函数所完成的工作如下:

  • 1 DIRTY_BATTERY_STATE bit位为1才进条件
  • 2 通过电池服务获取电池信息,是否在充电
  • 3 是否需要唤醒屏幕
  • 4 更新active时间 回调PhoneWindowManager的onUserActivity函数
  • 5 将电池状态信息保存到mBatterySaverStateMachine中
private void updateIsPoweredLocked(int dirty) {if ((dirty & DIRTY_BATTERY_STATE) != 0) {final boolean wasPowered = mIsPowered;final int oldPlugType = mPlugType;final boolean oldLevelLow = mBatteryLevelLow;// 是否充电mIsPowered = mBatteryManagerInternal.isPowered(BatteryManager.BATTERY_PLUGGED_ANY);// 充电类型mPlugType = mBatteryManagerInternal.getPlugType();// 电池电量mBatteryLevel = mBatteryManagerInternal.getBatteryLevel();// 是否低电量mBatteryLevelLow = mBatteryManagerInternal.getBatteryLevelLow();// 是否和上次充电状态不一样或者充电类型不同if (wasPowered != mIsPowered || oldPlugType != mPlugType) {mDirty |= DIRTY_IS_POWERED;// Update wireless dock detection state.final boolean dockedOnWirelessCharger = mWirelessChargerDetector.update(mIsPowered, mPlugType);// 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, "android.server.power:POWER", Process.SYSTEM_UID,mContext.getOpPackageName(), Process.SYSTEM_UID);}// 更新active时间 回调PhoneWindowManager的onUserActivity(event, uid)函数userActivityNoUpdateLocked(now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);}// 更新电池相关信息到mBatterySaverStateMachine中mBatterySaverStateMachine.setBatteryStatus(mIsPowered, mBatteryLevel, mBatteryLevelLow);}
}

updateWakeLockSummaryLocked

将mWakeLocks的bit位合并到mWakeLockSummary中,通过adjustWakeLockSummaryLocked函数来进一步调整bit位

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);// 获取锁的标志位final int wakeLockFlags = getWakeLockSummaryFlags(wakeLock);// 合并到mWakeLockSummary中mWakeLockSummary |= wakeLockFlags;}mWakeLockSummary = adjustWakeLockSummaryLocked(mWakeLockSummary);}
}

adjustWakeLockSummaryLocked

private int adjustWakeLockSummaryLocked(int wakeLockSummary) {// Cancel wake locks that make no sense based on the current state.if (mWakefulness != WAKEFULNESS_DOZING) {// 不是WAKEFULNESS_DOZING 清除WAKE_LOCK_DOZE和WAKE_LOCK_DRAW bit位wakeLockSummary &= ~(WAKE_LOCK_DOZE | WAKE_LOCK_DRAW);}if (mWakefulness == WAKEFULNESS_ASLEEP|| (wakeLockSummary & WAKE_LOCK_DOZE) != 0) {// 清除屏幕显示相关的bit位wakeLockSummary &= ~(WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM| WAKE_LOCK_BUTTON_BRIGHT);if (mWakefulness == WAKEFULNESS_ASLEEP) {// 清除Psensor关屏标识wakeLockSummary &= ~WAKE_LOCK_PROXIMITY_SCREEN_OFF;}}// Infer implied wake locks where necessary based on the current state.if ((wakeLockSummary & (WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM)) != 0) {if (mWakefulness == WAKEFULNESS_AWAKE) {// 系统是wake状态,需要获取WAKE_LOCK_CPU和WAKE_LOCK_STAY_AWAKE bit位置1wakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_STAY_AWAKE;} else if (mWakefulness == WAKEFULNESS_DREAMING) {// 屏保状态wakeLockSummary |= WAKE_LOCK_CPU;}}if ((wakeLockSummary & WAKE_LOCK_DRAW) != 0) {wakeLockSummary |= WAKE_LOCK_CPU;}return wakeLockSummary;
}

updateUserActivitySummaryLocked

用户过段时间没有操作屏幕或按键, 屏幕会关闭,检测超时时间是否需要重新计算或者时间已经过去,通过updateUserActivitySummaryLocked来更新,只有当屏幕是亮的时候,才需要计算。

private void updateUserActivitySummaryLocked(long now, int dirty) {// Update the status of the user activity timeout timer.// 更新用户活动超时时间if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY| DIRTY_WAKEFULNESS | DIRTY_SETTINGS)) != 0) {mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT);long nextTimeout = 0;// mWakefulness 是休眠模式不会进入if条件if (mWakefulness == WAKEFULNESS_AWAKE|| mWakefulness == WAKEFULNESS_DREAMING|| mWakefulness == WAKEFULNESS_DOZING) {final long sleepTimeout = getSleepTimeoutLocked();final long screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout);final long screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);final boolean userInactiveOverride = mUserInactiveOverrideFromWindowManager;final long nextProfileTimeout = getNextProfileTimeoutLocked(now);mUserActivitySummary = 0;// 亮屏if (mLastUserActivityTime >= mLastWakeTime) {nextTimeout = mLastUserActivityTime+ screenOffTimeout - screenDimDuration;// 当前时间小于超时时间, 屏幕还是亮的if (now < nextTimeout) {mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;} else {nextTimeout = mLastUserActivityTime + screenOffTimeout;if (now < nextTimeout) {// 处在超时和dim中间的时间段mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;}}}if (mUserActivitySummary == 0&& mLastUserActivityTimeNoChangeLights >= mLastWakeTime) {// nextTimeout = 上次唤醒时间加屏幕超时时间nextTimeout = mLastUserActivityTimeNoChangeLights + screenOffTimeout;if (now < nextTimeout) {// 根据mDisplayPowerRequest 状态设置mUserActivitySummaryif (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_BRIGHT|| mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_VR) {mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;} else if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;}}}// 屏保相关状态if (mUserActivitySummary == 0) {if (sleepTimeout >= 0) {final long anyUserActivity = Math.max(mLastUserActivityTime,mLastUserActivityTimeNoChangeLights);if (anyUserActivity >= mLastWakeTime) {nextTimeout = anyUserActivity + sleepTimeout;if (now < nextTimeout) {mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;}}} else {mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;nextTimeout = -1;}}if (mUserActivitySummary != USER_ACTIVITY_SCREEN_DREAM && userInactiveOverride) {if ((mUserActivitySummary &(USER_ACTIVITY_SCREEN_BRIGHT | USER_ACTIVITY_SCREEN_DIM)) != 0) {// Device is being kept awake by recent user activityif (nextTimeout >= now && mOverriddenTimeout == -1) {// Save when the next timeout would have occurredmOverriddenTimeout = nextTimeout;}}mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;nextTimeout = -1;}if (nextProfileTimeout > 0) {nextTimeout = Math.min(nextTimeout, nextProfileTimeout);}if (mUserActivitySummary != 0 && nextTimeout >= 0) {// 重新计算下次超时时间,超时从新调用updatePowerStateLocked函数// scheduleUserInactivityTimeout//  mDirty |= DIRTY_USER_ACTIVITY;//  updatePowerStateLocked();scheduleUserInactivityTimeout(nextTimeout);}} else {mUserActivitySummary = 0;}}
}

updateWakefulnessLocked

isItBedTimeYetLocked函数检测系统是否能休眠,通过shouldNapAtBedTimeLocked函数判断是否设置了屏保,如果设置了,则通过napNoUpdateLocked函数把mWakefulness设置为WAKEFULNESS_DREAMING模式,否则通过goToSleepNoUpdateLocked设置为WAKEFULNESS_DOZING模式

private boolean updateWakefulnessLocked(int dirty) {boolean changed = false;// 当 dirty为0时,或条件不成立则退出// updatePowerStateLocked中的for循环判断updateWakefulnessLocked为false则退出循环if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_BOOT_COMPLETED| DIRTY_WAKEFULNESS | DIRTY_STAY_ON | DIRTY_PROXIMITY_POSITIVE| DIRTY_DOCK_STATE)) != 0) {// isItBedTimeYetLocked 检测设备是否可以sleep (BedTime)if (mWakefulness == WAKEFULNESS_AWAKE && isItBedTimeYetLocked()) {if (DEBUG_SPEW) {Slog.d(TAG, "updateWakefulnessLocked: Bed time...");}final long time = SystemClock.uptimeMillis();// 是否设置了屏保if (shouldNapAtBedTimeLocked()) {// 进入屏保状态changed = napNoUpdateLocked(time, Process.SYSTEM_UID);} else {// 进入休眠状态changed = goToSleepNoUpdateLocked(time,PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, Process.SYSTEM_UID);}}}return changed;
}

napNoUpdateLocked

private boolean napNoUpdateLocked(long eventTime, int uid) {if (eventTime < mLastWakeTime || mWakefulness != WAKEFULNESS_AWAKE|| !mBootCompleted || !mSystemReady) {return false;}Trace.traceBegin(Trace.TRACE_TAG_POWER, "nap");try {Slog.i(TAG, "Nap time (uid " + uid +")...");mSandmanSummoned = true;// 设置为屏保状态 mWakefulness = WAKEFULNESS_DREAMINGsetWakefulnessLocked(WAKEFULNESS_DREAMING, 0);} finally {Trace.traceEnd(Trace.TRACE_TAG_POWER);}return true;
}

setWakefulnessLocked

void setWakefulnessLocked(int wakefulness, int reason) {if (mWakefulness != wakefulness) {mWakefulness = wakefulness;mWakefulnessChanging = true;mDirty |= DIRTY_WAKEFULNESS;if (mNotifier != null) {// 发送相应的状态改变的广播mNotifier.onWakefulnessChangeStarted(wakefulness, reason);}}
}

goToSleepNoUpdateLocked

private boolean goToSleepNoUpdateLocked(long eventTime, int reason, int flags, int uid) {if (eventTime < mLastWakeTime|| mWakefulness == WAKEFULNESS_ASLEEP|| mWakefulness == WAKEFULNESS_DOZING|| !mBootCompleted || !mSystemReady) {return false;}Trace.traceBegin(Trace.TRACE_TAG_POWER, "goToSleep");try {// 记录休眠时间mLastSleepTime = eventTime;mSandmanSummoned = true;// 设置为WAKEFULNESS_DOZING状态setWakefulnessLocked(WAKEFULNESS_DOZING, reason);// Skip dozing if requested.// 如果有PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE flag 则直接跳过DOZING模式, 直接进入休眠模式if ((flags & PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE) != 0) {reallyGoToSleepNoUpdateLocked(eventTime, uid);}} finally {Trace.traceEnd(Trace.TRACE_TAG_POWER);}return true;
}

reallyGoToSleepNoUpdateLocked

private boolean reallyGoToSleepNoUpdateLocked(long eventTime, int uid) {if (eventTime < mLastWakeTime || mWakefulness == WAKEFULNESS_ASLEEP|| !mBootCompleted || !mSystemReady) {return false;}Trace.traceBegin(Trace.TRACE_TAG_POWER, "reallyGoToSleep");try {Slog.i(TAG, "Sleeping (uid " + uid +")...");// 设置为休眠状态setWakefulnessLocked(WAKEFULNESS_ASLEEP, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);} finally {Trace.traceEnd(Trace.TRACE_TAG_POWER);}return true;
}

updateDreamLocked

private void updateDreamLocked(int dirty, boolean displayBecameReady) {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 || displayBecameReady) {if (mDisplayReady) {// 异步启动屏保scheduleSandmanLocked();}}
}

scheduleSandmanLocked

private void scheduleSandmanLocked() {// 如果已经计划屏保了, 则不做处理if (!mSandmanScheduled) {// 计划处理屏保位mSandmanScheduled = true;// 发送异步消息Message msg = mHandler.obtainMessage(MSG_SANDMAN);msg.setAsynchronous(true);mHandler.sendMessage(msg);}
}
PowerManagerHandler
case MSG_SANDMAN:handleSandman();

handleSandman

PowerManagerService::handleSandman函数所完成的工作如下:

  • 1 通过canDreamLocked和canDozeLocked来判断可不可以启动屏保
  • 2 如果可以启动屏保则启动屏保
  • 3 记录当前电量信息
  • 4 当前电量在屏保配置的范围内,继续屏保
  • 5 不满足上面条件时,通过isItBedTimeYetLocked判断来设置为WAKEFULNESS_DOZING或者WAKEFULNESS_AWAKE模式
  • 6 WAKEFULNESS_AWAKE模式时,则停止屏保
// 运行在HandlerThread线程中
private void handleSandman() {// Handle preconditions.final boolean startDreaming;final int wakefulness;synchronized (mLock) {mSandmanScheduled = false;wakefulness = mWakefulness;// 判断是否可以启动屏保if (mSandmanSummoned && mDisplayReady) {startDreaming = canDreamLocked() || canDozeLocked();mSandmanSummoned = false;} else {startDreaming = false;}}// Start dreaming if needed.// We only control the dream on the handler thread, so we don't need to worry about// concurrent attempts to start or stop the dream.final boolean isDreaming;if (mDreamManager != null) {// Restart the dream whenever the sandman is summoned.if (startDreaming) {mDreamManager.stopDream(false /*immediate*/);// 启动屏保mDreamManager.startDream(wakefulness == WAKEFULNESS_DOZING);}isDreaming = mDreamManager.isDreaming();} else {isDreaming = false;}// Update dream state.synchronized (mLock) {// Remember the initial battery level when the dream started.if (startDreaming && isDreaming) {// 记录当前的电量mBatteryLevelWhenDreamStarted = mBatteryLevel;if (wakefulness == WAKEFULNESS_DOZING) {Slog.i(TAG, "Dozing...");} else {Slog.i(TAG, "Dreaming...");}}// If preconditions changed, wait for the next iteration to determine// whether the dream should continue (or be restarted).if (mSandmanSummoned || mWakefulness != wakefulness) {return; // wait for next cycle}// Determine whether the dream should continue.// 屏保模式if (wakefulness == WAKEFULNESS_DREAMING) {// 现在是屏保模式,并且还能进入屏保模式,直接返回if (isDreaming && canDreamLocked()) {// 电池电量低于屏保配置电量,则进入WAKEFULNESS_DOZING模式if (mDreamsBatteryLevelDrainCutoffConfig >= 0&& mBatteryLevel < mBatteryLevelWhenDreamStarted- mDreamsBatteryLevelDrainCutoffConfig&& !isBeingKeptAwakeLocked()) {} else {return; // continue dreaming}}// Dream has ended or will be stopped.  Update the power state.if (isItBedTimeYetLocked()) {// sleepgoToSleepNoUpdateLocked(SystemClock.uptimeMillis(),PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, Process.SYSTEM_UID);// 更新电源相关信息updatePowerStateLocked();} else {// wakeUpwakeUpNoUpdateLocked(SystemClock.uptimeMillis(), "android.server.power:DREAM",Process.SYSTEM_UID, mContext.getOpPackageName(), Process.SYSTEM_UID);// 更新电源相关信息updatePowerStateLocked();}} else if (wakefulness == WAKEFULNESS_DOZING) {if (isDreaming) {return; // continue dozing}// Doze has ended or will be stopped.  Update the power state.// sleepreallyGoToSleepNoUpdateLocked(SystemClock.uptimeMillis(), Process.SYSTEM_UID);// 更新电源相关信息updatePowerStateLocked();}}// Stop dream.// awake状态, 停止屏保if (isDreaming) {mDreamManager.stopDream(false /*immediate*/);}
}

updateIsPoweredLocked

private void updateIsPoweredLocked() {if (mWakefulnessChanging && mDisplayReady) {if (mWakefulness == WAKEFULNESS_DOZING&& (mWakeLockSummary & WAKE_LOCK_DOZE) == 0) {return; // wait until dream has enabled dozing}if (mWakefulness == WAKEFULNESS_DOZING || mWakefulness == WAKEFULNESS_ASLEEP) {// 记录相关loglogSleepTimeoutRecapturedLocked();}if (mWakefulness == WAKEFULNESS_AWAKE) {// 记录相关loglogScreenOn();}mWakefulnessChanging = false;// 发送相关状态变化广播和一系列回调函数mNotifier.onWakefulnessChangeFinished();}
}

updateSuspendBlockerLocked

updateSuspendBlockerLocked方法通过调用SuspendBlockerImpl的acquire和release函数来和PowerHal模块通信,和natvie通信的函数为nativeAcquireSuspendBlocker和nativeReleaseSuspendBlocker,最终通过往/sys/power/wake_lock和/sys/power/kwake_unlock节点写入字符串信息,来和kernel通信,是否需要关闭屏幕或停止CPU

private void updateSuspendBlockerLocked() {// 是否需要CPU锁final boolean needWakeLockSuspendBlocker = ((mWakeLockSummary & WAKE_LOCK_CPU) != 0);// 是否需要屏幕锁final boolean needDisplaySuspendBlocker = needDisplaySuspendBlockerLocked();final boolean autoSuspend = !needDisplaySuspendBlocker;final boolean interactive = mDisplayPowerRequest.isBrightOrDim();// Disable auto-suspend if needed.// FIXME We should consider just leaving auto-suspend enabled forever since// we already hold the necessary wakelocks.if (!autoSuspend && mDecoupleHalAutoSuspendModeFromDisplayConfig) {setHalAutoSuspendModeLocked(false);}// First acquire suspend blockers if needed.if (needWakeLockSuspendBlocker && !mHoldingWakeLockSuspendBlocker) {// 获取CPU锁mWakeLockSuspendBlocker.acquire();mHoldingWakeLockSuspendBlocker = true;}if (needDisplaySuspendBlocker && !mHoldingDisplaySuspendBlocker) {// 获取屏幕锁mDisplaySuspendBlocker.acquire();mHoldingDisplaySuspendBlocker = true;}// Then release suspend blockers if needed.if (!needWakeLockSuspendBlocker && mHoldingWakeLockSuspendBlocker) {// 释放CPU锁, CPU将停止运行mWakeLockSuspendBlocker.release();mHoldingWakeLockSuspendBlocker = false;}if (!needDisplaySuspendBlocker && mHoldingDisplaySuspendBlocker) {// 释放屏幕锁, 屏幕将关闭mDisplaySuspendBlocker.release();mHoldingDisplaySuspendBlocker = false;}// Enable auto-suspend if needed.if (autoSuspend && mDecoupleHalAutoSuspendModeFromDisplayConfig) {setHalAutoSuspendModeLocked(true);}
}

Notifier

// 回调PhoneWindowManager的userActivity函数
sendUserActivity// 当休眠或唤醒时,PowerMnagerService会调用
onWakefulnessChangeStarted// 回调PhoneWindowManager的startedWakingUp函数或者startedGoingToSleep函数
handleEarlyInteractiveChange// call handleLateInteractiveChange
onWakefulnessChangeFinished// 回调PhoneWindowManager的finishedWakingUp函数或者finishedGoingToSleep函数
handleLateInteractiveChange// 发送亮屏广播
sendWakeUpBroadcast// 发送灭屏广播
sendGoToSleepBroadcast

mtk亮灭屏流程

灭屏流程

亮屏流程

用户活动流程

推荐博客

http://blog.chinaunix.net/uid-30510400-id-5569393.html

Android PowerManagerService简单分析相关推荐

  1. Android Framework------之Keyguard 简单分析

    前面对于MediaPlayer的系统研究,刚刚开始,由于其他原因现在要先暂停一下.这次要看的模块是android 4.2 系统中的Keyguard模块.在接触之后才发现,android4.2的keyg ...

  2. android开发中Settings结构简单分析

    Settings界面结构简单分析 Setting是android系统很重要的模块,这个模块并不是很复杂,这部分也一直在看,很多时候都是在看某个具体的选项,比如WLAN,蓝牙这样具体的源码,但是对于主界 ...

  3. Android Handler机制简单分析

    丨版权说明 : <Android Handler机制简单分析>于当前CSDN博客和乘月网属同一原创,转载请说明出处,谢谢. 本文一切从简,将围绕以下流程展开叙述: what why how ...

  4. Android 系统(261)---SIM卡不识或者掉卡简单分析

    SIM卡不识或者掉卡简单分析 1. 识卡大体过程 2.不识卡问题 不识卡的主要原因:  ①Modem发生错误,异常或者重启.  ②没有收到卡回的ATR  ③有收到卡回的ATR,但是后面跟卡通信出现异常 ...

  5. Android后台耗电分析及优化

    原文见: 在路上的blog Android后台耗电分析及优化 一.什么是耗电优化? 二.耗电优化第一个方向:优化后台耗电 1.唤醒锁定操作卡住(前台&后台) 2.唤醒次数过多 3.WLAN扫描 ...

  6. android释放acitity内存,Android 内存泄漏分析与解决方法

    在分析Android内存泄漏之前,先了解一下JAVA的一些知识 1. JAVA中的对象的创建 使用new指令生成对象时,堆内存将会为此开辟一份空间存放该对象 垃圾回收器回收非存活的对象,并释放对应的内 ...

  7. Android源码分析-全面理解Context

    前言 Context在android中的作用不言而喻,当我们访问当前应用的资源,启动一个新的activity的时候都需要提供Context,而这个Context到底是什么呢,这个问题好像很好回答又好像 ...

  8. Android Studio +MAT 分析内存泄漏实战

    点击打开链接 对于内存泄漏,在Android中如果不注意的话,还是很容易出现的,尤其是在Activity中,比较容易出现,下面我就说下自己是如何查找内存泄露的. 首先什么是内存泄漏? 内存泄漏就是一些 ...

  9. Android `AsyncTask`简要分析

    Android `AsyncTask`简要分析 AsyncTask简要分析 经典异步任务:AsyncTask,使用场景有:批量下载,批量拷贝等.官方文档就直接给出了一个批量下载的示例. private ...

最新文章

  1. 脑细胞膜等效神经网路
  2. SAP UI5 应用开发教程之六十九 - 如何从 SAP UI5 Not Found 页面跳转回到正常的应用页面
  3. P5591 小猪佩奇学数学(单位根反演)
  4. 压缩感知先进——关于稀疏矩阵
  5. (王道408考研操作系统)第一章计算机系统概述-第一节3:操作系统的运行机制与体系结构
  6. 探讨对理想团队模式构建的设想及软件流程的理解
  7. RTSP,RTP,RTCP的区别
  8. react —— diff算法与VDOM
  9. 使用axios 报 name.toUpperCase is not a function
  10. chrome developer tool 调试技巧2
  11. 简易的机器人聊天_如何制作一个简单的聊天机器人
  12. 布谷鸟沙盒分析静态文件_布谷鸟cuckoo
  13. 斯坦福大学自然语言处理第四课“语言模型(Language Modeling)”
  14. 基于特征全埋点的精排ODL实践总结
  15. java基于ssm的网上图书商城
  16. 在AI眼前“隐身”,用特制贴欺骗AI计算机视觉
  17. IT开发的岔路口:究竟是Java好还是嵌入式好?
  18. 【转】嵌入式开发正在日薄西山_有道理哦
  19. 七十年代译制片机器人的_老电影合集,怀旧经典电影,50,60,70,80年代,战争片,故事片,译制片...
  20. 赛门铁克:看***如何能够通过LED灯泡窃取你的隐私

热门文章

  1. 初来扎到啊(觉得有些神圣尼)
  2. curse库的使用总结
  3. 用计算机进行文本信息的加工处理,前面我们已经学了用计算机进行文本信息的加工与表达过程.ppt...
  4. 学习安装unik环境——过程一
  5. Unity3D疫情传播模拟器完整代码
  6. 自媒体攻略合集,教你如何做一名能赚钱的自媒体人
  7. excel如何生成各种图
  8. Androidstudio集成Butterknife后get和set方法不能用了处理办法(java.lang.IllegalArgumentException: cannot add an acti)
  9. linux 系统业务迁移,记录一次linux系统迁移过程
  10. Gradle - Groovy Language