一、PowerManagerService简介
PowerManagerService主要服务Android系统电源管理工作,这样讲比较笼统,就具体细节上大致可以认为PowerManagerService集中处理用户活动(如点击屏幕,按电源键等)、电量变化、用户设置(如在Setting中设置省电模式,飞行模式)、插拔充电器(无线冲,有线冲)等。当发生以上事件时,PowerManagerService都要进行各种状态的更新,以下把PMS作为PowerManagerService的简称
二、PowerManagerService启动流程
2.1、PMS启动
// Power manager needs to be started early because other services need it. // Native daemons may be watching for it to be registered so it must be ready // to handle incoming binder calls immediately (including being able to verify // the permissions for those calls). mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class); . . . try { // TODO: use boot phase mPowerManagerService.systemReady(mActivityManagerService.getAppOpsService()); } catch (Throwable e) { reportWtf("making Power Manager Service ready", e); }
2.2、SystemServiceManager.startService()
1 public <T extends SystemService> T startService(Class<T> serviceClass) { 2 final String name = serviceClass.getName(); 3 Slog.i(TAG, "Starting " + name); 4 5 // Create the service. 6 if (!SystemService.class.isAssignableFrom(serviceClass)) { 7 throw new RuntimeException("Failed to create " + name 8 + ": service must extend " + SystemService.class.getName()); 9 } 10 final T service; 11 try { 12 Constructor<T> constructor = serviceClass.getConstructor(Context.class); 13 service = constructor.newInstance(mContext); 14 } catch (InstantiationException ex) { 15 throw new RuntimeException("Failed to create service " + name 16 + ": service could not be instantiated", ex); 17 } catch (IllegalAccessException ex) { 18 throw new RuntimeException("Failed to create service " + name 19 + ": service must have a public constructor with a Context argument", ex); 20 } catch (NoSuchMethodException ex) { 21 throw new RuntimeException("Failed to create service " + name 22 + ": service must have a public constructor with a Context argument", ex); 23 } catch (InvocationTargetException ex) { 24 throw new RuntimeException("Failed to create service " + name 25 + ": service constructor threw an exception", ex); 26 } 27 28 // Register it. 29 mServices.add(service); 30 31 // Start it. 32 try { 33 service.onStart(); 34 } catch (RuntimeException ex) { 35 throw new RuntimeException("Failed to start service " + name 36 + ": onStart threw an exception", ex); 37 } 38 return service; 39 }
在Android5.0以后SystemServer启动服务的方式发生了改变,在Android4.4以前SystemServer通过new方法创建服务的对象,并把服务注册到SystemManager中;Android5.0以后SystemServer通过SystemServiceManager.startService来启动服务,主要通过反射的方式获取服务的构造方法,并创建服务对象;最后调用服务重写的onStart()方法。
说明:Android5.0以后所有服务都实现SystemService接口,这样方法服务的统一管理。
2.3 、PMS构造方法
public PowerManagerService(Context context) { super(context); mContext = context; //启动一个线程,创建一个handler,handler发送的消息由该线程来处理 mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_DISPLAY, false /*allowIo*/); mHandlerThread.start(); mHandler = new PowerManagerHandler(mHandlerThread.getLooper()); synchronized (mLock) { //创建两个suspendBlocker对象,获取suspendblocker防止cpu进去休眠 mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks"); mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display"); mDisplaySuspendBlocker.acquire(); mHoldingDisplaySuspendBlocker = true; mHalAutoSuspendModeEnabled = false; mHalInteractiveModeEnabled = true; mWakefulness = WAKEFULNESS_AWAKE; //初始化电源相关设置,这些方法通过jni调动native方法 nativeInit(); nativeSetAutoSuspend(false); nativeSetInteractive(true); nativeSetFeature(POWER_FEATURE_DOUBLE_TAP_TO_WAKE, 0); } }
2.4、OnStart()方法
1 @Override 2 public void onStart() { 3 //BinderService继承IPowerManager.Stub,其实就是PowerManager的服务端 4 //这里其实就是把BinderService对象注册到ServiceManager中 5 publishBinderService(Context.POWER_SERVICE, new BinderService()); 6 publishLocalService(PowerManagerInternal.class, new LocalService()); 7 8 //加入Watchdog监听 9 Watchdog.getInstance().addMonitor(this); 10 Watchdog.getInstance().addThread(mHandler); 11 }
2.5、systemReady()方法
public void systemReady(IAppOpsService appOps) { synchronized (mLock) { mSystemReady = true; mAppOps = appOps; 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(); //传感器相关,传感器检查到外部事件可以通过发送消息到mHandler的消息队列中处理 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(); //注意上面的注释,notifier运行在system server的主线程中,并且参数中传入了一个SuspendBlocker对象,应该发送通知的时候需要点亮屏幕 mNotifier = new Notifier(Looper.getMainLooper(), mContext, mBatteryStats, mAppOps, createSuspendBlockerLocked("PowerManagerService.Broadcasts"), mPolicy); //无线充电器相关,参数中传入了sensorManager,并且参数中传入了一个SuspendBlocker对象,也是为了有外部事件发生时点亮屏幕 mWirelessChargerDetector = new WirelessChargerDetector(sensorManager, createSuspendBlockerLocked("PowerManagerService.WirelessChargerDetector"), mHandler); //ContentObserver对象,用来监听电源相关设置的改变 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); ....... ....... ....... // Go. //读取资源文件中电源相关设置 readConfigurationLocked(); //更新设置中对电源的相关设置 updateSettingsLocked(); mDirty |= DIRTY_BATTERY_STATE; //更新电源状态,这里统一处理了所有的状态更新,该方法会被频繁调用 updatePowerStateLocked(); } }
2.6、updatePowerStateLocked()方法
三、PowerManager用法
PowerManager的用法很简单,我们主要看下PowerManager创建锁这部分:
newWakeLock(int levelAndFlags, String tag)
levelAndFlags: 就是上边表格中的几个flag,可以看到不同的flag对系统的影响并不一样
PARTIAL_WAKE_LOCK: 保持cpu运转状态,屏幕键盘灭,按power键该锁不会被系统自动释放,所以系统无法进去待机休眠
SCREEN_DIM_WAKE_LOCK: 保持cpu处于运行状态,屏幕微亮、键盘灭,但是按power键进入待机休眠时会自动释放
SCREEN_BRIGHT_WAKE_LOCK: 保持cpu处于运行状态,屏幕亮、键盘灭,但是按power键进入待机休眠时会自动释放
FULL_WAKE_LOCK: 保持cpu处于运行状态,屏幕、键盘亮,但是按power键进入待机休眠时会自动释放
注意:官方的文档介绍尽量不要使用WAKE_LOCK,用FLAG_KEEP_SCREEN_ON标志位代替WAKE_LOCK,用如下方式:
1 getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
当然该方法只是针对当前Activity,如果要整个应用都保持屏幕亮,则可以写了BaseActivity并设置该标志位,其他Activity继承BaseActivity即可。
四、PowerManagerService调试
PMS中最容易出现的问题就是待机待不下去,原因很可能就是获取的WAKE_LOCK没有及时释放,如果待机时有如下的锁的话是没法正真进去待机的,如果出现这种情况,按理说是应该在应用在进去待机时释放锁的
五、总结
总的来说PMS的流程并不复杂,不过需要静下心来分析代码仍然不是一件很容易的事情,关于updatePowerStateLocked()方法暂时还没写上去,感觉东西挺多的一下子写上去会显得很长,但是不仔细分析又感觉没必要写,所以就先空着,过两天再补上吧。本人水平有限,有不足之处请指出,后续我会持续更新修改。