做黑彩票的网站赚钱,wordpress用手机写博客,建设银行网站打不开别的网站可以吗,创意网站页面设计hongxi.zhu 2023-7-28 Android 13 PowerManagerService(简称PMS)主要是负责协调、管理设备CPU资源#xff0c;并提供功能接口给应用框架层或应用层申请获取CPU资源的一个服务#xff0c;例如#xff1a;亮灭屏、关机、WakeLock管理、Dreamland(屏保模式)、休眠时间等行为。 … hongxi.zhu 2023-7-28 Android 13 PowerManagerService(简称PMS)主要是负责协调、管理设备CPU资源并提供功能接口给应用框架层或应用层申请获取CPU资源的一个服务例如亮灭屏、关机、WakeLock管理、Dreamland(屏保模式)、休眠时间等行为。
1. PMS的启动流程
PMS是在SystemServer的startBootstrapServices()中通过SystemServiceManager.startService()启动很多服务依赖PMS服务所以它需要尽早的启动并注册到ServiceManage中所以它在startBootstrapServices()中来启动
frameworks/base/services/java/com/android/server/SystemServer.javaprivate void startBootstrapServices(NonNull TimingsTraceAndSlog t) {t.traceBegin(StartPowerManager);mPowerManagerService mSystemServiceManager.startService(PowerManagerService.class);t.traceEnd();}SystemServiceManager.startService()通过反射拿到PowerManagerService对象
frameworks/base/services/core/java/com/android/server/SystemServiceManager.javapublic T extends SystemService T startService(ClassT serviceClass) {try {final String name serviceClass.getName();final T service;try {//获取类构造方法构造对应对象ConstructorT constructor serviceClass.getConstructor(Context.class);service constructor.newInstance(mContext);} catch (InstantiationException ex) {throw new RuntimeException(Failed to create service name : service could not be instantiated, ex);} catch (IllegalAccessException ex) {...}//调用startService启动服务startService(service);//返回服务对象return service;} finally {Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);}}public void startService(NonNull final SystemService service) {// Check if already startedString className service.getClass().getName();mServiceClassnames.add(className);// Register it.//注册服务mServices.add(service);// Start it.long time SystemClock.elapsedRealtime();try {//调用服务的onStart()方法启动服务service.onStart();} catch (RuntimeException ex) {throw new RuntimeException(Failed to start service service.getClass().getName() : onStart threw an exception, ex);}warnIfTooLong(SystemClock.elapsedRealtime() - time, service, onStart);}将服务加入mServices列表中然后调用服务的onStart()方法mServices列表是管理着所有需要接收系统启动过程中生命周期的服务
1.1 PowerManagerService构造方法
frameworks/base/services/core/java/com/android/server/power/PowerManagerService.javapublic PowerManagerService(Context context) {this(context, new Injector()); //内部类Injector对象管理创建其他对象}PowerManagerService(Context context, Injector injector) {super(context);mContext context;mBinderService new BinderService(); //用于IPC交互, BinderService 继承于 IPowerManager.StubmLocalService new LocalService(); //用户跨线程交互(SystemServer进程内部)//创建一个NativeWrapper对象管理所有的native交互mNativeWrapper injector.createNativeWrapper();//创建SystemPropertiesWrapper对象用于获取系统属性等信息mSystemProperties injector.createSystemPropertiesWrapper();mClock injector.createClock();//内部类Injector对象管理创建其他对象mInjector injector;//创建PMS主线程优先级为DISPLAY级别mHandlerThread new ServiceThread(TAG,Process.THREAD_PRIORITY_DISPLAY, /* allowIo */ false);mHandlerThread.start(); //启动主线程//创建PMS主线程HandlermHandler injector.createHandler(mHandlerThread.getLooper(),new PowerManagerHandlerCallback());//用于管理Settings.Global下的常量mConstants new Constants(mHandler);//创建AmbientDisplayConfiguration对象管理一些显示配置如AODmAmbientDisplayConfiguration mInjector.createAmbientDisplayConfiguration(context);//创建AmbientDisplaySuppressionController对象用于管理AmbientDisplay显示相关和AOD显示有关mAmbientDisplaySuppressionController mInjector.createAmbientDisplaySuppressionController(context);//创建AttentionDetector对象用来检查用户活动是否需要再更新mAttentionDetector new AttentionDetector(this::onUserAttention, mLock);mFaceDownDetector new FaceDownDetector(this::onFlip);mScreenUndimDetector new ScreenUndimDetector();//创建BatterySavingStats对象用来记录电池耗电率mBatterySavingStats new BatterySavingStats(mLock);//创建BatterySaverPolicy对象管理一些省电策略mBatterySaverPolicy mInjector.createBatterySaverPolicy(mLock, mContext, mBatterySavingStats);//创建BatterySaverController对象管理省电策略的切换mBatterySaverController mInjector.createBatterySaverController(mLock, mContext,mBatterySaverPolicy, mBatterySavingStats);//创建BatterySaverStateMachine对象负责省电策略的开启/关闭mBatterySaverStateMachine mInjector.createBatterySaverStateMachine(mLock, mContext,mBatterySaverController);mLowPowerStandbyController mInjector.createLowPowerStandbyController(mContext,Looper.getMainLooper());mInattentiveSleepWarningOverlayController mInjector.createInattentiveSleepWarningController();mAppOpsManager injector.createAppOpsManager(mContext);mPowerGroupWakefulnessChangeListener new PowerGroupWakefulnessChangeListener();... //获取一些配置初始值synchronized (mLock) {//创建SuspendBlockerImpl对象PowerManagerService.Booting类型对象负责在开机时负责保活CPUmBootingSuspendBlocker mInjector.createSuspendBlocker(this, PowerManagerService.Booting);//创建SuspendBlockerImpl对象WakeLock的最终反映PowerManagerService.WakeLocks类型对象负责保活CPUmWakeLockSuspendBlocker mInjector.createSuspendBlocker(this, PowerManagerService.WakeLocks);//创建SuspendBlockerImpl对象PowerManagerService.Display类型对象负责保持屏幕常亮mDisplaySuspendBlocker mInjector.createSuspendBlocker(this, PowerManagerService.Display);//申请mBootingSuspendBlocker保持开机启动过程CPU资源if (mBootingSuspendBlocker ! null) {mBootingSuspendBlocker.acquire();mHoldingBootingSuspendBlocker true;}//申请mDisplaySuspendBlocker保持屏幕常亮if (mDisplaySuspendBlocker ! null) {mDisplaySuspendBlocker.acquire(HOLDING_DISPLAY_SUSPEND_BLOCKER);mHoldingDisplaySuspendBlocker true;}//auto-suspend 模式是否可用mHalAutoSuspendModeEnabled false;//是否是可交互状态mHalInteractiveModeEnabled true;//设置设备状态为唤醒状态mWakefulnessRaw WAKEFULNESS_AWAKE;//静默模式会控制背光的点亮使用场景不多sQuiescent mSystemProperties.get(SYSTEM_PROPERTY_QUIESCENT, 0).equals(1)|| InitProperties.userspace_reboot_in_progress().orElse(false);//mNativeWrapper对象进行native层初始化工作mNativeWrapper.nativeInit(this);mNativeWrapper.nativeSetAutoSuspend(false); //设置auto suspend状态mNativeWrapper.nativeSetPowerMode(Mode.INTERACTIVE, true); //设置interactive状态mNativeWrapper.nativeSetPowerMode(Mode.DOUBLE_TAP_TO_WAKE, false); //设置双击唤醒模式状态mInjector.invalidateIsInteractiveCaches();}}构造方法主要做了几件事
创建用于IPC的BinderService对象和system_server进程内跨线程交互的LocalService对象创建PMS的主线程并使用该HandlerThread的Looper实例化PowerManagerHandler将作为PMS主线程Handler进行Message的处理相关配置参数的读取如系统配置各种亮度参数获取了三个Suspend锁对象SuspendBlocker是一种锁机制上层申请的wakelock锁在PMS中都会反映为SuspendBlocker锁通过mNativeWrapper对象和底层进行状态交互
1.2 onStart()中注册发布服务
执行完构造方法后接着执行了onStart()
frameworks/base/services/core/java/com/android/server/power/PowerManagerService.javaOverridepublic void onStart() {//向ServiceManager进程注册当前服务mBinderService(BinderServic才是PMS的Binder服务端)publishBinderService(Context.POWER_SERVICE, mBinderService, /* allowIsolated */ false,DUMP_FLAG_PRIORITY_DEFAULT | DUMP_FLAG_PRIORITY_CRITICAL);//发布本地服务提供给SystemServer进程中其他组件访问publishLocalService(PowerManagerInternal.class, mLocalService);//添加watchdog监听Watchdog.getInstance().addMonitor(this);Watchdog.getInstance().addThread(mHandler);}这个方法中会进行对PMS的Binder服务和Local服务的注册BinderService注册后其他模块中就可以通过ServiceManager获取到对应的Binder对象进行IPC通信LocalService注册后在system_server进程内就可以通过获取LocalService对象跨线程交互。 PMS中的BinderService是继承自IPowerManager.Stub的一个内部类BinderServiceIPowerManager.Stub继承自Binder并且实现了IPowerManager因此PMS和其他模块的跨进程交互实际上就是通过PMS.BinderService实现。
Binder服务注册的过程在SystemService中的publishBinderService方法通过ServiceManager.addService注册
frameworks/base/services/core/java/com/android/server/SystemService.javaprotected final void publishBinderService(String name, IBinder service,boolean allowIsolated, int dumpPriority) {ServiceManager.addService(name, service, allowIsolated, dumpPriority);}frameworks/base/core/java/android/os/ServiceManager.javapublic static void addService(String name, IBinder service) {addService(name, service, false, IServiceManager.DUMP_FLAG_PRIORITY_DEFAULT);}当通过ServiceManager注册后就可以根据Context.POWER_SERVICE在其他服务中获得服务代理对象进行跨进程交互了。
LocalService则用于system_server进程内部交互注册的对象是另一个内部类——继承自PowerManagerInternal的LocalService(带有Internal的类一般都在System进程内使用)。Local Service的注册是在LocalServices中进行其注册方法如下
frameworks/base/services/core/java/com/android/server/SystemService.javaprotected final T void publishLocalService(ClassT type, T service) {LocalServices.addService(type, service);}frameworks/base/core/java/com/android/server/LocalServices.javapublic static T void addService(ClassT type, T service) {synchronized (sLocalServiceObjects) {if (sLocalServiceObjects.containsKey(type)) {throw new IllegalStateException(Overriding service registration);}sLocalServiceObjects.put(type, service); //添加到sLocalServiceObjects容器中}}1.3 onBootPhase()进行各个启动阶段的处理
回到SytemServer中startBootstrapServices()方法中PMS的实例化和注册流程执行完成了接下来会开始执行SystemService的生命周期会开始执行SystemServiceManager.onBootPhase()这个方法为所有的已进行实例化和注册的服务(通过前面的startService启动的服务)设置启动阶段以便在不同的启动阶段进行不同的工作方法如下
frameworks/base/services/core/java/com/android/server/SystemServiceManager.javapublic void startBootPhase(NonNull TimingsTraceAndSlog t, int phase) {mCurrentPhase phase;try {final int serviceLen mServices.size();for (int i 0; i serviceLen; i) {final SystemService service mServices.get(i);try {service.onBootPhase(mCurrentPhase);} catch (Exception ex) {...}}} finally {t.traceEnd();}if (phase SystemService.PHASE_BOOT_COMPLETED) {final long totalBootTime SystemClock.uptimeMillis() - mRuntimeStartUptime;t.logDuration(TotalBootTime, totalBootTime);SystemServerInitThreadPool.shutdown();}}在SystemServiceManager#startBootPhase()中通过在SystemServiceManager中传入不同的形参遍历SystemServiceManager#mServices列表调用各个SystemService#onBootPhase(int)方法根据参数在方法实现中完成不同的工作。在SystemService中定义了七个代表启动阶段的参数 PHASE_WAIT_FOR_DEFAULT_DISPLAY第一个启动阶段用于在启动PKMS之前需要确保已经存在默认逻辑屏只有DisplayManagerService使用该阶段 PHASE_LOCK_SETTINGS_READY第二个启动阶段该阶段的执行意味这Lock Pattern/Password相关服务已经准备完毕只有DisplayManagerService使用该阶段 PHASE_SYSTEM_SERVICES_READY第三个启动阶段该阶段的执行意味这其他服务可以安全地使用核心系统服务; PHASE_DEVICE_SPECIFIC_SERVICES_READY第四个启动阶段该阶段的执行意味这其他服务可以安全地使用设备指定的一些系统服务这些服务在config_deviceSpecificSystemServices中进行配置; PHASE_ACTIVITY_MANAGER_READY第五个启动阶段该阶段的执行意味这其他AMS组件已经启动完成可以进行广播操作; PHASE_THIRD_PARTY_APPS_CAN_START第六个启动阶段该阶段的执行意味这系统可以启动APP并可以进行service的bind/start操作了 PHASE_BOOT_COMPLETED第六个启动阶段该阶段的执行意味这启动完成Home应用也已经启动完成并且可以和设备进行交互了。 PMS#onBootPhase()方法只对以上的3个阶段做了处理
frameworks/base/services/core/java/com/android/server/power/PowerManagerService.javaOverridepublic void onBootPhase(int phase) {if (phase PHASE_SYSTEM_SERVICES_READY) {systemReady(); //如果是PHASE_SYSTEM_SERVICES_READY阶段则调用PMS的systemReady()} else if (phase PHASE_THIRD_PARTY_APPS_CAN_START) {//统计系统启动次数adb shell settings get global boot_count可查看incrementBootCount();} else if (phase PHASE_BOOT_COMPLETED) {synchronized (mLock) {final long now mClock.uptimeMillis();mBootCompleted true; //表示启动完成mDirty | DIRTY_BOOT_COMPLETED; //最重要的标志位//执行BatterySaverStateMachine.onBootCompleted()mBatterySaverStateMachine.onBootCompleted();//更新用户活动时间userActivityNoUpdateLocked(now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);//更新全局状态信息updatePowerStateLocked();if (sQuiescent) {sleepPowerGroupLocked(mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP),mClock.uptimeMillis(),PowerManager.GO_TO_SLEEP_REASON_QUIESCENT,Process.SYSTEM_UID);}//注册DeviceStateManager服务的回调接口mContext.getSystemService(DeviceStateManager.class).registerCallback(new HandlerExecutor(mHandler), new DeviceStateListener());}}}mDirty是一个二进制的标记位用来表示电源状态哪一部分发生了改变通过对其进行置位|操作、清零操作得到二进制数各个位的值(0或1)进行不同的处理这个变量非常重要。 最后调用updatePowerStateLocked()方法这是整个PMS中最重要的方法会在下面进行详细分析。 此时启动过程中SystemService的生命周期方法全部执行完毕。
1.4 sytemReady()
当onBootPhase处于PHASE_SYSTEM_SERVICES_READY阶段时执行sytemReady() private void systemReady() {//方法太长了}这个方法中主要做了以下几个操作方法太长了相关方法代码就不再粘贴:
获取各类本地服务和远程服务如Dreamland服务(DreamMangerService)、窗口服务(PhoneWindowManager)、电池状态监听(BatteryService)等服务 注册用于和其他SytemService交互的广播 调用updateSettingsLocked()方法更新Settings中值的变化 调用readConfigurationLocked()方法读取配置文件中的默认值 注册SettingsObserver监听
到此为止PMS的启动过程完成。
2. 核心方法updatePowerStateLocked()
updatePowerStateLocked()方法是整个PMS模块的核心方法也是整个PSM中最重要的一个方法它用来更新整个Power状态。当Power状态发生改变时如亮灭屏、电池状态改变、暗屏、WakeLock锁申请/释放…都会调用该方法并调用其他同级方法进行各个状态的更新
frameworks/base/services/core/java/com/android/server/power/PowerManagerService.javaprivate void updatePowerStateLocked() {if (!mSystemReady || mDirty 0 || mUpdatePowerStateInProgress) {return;}Trace.traceBegin(Trace.TRACE_TAG_POWER, updatePowerState);mUpdatePowerStateInProgress true;try {// Phase 0: Basic state updates. 基本状态的更新updateIsPoweredLocked(mDirty); //更新充电状态updateStayOnLocked(mDirty); //更新当前是否为屏幕常亮状态由mStayOn控制updateScreenBrightnessBoostLocked(mDirty); //更新是否需要增强亮度变量// Phase 1: Update wakefulness. 更新唤醒状态// Loop because the wake lock and user activity computations are influenced// by changes in wakefulness.// 循环是因为唤醒锁和用户活动计算受到唤醒状态变化的影响。final long now mClock.uptimeMillis();int dirtyPhase2 0;for (;;) { // 循环进行更新流程直到updateWakefulnessLocked()返回falseint dirtyPhase1 mDirty;dirtyPhase2 | dirtyPhase1;mDirty 0; //清空标记// 更新用于统计wakelock的标记值mWakeLockSummary属性updateWakeLockSummaryLocked(dirtyPhase1);// 更新用于统计用户活动状态的标记值mUserActivitySummary属性updateUserActivitySummaryLocked(now, dirtyPhase1);// 更新细微模式状态updateAttentiveStateLocked(now, dirtyPhase1);// 更新唤醒状态如果状态改变返回trueif (!updateWakefulnessLocked(dirtyPhase1)) {break;}}// Phase 2: Lock profiles that became inactive/not kept awake.updateProfilesLocked(now);// Phase 3: Update power state of all PowerGroups. 更新PowerGroups状态final boolean powerGroupsBecameReady updatePowerGroupsLocked(dirtyPhase2);// Phase 4: Update dream state (depends on power group ready signal). 更新Dreamland状态updateDreamLocked(dirtyPhase2, powerGroupsBecameReady);// Phase 5: Send notifications, if needed. 如果wakefulness改变做最后的收尾工作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! 更新SuspendBlocker锁状态updateSuspendBlockerLocked();} finally {Trace.traceEnd(Trace.TRACE_TAG_POWER);mUpdatePowerStateInProgress false;}}下面对以上内容中所有方法逐个进行分析
2.1 updateIsPoweredLocked()更新充电状态
这个方法用于更新mIsPowered属性它代表当前的充电状态。插拔USB点亮屏幕功能的逻辑就是在这个方法中。该方法如下 private void updateIsPoweredLocked(int dirty) {if ((dirty DIRTY_BATTERY_STATE) ! 0) {// 记录旧值final boolean wasPowered mIsPowered;final int oldPlugType mPlugType;// 获取新值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; // 设置标记位DIRTY_IS_POWERED// 更新无线充电状态final boolean dockedOnWirelessCharger mWirelessChargerDetector.update(mIsPowered, mPlugType);final long now mClock.uptimeMillis();// 插拔USB是否需要亮屏if (shouldWakeUpWhenPluggedOrUnpluggedLocked(wasPowered, oldPlugType,dockedOnWirelessCharger)) {// 亮屏流程wakePowerGroupLocked(mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP),now, PowerManager.WAKE_REASON_PLUGGED_IN,android.server.power:PLUGGED: mIsPowered, Process.SYSTEM_UID,mContext.getOpPackageName(), Process.SYSTEM_UID);}// 更新用户活动时间userActivityNoUpdateLocked(mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP), now,PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);// 播放充电提示音和动画if (mBootCompleted) { //只有在开机完成后才允许播放充电提示声if (mIsPowered !BatteryManager.isPlugWired(oldPlugType) BatteryManager.isPlugWired(mPlugType)) {mNotifier.onWiredChargingStarted(mUserId);} else if (dockedOnWirelessCharger) {mNotifier.onWirelessChargingStarted(mBatteryLevel, mUserId);}}}//将充电状态更新到BatterySaverStateMachinemBatterySaverStateMachine.setBatteryStatus(mIsPowered, mBatteryLevel, mBatteryLevelLow);}}只有对mDirty设置了DIRTY_BATTERY_STATE标记时才会进入这个方法中那么DIRTY_BATTERY_STATE在什么时候会设置呢一是当PMS执行systemReady()时二是当电池信息变化后由healthd模块上报给BatteryServiceBatteryService中则会发出广播Intent.ACTION_BATTERY_CHANGED来通知其他组件PMS中会接收这个广播并作出处理
frameworks/base/services/core/java/com/android/server/power/PowerManagerService.javafinal class BatteryReceiver extends BroadcastReceiver {Overridepublic void onReceive(Context context, Intent intent) {synchronized (mLock) {handleBatteryStateChangedLocked();}}}private void handleBatteryStateChangedLocked() {mDirty | DIRTY_BATTERY_STATE;updatePowerStateLocked();}因此只要电池状态发生变化就会执行这个方法。在这个方法中
首先更新一些如mIsPowered等全局变量。然后通过shouldWakeUpWhenPluggedOrUnpluggedLocked()方法判断是否需要亮屏这就是插拔USB点亮屏幕功能的逻辑。接下来执行userActivityNoUpdateLocked()方法更新用户活动时间这个时间决定了何时会自动灭屏用户每次操作手机(触摸、按键、Other)都会更新到当前时间用户最后活动时间 设置自动休眠时间 最终自动灭屏的时间点这个方法会在后面部分分析。再接下来则调用Notifier对象播放插拔USB音效或动画Notifier类是PMS模块中用于发送广播、异步通知其他组件的一个类。最后将充电状态传递给mBatterySaverStateMachine中进行省电策略的调整。
2.2 updateStayOnLocked()更新屏幕常亮状态
这个方法用来更新全局变量mStayOn的值如果把开发者选项—不锁定屏幕这个选项开启后则在充电时将保持常亮不会自动休眠
frameworks/base/services/core/java/com/android/server/power/PowerManagerService.javaprivate void updateStayOnLocked(int dirty) {if ((dirty (DIRTY_BATTERY_STATE | DIRTY_SETTINGS)) ! 0) {final boolean wasStayOn mStayOn;if (mStayOnWhilePluggedInSetting ! 0 !isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked()) {// 如果任意方式充电(AC/USB/wireless)返回truemStayOn mBatteryManagerInternal.isPowered(mStayOnWhilePluggedInSetting);} else {mStayOn false;}// 状态发生变化时向mDirty设置DIRTY_STAY_ON标记if (mStayOn ! wasStayOn) {mDirty | DIRTY_STAY_ON;}}}只有mDirty设置了DIRTY_BATTERY_STATE或DIRTY_SETTINGS标记位后才会执行该方法。DIRTY_BATTERY_STATE在电池状态发生变化后设置DIRTY_SETTINGS是在Settings中的值发生变化后设置mStayOnWhilePluggedInSetting就是从来自于Settings中不锁定屏幕的值如果发生变化且处于充电状态则会更新mStayOn变量的值。在自动灭屏流程中一旦mStayOn值为true则永远不会灭屏从而实现了“不锁定屏幕”这个功能。
2.3 updateScreenBrightnessBoostLocked()更新是否增强亮度
这个方法会更新表示增强亮度的全局变量mScreenBrightnessBoostInProgressPMS.BinderService提供了boostScreenBrightness()方法允许其他组件通过该接口将亮度调节到最大(短时间保持)并保持5s后恢复 private void updateScreenBrightnessBoostLocked(int dirty) {if ((dirty DIRTY_SCREEN_BRIGHTNESS_BOOST) ! 0) {if (mScreenBrightnessBoostInProgress) {final long now mClock.uptimeMillis();mHandler.removeMessages(MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT);if (mLastScreenBrightnessBoostTime mLastGlobalSleepTime) {final long boostTimeout mLastScreenBrightnessBoostTime SCREEN_BRIGHTNESS_BOOST_TIMEOUT;// 向主线程mHandler发出一个异步消息5s后会再次更新if (boostTimeout now) {Message msg mHandler.obtainMessage(MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT);msg.setAsynchronous(true);mHandler.sendMessageAtTime(msg, boostTimeout);return;}}// 表示增强亮度结束mScreenBrightnessBoostInProgress false;// 更新用户活动时间userActivityNoUpdateLocked(now,PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);}}}只有当mDirty设置了DIRTY_SCREEN_BRIGHTNESS_BOOST标记时才会执行这个方法。这个标记位就是通过boostScreenBrightness()设置这个功能在Google原生逻辑中有一个使用场景
// frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java//是否开启双击Power键定制行为(例如双击打开NFC,相机等)
mDoublePressOnPowerBehavior mContext.getResources().getInteger(com.android.internal.R.integer.config_doublePressOnPowerBehavior);// must match: config_doublePressOnPowerBehavior in config.xmlstatic final int MULTI_PRESS_POWER_NOTHING 0; //默认无static final int MULTI_PRESS_POWER_THEATER_MODE 1; //剧场模式static final int MULTI_PRESS_POWER_BRIGHTNESS_BOOST 2; //双击电源键会将亮度调到最大static final int MULTI_PRESS_POWER_LAUNCH_TARGET_ACTIVITY 3; //双击打开特定应用2.4 updateWakeLockSummaryLocked()更新WakeLock统计值
从这个方法开始到直到updateWakefulnessLocked()结束将会在一个for循环中执行。 该方法用来更新mWakeLockSummary属性它是用来记录所有WakeLock锁状态的状态值代表了所有的WakeLock在请求Display状时作为判断条件确定具体的请求状态。系统规定了系统休眠状态对WakeLock锁的使用影响如当系统休眠后常亮锁(PowerManager.SCREEN_BRIGHT等)将会被忽略系统唤醒后Doze锁(PowerManager.DOZE_WAKE_LOCK等将会被忽略 private void updateWakeLockSummaryLocked(int dirty) {if ((dirty (DIRTY_WAKE_LOCKS | DIRTY_WAKEFULNESS | DIRTY_DISPLAY_GROUP_WAKEFULNESS))! 0) {mWakeLockSummary 0; //初始值为0// 将每个ProfilePowerState的mWakeLockSummary也进行重置final int numProfiles mProfilePowerState.size();for (int i 0; i numProfiles; i) {mProfilePowerState.valueAt(i).mWakeLockSummary 0;}// 将每个mPowerGroups的setWakeLockSummaryLocked也进行重置for (int idx 0; idx mPowerGroups.size(); idx) {mPowerGroups.valueAt(idx).setWakeLockSummaryLocked(0);}int invalidGroupWakeLockSummary 0;final int numWakeLocks mWakeLocks.size();// 遍历mWakeLocks列表for (int i 0; i numWakeLocks; i) {final WakeLock wakeLock mWakeLocks.get(i);final Integer groupId wakeLock.getPowerGroupId();// a wakelock with an invalid group ID should affect all groupsif (groupId null || (groupId ! Display.INVALID_DISPLAY_GROUP !mPowerGroups.contains(groupId))) {continue;}final PowerGroup powerGroup mPowerGroups.get(groupId);// 获取每个WakeLock对应的Flag标记final int wakeLockFlags getWakeLockSummaryFlags(wakeLock);// 标记在mWakeLockSummary上mWakeLockSummary | wakeLockFlags;if (groupId ! Display.INVALID_DISPLAY_GROUP) {int wakeLockSummary powerGroup.getWakeLockSummaryLocked();wakeLockSummary | wakeLockFlags;powerGroup.setWakeLockSummaryLocked(wakeLockSummary);} else {invalidGroupWakeLockSummary | wakeLockFlags;}// 对每个ProfilePowerState#mWakeLockSummary也进行标记for (int j 0; j numProfiles; j) {final ProfilePowerState profile mProfilePowerState.valueAt(j);if (wakeLockAffectsUser(wakeLock, profile.mUserId)) {profile.mWakeLockSummary | wakeLockFlags;}}}for (int idx 0; idx mPowerGroups.size(); idx) {final PowerGroup powerGroup mPowerGroups.valueAt(idx);final int wakeLockSummary adjustWakeLockSummary(powerGroup.getWakefulnessLocked(),invalidGroupWakeLockSummary | powerGroup.getWakeLockSummaryLocked());powerGroup.setWakeLockSummaryLocked(wakeLockSummary);}// 根据系统状态对mWakeLockSummary进行调整mWakeLockSummary adjustWakeLockSummary(getGlobalWakefulnessLocked(),mWakeLockSummary);// 对每个ProfilePowerState#mWakeLockSummary也进行调整for (int i 0; i numProfiles; i) {final ProfilePowerState profile mProfilePowerState.valueAt(i);profile.mWakeLockSummary adjustWakeLockSummary(getGlobalWakefulnessLocked(),profile.mWakeLockSummary);}}}只有当mDirty设置了DIRTY_WAKE_LOCKS和DIRTY_WAKEFULNESS标记位时才会执行该方法。DIRTY_WAKE_LOCKS在申请WakeLock锁时设置DIRTY_WAKEFULNESS在系统唤醒状态发生变化时设置。 进入该方法后首先从保存了WakeLock的List中进行遍历并根据WakeLock类型给mWakeLockSummary设置标记这些标记位如下:
// frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java// Summarizes the state of all active wakelocks.static final int WAKE_LOCK_CPU 1 0; // 表示需要CPU保持唤醒状态static final int WAKE_LOCK_SCREEN_BRIGHT 1 1; // 表示持有FULL_WAKE_LOCK锁需要屏幕常亮static final int WAKE_LOCK_SCREEN_DIM 1 2; // 表示持有SCREEN_DIM_WAKE_LOCK锁需要保持dim不灭屏static final int WAKE_LOCK_BUTTON_BRIGHT 1 3; //表示持有FULL_WAKE_LOCK锁需要按键灯常亮static final int WAKE_LOCK_PROXIMITY_SCREEN_OFF 1 4; // 表示持有Psensor WakeLock锁static final int WAKE_LOCK_STAY_AWAKE 1 5; // only set if already awake // 表示保持屏幕常亮(只能用在awake状态时)static final int WAKE_LOCK_DOZE 1 6; // 表示持有DOZE_WAKE_LOCK锁static final int WAKE_LOCK_DRAW 1 7; //表示持有DRAW_WAKE_LOCK锁然后将根据系统状态进行调整:
// frameworks/base/services/core/java/com/android/server/power/PowerManagerService.javaprivate static int adjustWakeLockSummary(int wakefulness, int wakeLockSummary) {// Cancel wake locks that make no sense based on the current state.// 唤醒状态不处于Doze状态时忽略掉PowerManager.DOZE_WAKE_LOCK和PowerManager.DRAW_WAKE_LOCK两类型锁if (wakefulness ! WAKEFULNESS_DOZING) {wakeLockSummary ~(WAKE_LOCK_DOZE | WAKE_LOCK_DRAW);}// 唤醒状态处于Asleep状态或者Doze状态时忽略掉屏幕常亮锁、PSensor锁if (wakefulness WAKEFULNESS_ASLEEP|| (wakeLockSummary WAKE_LOCK_DOZE) ! 0) {wakeLockSummary ~(WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM| WAKE_LOCK_BUTTON_BRIGHT);if (wakefulness WAKEFULNESS_ASLEEP) {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) {// 唤醒状态处于Awake状态WAKE_LOCK_STAY_AWAKE只用于awake状态时if (wakefulness WAKEFULNESS_AWAKE) {wakeLockSummary | WAKE_LOCK_CPU | WAKE_LOCK_STAY_AWAKE;} else if (wakefulness WAKEFULNESS_DREAMING) { // 唤醒状态处于Awake状态WAKE_LOCK_STAY_AWAKE只用于awake状态时wakeLockSummary | WAKE_LOCK_CPU;}}// 有DRAW_WAKE_LOCK锁时需要CPU保持唤醒if ((wakeLockSummary WAKE_LOCK_DRAW) ! 0) {wakeLockSummary | WAKE_LOCK_CPU;}return wakeLockSummary;}在平时分析处理不灭屏相关Bug时通过该值可确定当前系统持有哪些类型的锁。 最终得到mWakeLockSummary在自动灭屏流程中将使用起到重要作用当自动灭屏时如果mWakeLockSummary设置有WAKE_LOCK_STAY_AWAKE标记位那么将不会灭屏。 此外上面方法中出现了对ProfilePowerState对象的处理它用来对不同user进行不同参数的设置在多用户模式下可以支持不同的状态这部分略去。
2.5 updateUserActivitySummaryLocked()更新用户活动状态
这个方法用来更新全局变量mUserActivitySummary它表示用户活动状态有三个值: // Summarizes the user activity state.static final int USER_ACTIVITY_SCREEN_BRIGHT 1 0; // 表示亮屏状态下的交互static final int USER_ACTIVITY_SCREEN_DIM 1 1; // 表示Dim状态下的交互static final int USER_ACTIVITY_SCREEN_DREAM 1 2; // 表示Dreamland状态下的交互何时开始自动灭屏就是这个方法中实现的。当设备和用户有交互时都会根据当前时间和自动灭屏时间、Dim时长、当前唤醒状态计算下次休眠的时间完成自动灭屏的操作。由亮屏进入Dim的时长、Dim到灭屏的时长、亮屏到屏保的时长都是在这里计算的这个方法的详细分析见后面的灭屏流程篇。
2.6 updateAttentiveStateLocked()更新细微模式状态
这个方法用来更新细微模式状态这是Android R上新添加的一个功能其目的就是解决用户长时间没有操作但一直持有亮屏锁导致系统不灭屏这个场景的算是一个省电优化项看下是如何实现的
//frameworks/base/services/core/java/com/android/server/power/PowerManagerService.javaprivate void updateAttentiveStateLocked(long now, int dirty) {// 触发细微模式的时间阈值long attentiveTimeout getAttentiveTimeoutLocked();// Attentive state only applies to the default display group.// 自动休眠时间long goToSleepTime mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP).getLastUserActivityTimeLocked() attentiveTimeout;// 细微模式提示Dialog弹出时间long showWarningTime goToSleepTime - mAttentiveWarningDurationConfig;// 是否已经弹出提升对话框boolean warningDismissed maybeHideInattentiveSleepWarningLocked(now, showWarningTime);if (attentiveTimeout 0 (warningDismissed|| (dirty (DIRTY_ATTENTIVE | DIRTY_STAY_ON | DIRTY_SCREEN_BRIGHTNESS_BOOST| DIRTY_PROXIMITY_POSITIVE | DIRTY_WAKEFULNESS | DIRTY_BOOT_COMPLETED| DIRTY_SETTINGS)) ! 0)) {mHandler.removeMessages(MSG_ATTENTIVE_TIMEOUT);// 是否需要弹出警告if (isBeingKeptFromInattentiveSleepLocked()) {return;}long nextTimeout -1;if (now showWarningTime) {nextTimeout showWarningTime;} else if (now goToSleepTime) {// 弹出警告给用户mInattentiveSleepWarningOverlayController.show();nextTimeout goToSleepTime;}// 下一次进入时将会灭屏if (nextTimeout 0) {scheduleAttentiveTimeout(nextTimeout);}}}这里提供了两个配置值
mAttentiveWarningDurationConfig表示触发细微模式前弹出警告的时长到达该时间时会弹出对话框提示用户是否还要亮屏mAttentiveTimeoutConfig表示触发细微模式的时间阈值到达该时长后会进行自动灭屏 这种情况下即使没有达到用户设置的自动休眠时间也会进行自动灭屏。
2.7 updateWakefulnessLocked()是否需要更新唤醒状态
这个方法也和自动灭屏流程有关。如果满足自动灭屏条件会更新系统唤醒状态。 这三个方法放在for(;;)循环中执行是因为它们共同决定了设备的唤醒状态前两个方法是汇总状态后一个方法是根据前两个方法汇总的值而进行判断是否要改变当前的设备唤醒状态汇总状态会受mWakefulness的影响因此会进行循环处理。 同时也仅仅会在超时灭屏进入睡眠或屏保时for循环会执行两次其他情况下只会执行一次。这个方法的详细分析见PMS灭屏流程。
2.8 updateProfilesLocked()
以上几个方法针对全局状态进行更新这个方法则根据ProfilePowerState中保存的状态更新不同用户是否进入锁定状态由于使用场景不是很高这里暂且略过。
2.9 updatePowerGroupsLocked
该方法用于请求并更新Display状态在这个方法中会确定多个影响Display状态的属性并将这些值封装到DisplayPowerRequest对象中向DisplayMangerService发起请求最终由DMS完成Display亮度、状态的更新 private boolean updatePowerGroupsLocked(int dirty) {final boolean oldPowerGroupsReady areAllPowerGroupsReadyLocked();if ((dirty (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS| DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED | DIRTY_BOOT_COMPLETED| DIRTY_SETTINGS | DIRTY_SCREEN_BRIGHTNESS_BOOST | DIRTY_VR_MODE_CHANGED |DIRTY_QUIESCENT | DIRTY_DISPLAY_GROUP_WAKEFULNESS)) ! 0) {if ((dirty DIRTY_QUIESCENT) ! 0) {if (areAllPowerGroupsReadyLocked()) {sQuiescent false;} else {mDirty | DIRTY_QUIESCENT;}}for (int idx 0; idx mPowerGroups.size(); idx) {final PowerGroup powerGroup mPowerGroups.valueAt(idx);final int groupId powerGroup.getGroupId();// Determine appropriate screen brightness and auto-brightness adjustments.final boolean autoBrightness; // 自动亮度是否开启final float screenBrightnessOverride; // 是否有覆盖亮度if (!mBootCompleted) {//启动过程中要求亮度稳定要求默认亮度和Bootloader中设定的亮度值保持一致autoBrightness false; //不开启自动亮度screenBrightnessOverride mScreenBrightnessDefault; //使用默认值} else if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)) {//使用WindowManager覆盖的亮度值autoBrightness false;screenBrightnessOverride mScreenBrightnessOverrideFromWindowManager;} else {autoBrightness (mScreenBrightnessModeSetting Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);screenBrightnessOverride PowerManager.BRIGHTNESS_INVALID_FLOAT;}//向DisplayMangerService发起请boolean ready powerGroup.updateLocked(screenBrightnessOverride, autoBrightness,shouldUseProximitySensorLocked(), shouldBoostScreenBrightness(),mDozeScreenStateOverrideFromDreamManager,mDozeScreenBrightnessOverrideFromDreamManagerFloat,mDrawWakeLockOverrideFromSidekick,mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.SCREEN_BRIGHTNESS),sQuiescent, mDozeAfterScreenOff, mIsVrModeEnabled, mBootCompleted,mScreenBrightnessBoostInProgress, mRequestWaitForNegativeProximity);int wakefulness powerGroup.getWakefulnessLocked();final boolean displayReadyStateChanged powerGroup.setReadyLocked(ready);final boolean poweringOn powerGroup.isPoweringOnLocked();if (ready displayReadyStateChanged poweringOn wakefulness WAKEFULNESS_AWAKE) {powerGroup.setIsPoweringOnLocked(false);LatencyTracker.getInstance(mContext).onActionEnd(ACTION_TURN_ON_SCREEN);Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, TRACE_SCREEN_ON, groupId);final int latencyMs (int) (mClock.uptimeMillis()- powerGroup.getLastPowerOnTimeLocked());// 如果亮屏流程超过200ms输出亮屏所用时间if (latencyMs SCREEN_ON_LATENCY_WARNING_MS) {Slog.w(TAG, Screen on took latencyMs ms);}}}// 释放PSensor WakeLock锁时的一个标记mRequestWaitForNegativeProximity false;}return areAllPowerGroupsReadyLocked() !oldPowerGroupsReady;}boolean updateLocked(float screenBrightnessOverride, boolean autoBrightness,boolean useProximitySensor, boolean boostScreenBrightness, int dozeScreenState,float dozeScreenBrightness, boolean overrideDrawWakeLock,PowerSaveState powerSaverState, boolean quiescent, boolean dozeAfterScreenOff,boolean vrModeEnabled, boolean bootCompleted, boolean screenBrightnessBoostInProgress,boolean waitForNegativeProximity) {// 根据系统唤醒状态获取请求的策略 off, doze, dim or bright.mDisplayPowerRequest.policy getDesiredScreenPolicyLocked(quiescent, dozeAfterScreenOff,vrModeEnabled, bootCompleted, screenBrightnessBoostInProgress);// WindowManager覆盖的亮度值如播放视频时调节亮度mDisplayPowerRequest.screenBrightnessOverride screenBrightnessOverride;// 是否使用自动亮度mDisplayPowerRequest.useAutoBrightness autoBrightness;// 是否存在PSensor Wakelock锁mDisplayPowerRequest.useProximitySensor useProximitySensor;// 是否有增强亮度mDisplayPowerRequest.boostScreenBrightness boostScreenBrightness;// 唤醒状态为Doze时确定display的状态if (mDisplayPowerRequest.policy DisplayPowerRequest.POLICY_DOZE) {mDisplayPowerRequest.dozeScreenState dozeScreenState;if ((getWakeLockSummaryLocked() WAKE_LOCK_DRAW) ! 0 !overrideDrawWakeLock) {if (mDisplayPowerRequest.dozeScreenState Display.STATE_DOZE_SUSPEND) {mDisplayPowerRequest.dozeScreenState Display.STATE_DOZE;}if (mDisplayPowerRequest.dozeScreenState Display.STATE_ON_SUSPEND) {mDisplayPowerRequest.dozeScreenState Display.STATE_ON;}}// Doze时的屏幕亮度mDisplayPowerRequest.dozeScreenBrightness dozeScreenBrightness;} else {mDisplayPowerRequest.dozeScreenState Display.STATE_UNKNOWN;mDisplayPowerRequest.dozeScreenBrightness PowerManager.BRIGHTNESS_INVALID_FLOAT;}mDisplayPowerRequest.lowPowerMode powerSaverState.batterySaverEnabled;mDisplayPowerRequest.screenLowPowerBrightnessFactor powerSaverState.brightnessFactor;// 发起请求返回值表示DisplayPowerController中是否完成这次请求boolean ready mDisplayManagerInternal.requestPowerState(mGroupId, mDisplayPowerRequest,waitForNegativeProximity);mNotifier.onScreenPolicyUpdate(mGroupId, mDisplayPowerRequest.policy);return ready;}在向DisplayManagerService发起请求时会将所有的信息封装到DisplayPowerRequest对象中其中policy属性值有五类
POLICY_OFF请求屏幕进入灭屏状态POLICY_DOZE请求屏幕进入Doze状态POLICY_DIM请求屏幕进入Dim状态POLICY_BRIGHT请求屏幕处于正常亮屏状态POLICY_VRVR模式相关
在请求前通过getDesiredScreenPolicyLocked()方法根据当前唤醒状态和WakeLock统计状态来决定要请求的Display状态 int getDesiredScreenPolicyLocked(boolean quiescent, boolean dozeAfterScreenOff,boolean vrModeEnabled, boolean bootCompleted, boolean screenBrightnessBoostInProgress) {final int wakefulness getWakefulnessLocked();final int wakeLockSummary getWakeLockSummaryLocked();// 当前唤醒状态为Asleep则Display状态会设置为OFFif (wakefulness WAKEFULNESS_ASLEEP || quiescent) {return DisplayPowerRequest.POLICY_OFF;} else if (wakefulness WAKEFULNESS_DOZING) { // 当前唤醒状态为Doze则Display状态会设置为Doze指定的状态if ((wakeLockSummary WAKE_LOCK_DOZE) ! 0) {return DisplayPowerRequest.POLICY_DOZE;}// 表示跳过Doze的状态直接设置成OFFif (dozeAfterScreenOff) {return DisplayPowerRequest.POLICY_OFF;}// Fall through and preserve the current screen policy if not configured to// doze after screen off. This causes the screen off transition to be skipped.}//如果开启了VR模式则设置为VR模式if (vrModeEnabled) {return DisplayPowerRequest.POLICY_VR;}// 如果存在亮屏锁、用户活动状态为亮屏、进行增强亮度则Display状态将设置为ONif ((wakeLockSummary WAKE_LOCK_SCREEN_BRIGHT) ! 0|| !bootCompleted|| (getUserActivitySummaryLocked() USER_ACTIVITY_SCREEN_BRIGHT) ! 0|| screenBrightnessBoostInProgress) {return DisplayPowerRequest.POLICY_BRIGHT;}// 不满足以上条件默认设置DIMreturn DisplayPowerRequest.POLICY_DIM;}2.10 updateDreamLocked()
该方法用来更新设备Dreamland状态比如是否进入Dream、Doze或者开始休眠:
// frameworks/base/services/core/java/com/android/server/power/PowerManagerService.javaprivate void updateDreamLocked(int dirty, boolean powerGroupBecameReady) {if ((dirty (DIRTY_WAKEFULNESS| DIRTY_USER_ACTIVITY| DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED| DIRTY_ATTENTIVE| DIRTY_WAKE_LOCKS| DIRTY_BOOT_COMPLETED| DIRTY_SETTINGS| DIRTY_IS_POWERED| DIRTY_STAY_ON| DIRTY_PROXIMITY_POSITIVE| DIRTY_BATTERY_STATE)) ! 0 || powerGroupBecameReady) {if (areAllPowerGroupsReadyLocked()) { //areAllPowerGroupsReadyLocked为ture后才会进一步执行//通过Handler异步发送一个消息scheduleSandmanLocked();}}}private boolean areAllPowerGroupsReadyLocked() {final int size mPowerGroups.size();for (int i 0; i size; i) {if (!mPowerGroups.valueAt(i).isReadyLocked()) {return false;}}return true;}可以看到对于Dreamland相关状态的更新依赖areAllPowerGroupsReadyLocked的返回值它表示每一个display是否已经准备就绪因此只有在准备就绪的情况下才会进一步调用该方法的方法体。最后会PMS主线程中调用handleSandman()方法执行Dreamland的操作:
// frameworks/base/services/core/java/com/android/server/power/PowerManagerService.javaprivate void handleSandman(int groupId) { // runs on handler thread// Handle preconditions.final boolean startDreaming;final int wakefulness;synchronized (mLock) {mSandmanScheduled false;final PowerGroup powerGroup mPowerGroups.get(groupId);wakefulness powerGroup.getWakefulnessLocked();// 如果召唤了睡魔且每个Display状态已经准备完毕if ((wakefulness WAKEFULNESS_DREAMING || wakefulness WAKEFULNESS_DOZING) powerGroup.isSandmanSummonedLocked() powerGroup.isReadyLocked()) {// 判断是否可以进入DreamlandstartDreaming canDreamLocked(powerGroup) || canDozeLocked(powerGroup);powerGroup.setSandmanSummonedLocked(/* isSandmanSummoned */ false);} else {startDreaming false;}}// Start dreaming if needed.// We only control the dream on the handler thread, so we dont 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(/* immediate */ false);// 开始进入DreamlandmDreamManager.startDream(wakefulness WAKEFULNESS_DOZING);}isDreaming mDreamManager.isDreaming();} else {isDreaming false;}// At this point, we either attempted to start the dream or no attempt will be made,// so stop holding the display suspend blocker for Doze.mDozeStartInProgress false;// Update dream state.synchronized (mLock) {...// Remember the initial battery level when the dream started.// 记录下进入Dream模式前的初始电量值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).final PowerGroup powerGroup mPowerGroups.get(groupId);if (powerGroup.isSandmanSummonedLocked()|| powerGroup.getWakefulnessLocked() ! wakefulness) {return; // wait for next cycle}// Determine whether the dream should continue.long now mClock.uptimeMillis();if (wakefulness WAKEFULNESS_DREAMING) {if (isDreaming canDreamLocked(powerGroup)) {if (mDreamsBatteryLevelDrainCutoffConfig 0 mBatteryLevel mBatteryLevelWhenDreamStarted- mDreamsBatteryLevelDrainCutoffConfig !isBeingKeptAwakeLocked(powerGroup)) {//充电速度慢于消耗速度或者用户活动timeout已过则退出Dream进入睡眠} else {return; // continue dreaming 继续维持Dream状态}}// Dream has ended or will be stopped. Update the power state.// 退出Dreamland,进入休眠状态if (isItBedTimeYetLocked(powerGroup)) {if (isAttentiveTimeoutExpired(powerGroup, now)) {//更新睡眠状态sleepPowerGroupLocked(powerGroup, now,PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, Process.SYSTEM_UID);} else {//更新doze状态dozePowerGroupLocked(powerGroup, now,PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, Process.SYSTEM_UID);}} else {// 唤醒设备wakePowerGroupLocked(powerGroup, now,PowerManager.WAKE_REASON_DREAM_FINISHED,android.server.power:DREAM_FINISHED, Process.SYSTEM_UID,mContext.getOpPackageName(), Process.SYSTEM_UID);}} else if (wakefulness WAKEFULNESS_DOZING) {if (isDreaming) {return; // continue dozing 继续保持doze状态}// Doze has ended or will be stopped. Update the power state.// 更新睡眠状态sleepPowerGroupLocked(powerGroup, now, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT,Process.SYSTEM_UID);}}// Stop dream.if (isDreaming) {mDreamManager.stopDream(/* immediate */ false);}}在以上方法中将会调用DreamManager处理具体的Dreamland逻辑这部分流程的分析在DreamManagerService模块分析时会进行详细分析。
2.11 finishWakefulnessChangeIfNeededLocked()
该方法主要做唤醒状态发生变化后后半部分更新工作
//frameworks/base/services/core/java/com/android/server/power/PowerManagerService.javaGuardedBy(mLock)private void finishWakefulnessChangeIfNeededLocked() {if (mWakefulnessChanging areAllPowerGroupsReadyLocked()) {if (getGlobalWakefulnessLocked() WAKEFULNESS_DOZING (mWakeLockSummary WAKE_LOCK_DOZE) 0) {return; // wait until dream has enabled dozing} else {// Doze wakelock acquired (doze started) or device is no longer dozing.mDozeStartInProgress false;}Android采码蜂:if (getGlobalWakefulnessLocked() WAKEFULNESS_DOZING|| getGlobalWakefulnessLocked() WAKEFULNESS_ASLEEP) {logSleepTimeoutRecapturedLocked();}mWakefulnessChanging false;mNotifier.onWakefulnessChangeFinished();}}只有当屏幕状态改变后才会执行该方法。进入该方法后将通过Notifier#onWakefulnessChangeFinished()方法发送亮屏、灭屏广播等。 该方法中的logScreenOn()方法将打印出整个亮屏流程的耗时在平时处理问题时很有帮助。 2.12 updateSuspendBlockerLocked()
这个方法用来更新SuspendBlocker锁状态。Suspend锁机制是Android框架中锁机的一种锁它代表了框架层以上所有的WakeLock。Wakelock锁是APP或其他组建向PMS模块申请而Suspend锁是PMS模块中对WakeLock锁的最终表现或者说上层应用或system_server其他组件申请了wakelock锁后在PMS中最终都会表现为Suspend锁通过Suspend锁向Hal层写入节点Kernal层会读取节点从而唤醒或者休眠CPU。 该方法的详细分析在PMS WakeLock机制中进行汇总。 到此为止对PMS中所有核心方法进行了简单的分析有些方法仅仅说明了下作用会在后面具体业务中进行详细分析。
跟着学习自 Android R PowerManagerService模块(1) 启动流程和核心方法