PowerManagerService提供Android系统的电源管理服务,主要功能是控制系统的待机状态,控制显示屏的开关和亮度调节等。
PowerManagerService在systemserver中创建,加入到serviceManager中:
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
先从构造函数分析,代码如下:
public PowerManagerService(Context context) { super(context); mContext = context; //创建处理消息的线程 mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_DISPLAY, false /*allowIo*/); mHandlerThread.start(); //创建Handler,注意mHandlerThread.getLooper(),每一个线程都只有一个looper,这样消息的处理会放在这个线程中 mHandler = new PowerManagerHandler(mHandlerThread.getLooper()); synchronized (mLock) { mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks"); mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display"); //防止cpu进入睡眠状态 mDisplaySuspendBlocker.acquire(); mHoldingDisplaySuspendBlocker = true; mHalAutoSuspendModeEnabled = false; mHalInteractiveModeEnabled = true; //当前系统状态正常运行状态 mWakefulness = WAKEFULNESS_AWAKE; nativeInit(); nativeSetAutoSuspend(false); nativeSetInteractive(true); } }
构造函数比较简单,创建了一个接受消息处理的线程,cpu持锁不让手机睡眠,以及一些变量的初始化。
SystemServer创建完PowerManagerService后,继续调用SystemReady方法,再做一些初始化的工作,代码如下:
public void systemReady(IAppOpsService appOps) { synchronized (mLock) { mSystemReady = true; mAppOps = appOps; //android5.0后的新方法,localService可以直接取,在4.4中这样service是在init中传对象进来的 mDreamManager = getLocalService(DreamManagerInternal.class); mDisplayManagerInternal = getLocalService(DisplayManagerInternal.class); mPolicy = getLocalService(WindowManagerPolicy.class); mBatteryManagerInternal = getLocalService(BatteryManagerInternal.class); PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); //获取缺省、最大、最小屏幕亮度 mScreenBrightnessSettingMinimum = pm.getMinimumScreenBrightnessSetting(); mScreenBrightnessSettingMaximum = pm.getMaximumScreenBrightnessSetting(); mScreenBrightnessSettingDefault = pm.getDefaultScreenBrightnessSetting(); //创建sensorManager和sersorservice交互 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. mBatteryStats = BatteryStatsService.getService(); mNotifier = new Notifier(Looper.getMainLooper(), mContext, mBatteryStats, mAppOps, 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); // 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); // 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.Secure.getUriFor( Settings.Secure.SLEEP_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); resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ), false, mSettingsObserver, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.Global.getUriFor( Settings.Global.LOW_POWER_MODE), false, mSettingsObserver, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.Global.getUriFor( Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL), false, mSettingsObserver, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.Global.getUriFor( Settings.Global.THEATER_MODE_ON), false, mSettingsObserver, UserHandle.USER_ALL); // Go. readConfigurationLocked(); updateSettingsLocked(); mDirty |= DIRTY_BATTERY_STATE; updatePowerStateLocked(); } }
从在android5.1.1中,service一般都会继承一个虚类SystemService,在其中定义了两个接口onStart和onBootPhase,分别是PowerManagerService启动的时候会调用,而onBootPhase会在系统启动的各个阶段来调用,下面我们分别来看看在powerManagerService中这两个函数的实现:
@Override public void onStart() { publishBinderService(Context.POWER_SERVICE, new BinderService()); publishLocalService(PowerManagerInternal.class, new LocalService()); Watchdog.getInstance().addMonitor(this); Watchdog.getInstance().addThread(mHandler); }
在onstart函数中,必须把一些接口publish,像在之前Binder的接口,都是通过PowerManagerService extends IPowerManager.Stub形式在PowerManagerService中实现接口
而在android5.1.1中都是通过方式重新定义一个类,然后把这个类publish出去。
private final class BinderService extends IPowerManager.Stub { @Override // Binder call public void acquireWakeLockWithUid(IBinder lock, int flags, String tag, String packageName, int uid) { if (uid < 0) { uid = Binder.getCallingUid(); } acquireWakeLock(lock, flags, tag, packageName, new WorkSource(uid), null); } @Override // Binder call public void powerHint(int hintId, int data) { if (!mSystemReady) { // Service not ready yet, so who the heck cares about power hints, bah. return; } mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); powerHintInternal(hintId, data); } @Override // Binder call public void acquireWakeLock(IBinder lock, int flags, String tag, String packageName, WorkSource ws, String historyTag) {
。。。。。。。。。。。。。。而localservice都是一些本地的服务,不是通过Binder实现的。
我们接下来从,powerManager中的wakeLock说起,在powerManager中调用newWakeLock接口会生成一个WakeLock对象,而调用器acqure方法,最终会调用PowerManagerService中的acquireWakeLock方法
而具体的WakeLock有几种如下:
PARTIAL_WAKE_LOCK:只保持CPU运行,屏幕和键盘光关闭。
FULL_WAKE_LOCK:都不关闭
SCREEN_BRIGHT_WAKE_LOCK:屏幕背光不关闭,键盘光关闭
SCREEN_DIM_WAKE_LOCK:屏幕背光不关闭,键盘光关闭。但是屏幕背光可以变暗
PROXIMITY_SCREEN_OFF_WAKE_LOCK当持有这种类型wakelock,当距离传感器被遮挡,屏幕将被关闭。打电话时用这个功能
在PowerManagerService中的acquieWakeLock先要检查权限然后调用acquireWakeLockInternal接口,代码如下:
private void acquireWakeLockInternal(IBinder lock, int flags, String tag, String packageName, WorkSource ws, String historyTag, int uid, int pid) { synchronized (mLock) { WakeLock wakeLock; //查找wakelock int index = findWakeLockIndexLocked(lock); boolean notifyAcquire; if (index >= 0) {查找到 wakeLock = mWakeLocks.get(index); if (!wakeLock.hasSameProperties(flags, tag, ws, uid, pid)) {属性不一样,更新 // Update existing wake lock. This shouldn't happen but is harmless. notifyWakeLockChangingLocked(wakeLock, flags, tag, packageName, uid, pid, ws, historyTag); wakeLock.updateProperties(flags, tag, packageName, ws, historyTag, uid, pid); } notifyAcquire = false; } else {没找到,重新建立,添加 wakeLock = new WakeLock(lock, flags, tag, packageName, ws, historyTag, uid, pid); try { lock.linkToDeath(wakeLock, 0); } catch (RemoteException ex) { throw new IllegalArgumentException("Wake lock is already dead."); } mWakeLocks.add(wakeLock); notifyAcquire = true; } //看是否需要点亮屏幕 applyWakeLockFlagsOnAcquireLocked(wakeLock, uid); //整个PowermanagerService用来记录各个状态变化的一个标志位 mDirty |= DIRTY_WAKE_LOCKS; //更新各个状态 updatePowerStateLocked(); if (notifyAcquire) { // This needs to be done last so we are sure we have acquired the // kernel wake lock. Otherwise we have a race where the system may // go to sleep between the time we start the accounting in battery // stats and when we actually get around to telling the kernel to // stay awake. notifyWakeLockAcquiredLocked(wakeLock); } } }
整个PowermanagerService都是靠一个mDirty的各个标志位来记录各个状态的变化,随后会调用一个updatePowerStateLocked来更新各个状态。
同样解锁会调用到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)); } if ((flags & PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY) != 0) { mRequestWaitForNegativeProximity = true; } //去除wakelock wakeLock.mLock.unlinkToDeath(wakeLock, 0); removeWakeLockLocked(wakeLock, index); } } PowerManagerService中最终各个接口都会调一个函数updatePowerStateLocked,主要用来更新power的各个状态 private void updatePowerStateLocked() { if (!mSystemReady || mDirty == 0) {各个状态没有变化 return; } if (!Thread.holdsLock(mLock)) { Slog.wtf(TAG, "Power manager lock was not held when calling updatePowerStateLocked"); } Trace.traceBegin(Trace.TRACE_TAG_POWER, "updatePowerState"); try { // Phase 0: Basic state updates. //更新充电的各个状态(是否充电、电池电量、充电方式、是否低电量),以及更新低功耗模式(android5.0增加的) updateIsPoweredLocked(mDirty); //更新mStayOn状态,为true,屏幕常亮 updateStayOnLocked(mDirty); //更新屏幕是否最亮的状态是否持续 updateScreenBrightnessBoostLocked(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; for (;;) { int dirtyPhase1 = mDirty; dirtyPhase2 |= dirtyPhase1; mDirty = 0; //更新mWakeLockSummary的状态 updateWakeLockSummaryLocked(dirtyPhase1); //更新mUserActivitySummary状态 updateUserActivitySummaryLocked(now, dirtyPhase1); if (!updateWakefulnessLocked(dirtyPhase1)) { break; } } // Phase 2: Update display power state. boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);//更新display状态,在displaypowercontrol中会控制亮度,灭屏等 // Phase 3: Update dream state (depends on display ready signal). //更新梦的状态,用dreammanager控制梦,powermanagerservice中记录mWakefulness updateDreamLocked(dirtyPhase2, displayBecameReady); // Phase 4: Send notifications, if needed. if (mDisplayReady) { finishWakefulnessChangeLocked(); } // Phase 5: Update suspend blocker. // Because we might release the last suspend blocker here, we need to make sure // we finished everything else first! //更新睡眠锁,以及是否持锁和释放锁 updateSuspendBlockerLocked(); } finally { Trace.traceEnd(Trace.TRACE_TAG_POWER); } }
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 (shouldNapAtBedTimeLocked()) { //当前状态设置为睡眠状态 changed = napNoUpdateLocked(time, Process.SYSTEM_UID); } else { //当前状态设置为假寐状态 changed = goToSleepNoUpdateLocked(time, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, Process.SYSTEM_UID); } } } return changed; }
private boolean isBeingKeptAwakeLocked() { return mStayOn || mProximityPositive//距离传感器 || (mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) != 0//wakelock锁 || (mUserActivitySummary & (USER_ACTIVITY_SCREEN_BRIGHT | USER_ACTIVITY_SCREEN_DIM)) != 0//用户行为、和用户点击屏幕、自动灭屏时间等有关 || mScreenBrightnessBoostInProgress;\\是否要保持处于最亮状态 } private boolean isItBedTimeYetLocked() { //当启动完成、并且设备不必保持唤醒状态是的时候返回true return mBootCompleted && !isBeingKeptAwakeLocked(); }
private void handleSandman() { // runs on handler thread // 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()) { //在做梦中 if (mDreamsBatteryLevelDrainCutoffConfig >= 0 && mBatteryLevel < mBatteryLevelWhenDreamStarted - mDreamsBatteryLevelDrainCutoffConfig && !isBeingKeptAwakeLocked()) { // If the user activity timeout expired and the battery appears // to be draining faster than it is charging then stop dreaming // and go to sleep. Slog.i(TAG, "Stopping dream because the battery appears to " + "be draining faster than it is charging. " + "Battery level when dream started: " + mBatteryLevelWhenDreamStarted + "%. " + "Battery level now: " + mBatteryLevel + "%."); } else { //继续做梦 return; // continue dreaming } } // Dream has ended or will be stopped. Update the power state. //结束做梦,要么唤醒、要么继续goToSleep if (isItBedTimeYetLocked()) { goToSleepNoUpdateLocked(SystemClock.uptimeMillis(), PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, Process.SYSTEM_UID); updatePowerStateLocked(); } else { wakeUpNoUpdateLocked(SystemClock.uptimeMillis(), 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. reallyGoToSleepNoUpdateLocked(SystemClock.uptimeMillis(), Process.SYSTEM_UID); updatePowerStateLocked(); } } // Stop dream.能走到这说明,肯定结束做梦 if (isDreaming) { mDreamManager.stopDream(false /*immediate*/); } }
private void updateSuspendBlockerLocked() { final boolean needWakeLockSuspendBlocker = ((mWakeLockSummary & WAKE_LOCK_CPU) != 0);//是否要cpu持锁 final boolean needDisplaySuspendBlocker = needDisplaySuspendBlockerLocked();//是否display要持锁 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) { mWakeLockSuspendBlocker.acquire(); mHoldingWakeLockSuspendBlocker = true; } if (needDisplaySuspendBlocker && !mHoldingDisplaySuspendBlocker) { mDisplaySuspendBlocker.acquire(); mHoldingDisplaySuspendBlocker = true; } // Inform the power HAL about interactive mode. // Although we could set interactive strictly based on the wakefulness // as reported by isInteractive(), it is actually more desirable to track // the display policy state instead so that the interactive state observed // by the HAL more accurately tracks transitions between AWAKE and DOZING. // Refer to getDesiredScreenPolicyLocked() for details. if (mDecoupleHalInteractiveModeFromDisplayConfig) { // When becoming non-interactive, we want to defer sending this signal // until the display is actually ready so that all transitions have // completed. This is probably a good sign that things have gotten // too tangled over here... if (interactive || mDisplayReady) {//当屏幕亮着|| 当屏幕暗着,displayPowerControl准备好了,进入该条件设置 setHalInteractiveModeLocked(interactive); } } // Then release suspend blockers if needed. if (!needWakeLockSuspendBlocker && mHoldingWakeLockSuspendBlocker) { mWakeLockSuspendBlocker.release(); mHoldingWakeLockSuspendBlocker = false; } if (!needDisplaySuspendBlocker && mHoldingDisplaySuspendBlocker) { mDisplaySuspendBlocker.release(); mHoldingDisplaySuspendBlocker = false; } // Enable auto-suspend if needed. if (autoSuspend && mDecoupleHalAutoSuspendModeFromDisplayConfig) { setHalAutoSuspendModeLocked(true); } }
private void goToSleepInternal(long eventTime, int reason, int flags, int uid) { synchronized (mLock) { //返回true,才更新状态 if (goToSleepNoUpdateLocked(eventTime, reason, flags, uid)) { updatePowerStateLocked(); } } } @SuppressWarnings("deprecation") private boolean goToSleepNoUpdateLocked(long eventTime, int reason, int flags, int uid) { if (DEBUG_SPEW) { Slog.d(TAG, "goToSleepNoUpdateLocked: eventTime=" + eventTime + ", reason=" + reason + ", flags=" + flags + ", uid=" + uid); } if (eventTime < mLastWakeTime || mWakefulness == WAKEFULNESS_ASLEEP || mWakefulness == WAKEFULNESS_DOZING || !mBootCompleted || !mSystemReady) { return false; } Trace.traceBegin(Trace.TRACE_TAG_POWER, "goToSleep"); try { switch (reason) {//说明原因 case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN: Slog.i(TAG, "Going to sleep due to device administration policy " + "(uid " + uid +")..."); break; 。。。。。。。。。。。。。 } mLastSleepTime = eventTime; mSandmanSummoned = true; setWakefulnessLocked(WAKEFULNESS_DOZING, reason); // Report the number of wake locks that will be cleared by going to sleep. //统计wakelock的数量 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); // Skip dozing if requested. //直接进入睡眠 if ((flags & PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE) != 0) { reallyGoToSleepNoUpdateLocked(eventTime, uid); } } finally { Trace.traceEnd(Trace.TRACE_TAG_POWER); } return true; }