Android电源管理框架

2019-07-13 23:11发布

Android电源管理框架
管理策略:通过锁和定时器来切换系统的状态,使系统的功耗降至最低
层次结构:App、Framework、HAL和kernel层 l  应用层:这里所谓的应用层主要是指应用程序和其他使用电源管理的Service,包括但不限于以下Services: PowerManagerService、BatteryService、LightService等。 l  框架层:在Android框架层包含了对应用层接口的API调用以及电源的协调工作,主要包含PowerManager.java、PowerManagerService.java、com_android_server_PowerManagerService.cpp、Power.java、android_os_Power.cpp。其中PowerManagerService.java是核心,Power.java提供底层的函数接口,与JNI层进行交互。PowerManager.java是提供给应用层调用的。android_os_power.cpp是jni交互文件。这一层的功能相对比较复杂,比如系统状态的切换,背光的调节及开关,Wake Lock的申请和释放等等,但这一层跟硬件平台无关。 l  HAL层:该层只有一个Power.c文件,该文件通过sysfs的方式与kernel进行通信。主要功能有申请wake_lock,释放wake_lock,设置屏幕状态等。用户空间的native库绝不能直接调用Android电源管理(见下图)。绕过Android运行时的电源管理政策,将破坏该系统。所有对电源管理的调用应通过Android的PowerManagerAPI来完成。 l  Kernel层:内核层的电源管理方案实现主要包含三部分: 1、Kernel/power/:实现了系统电源管理框架机制。 2、Arch/arm(ormips or powerpc)/mach-XXX/pm.c:实现对特定板的处理器电源管理。 3、drivers/power:是设备电源管理的基础框架,为驱动提供了电源管理接口。 Android的电源管理框架
Android系统提供的几个低功耗模式 earlysuspend:让设备进入低功耗,如LCD关闭 suspend:只有电源模块和 hibernation:内存镜像写入磁盘,下次开机可恢复
PowerManager是PMS的代理类,实现如下常用功能 reboot、gotoSleep、wakeUp、shutDown、isDeviceIdleMode、userActivity和屏幕信息操作等接口 userActivity:向PowerManagerService报告影响系统休眠的用户活动,重计算灭屏时间,背光亮度等,例如触屏,划屏,power键等用户活动;
isDeviceIdleMode:返回设备当前的状态,如果处于Idle状态,则返回true,Idle状态是在手机长时间没有被使用以及没有运动的情况下,手机进入到一种Doze低功耗的模式下,这种状态下手机可能会关掉网络数据访问,可以通过监视DEVICE_IDLE_MODE_CHANGED这个广播信息,来监控手机状态的改变

电源管理的核心服务PowerManagerService(PMS)流程 PowerManager是通过binder与PowerManagerService进行通信的,PowerManer中的大部分方法在PMS中都有阈值对应的方法,PMS是整个电源管理的决策系统
参考链接: http://blog.csdn.net/gaugamela/article/details/52785041
http://www.myexception.cn/android/2076061.html
http://blog.csdn.net/kitty_landon/article/details/47107045
PMS:PowerNamagerService的启动 在SystemServer中启动PMS和SensorService frameworks/base/services/java/com/android/server/SystemServer.java private void startBootstrapServices() { mActivityManagerService = mSystemServiceManager.startService( ActivityManagerService.Lifecycle.class).getService(); mActivityManagerService.setSystemServiceManager(mSystemServiceManager); mActivityManagerService.setInstaller(installer); mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);//启动PMS ....... startSensorService(); //native函数,sensor管理 } 上面的函数为Android系统的引导程序,启动PMS时候会通过反射方式调用服务(PMS)的构造函数,同时执行服务(PMS)的onStart()函数 public T startService(Class serviceClass) { ...... Constructor constructor = serviceClass.getConstructor(Context.class); service = constructor.newInstance(mContext);//调用PMS的构造函数 ...... mServices.add(service);//将PMS作为系统服务添加到服务列表 service.onStart();//调用PMS的onStart方法 return service; }
PMS的构造函数实现如下 public PowerManagerService(Context context) { super(context); mContext = context; mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_DISPLAY, false /*allowIo*/); mHandlerThread.start(); mHandler = new PowerManagerHandler(mHandlerThread.getLooper()); synchronized (mLock) { mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks");//控制CPU mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display");//控制屏幕 mDisplaySuspendBlocker.acquire(); mHoldingDisplaySuspendBlocker = true; mHalAutoSuspendModeEnabled = false; mHalInteractiveModeEnabled = true; mWakefulness = WAKEFULNESS_AWAKE;//系统所处的状态(系统正常状态,休眠状态,屏保状态,doze状态) nativeInit(); nativeSetAutoSuspend(false); nativeSetInteractive(true); nativeSetFeature(POWER_FEATURE_DOUBLE_TAP_TO_WAKE, 0); } } mWakefulness有四种取值标识系统当前的状态 WAKEFULNESS_ASLEEP:表示系统当前处于休眠状态,只能被wakeUp()调用唤醒。 WAKEFULNESS_AWAKE:表示系统目前处于正常运行状态。 WAKEFULNESS_DREAMING:表示系统当前正处于屏保的状态。 WAKEFULNESS_DOZING:表示系统正处于“doze”状态。这种状态下只有低耗电的“屏保”可以运行,其他应用进程都被挂起。 关于createSuspendBlockerLocked的实现 private SuspendBlocker createSuspendBlockerLocked(String name) { SuspendBlocker suspendBlocker = new SuspendBlockerImpl(name); mSuspendBlockers.add(suspendBlocker); return suspendBlocker; } acquire()函数的实现 public void acquire() { synchronized (this) { mReferenceCount += 1; if (mReferenceCount == 1) { nativeAcquireSuspendBlocker(mName); } } } 所以每次acquire() count都会加1,nativeAcquireSuspendBlocker(mName)方法通过JNI调用native层的nativeAcquireSuspendBlocker方法。 static void nativeAcquireSuspendBlocker(JNIEnv *env, jclass clazz, jstring nameStr) { ScopedUtfChars name(env, nameStr); acquire_wake_lock(PARTIAL_WAKE_LOCK, name.c_str()); } acquire_wake_lock()调用的是power.c文件中的acquire_wake_lock()方法。在该方法中通过往/sys/power/wake_lock,/sys/power/wake_unlock等文件中写入数据来进行底层持锁 下面看nativeInit()函数,通过JNI方法在native层初始化相关资源 static void nativeInit(JNIEnv* env, jobject obj) { //创建一个全局引用对象,引用PMS gPowerManagerServiceObj = env->NewGlobalRef(obj); //利用hw_get_module加载底层动态库,具体实现还是依赖与dlsym函数 status_t err = hw_get_module(POWER_HARDWARE_MODULE_ID, (hw_module_t const**)&gPowerModule); if (!err) { //调用底层动态库的init函数 gPowerModule->init(gPowerModule); } else { ALOGE("Couldn't load %s module (%s)", POWER_HARDWARE_MODULE_ID, strerror(-err)); } } static void nativeSetAutoSuspend(JNIEnv* /* env */, jclass /* clazz */, jboolean enable) { if (enable) { ALOGD_IF_SLOW(100, "Excessive delay in autosuspend_enable() while turning screen off"); autosuspend_enable(); } else { ALOGD_IF_SLOW(100, "Excessive delay in autosuspend_disable() while turning screen on"); //初始时调用autosuspend_disable函数,定义于system/core/libsuspend/autosuspend.c中 //最终将调用到autosuspend_earlysuspend_disable函数,就是将底层的置为pwr_state_on的状态 autosuspend_disable(); } } static void nativeSetInteractive(JNIEnv* /* env */, jclass /* clazz */, jboolean enable) { if (gPowerModule) { if (enable) { ALOGD_IF_SLOW(20, "Excessive delay in setInteractive(true) while turning screen on"); //初始时,调用动态库的setInteractive函数,目前还不确定这个函数调用后的效果 gPowerModule->setInteractive(gPowerModule, true); } else { ALOGD_IF_SLOW(20, "Excessive delay in setInteractive(false) while turning screen off"); gPowerModule->setInteractive(gPowerModule, false); } } } static void nativeSetFeature(JNIEnv *env, jclass clazz, jint featureId, jint data) { int data_param = data; if (gPowerModule && gPowerModule->setFeature) { //初始时,调用动态库的setFeature函数,将POWER_FEATURE_DOUBLE_TAP_TO_WAKE置为0 gPowerModule->setFeature(gPowerModule, (feature_t)featureId, data_param); } } nativeInit()方法中,创建了一个对应的Native层PowerManagerService,然后调用了gPowerModule的init函数。以下是power_module的结构类型
struct power_module HAL_MODULE_INFO_SYM = { .common = { .tag = HARDWARE_MODULE_TAG, .module_api_version = POWER_MODULE_API_VERSION_0_2, .hal_api_version = HARDWARE_HAL_API_VERSION, .id = POWER_HARDWARE_MODULE_ID, .name = "Default Power HAL", .author = "The Android Open Source Project", .methods = &power_module_methods, }, .init = power_init, .setInteractive = power_set_interactive, .powerHint = power_hint, }; gPowerModule->init方法对应的是power_init 这个应该是由硬件厂商来实现的,不同的硬件初始化方式也不一样,我们看先htc相关的实现方式. Power_init实际就是在cpu的节点中写入了一些初始化的值,以下是htc一个例子 static void power_init(struct power_module __unused *module) { sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/timer_rate", "20000"); sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/timer_slack", "20000"); sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/min_sample_time", "80000"); sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/hispeed_freq", "1530000"); sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/go_hispeed_load", "99"); sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/target_loads", "65 228000:75 624000:85"); sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/above_hispeed_delay", "20000"); sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/boostpulse_duration", "1000000"); sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/io_is_busy", "0"); calculate_max_cpu_freq(); } 所以构造函数实际上时设置了一些标志位,设置系统的状态,加载底层与硬件设置相关的函数 PMS的onStart()函数 @Override public void onStart() { publishBinderService(Context.POWER_SERVICE, new BinderService());//最终通过ServiceManager的Add函数注册BinderService publishLocalService(PowerManagerInternal.class, new LocalService()); Watchdog.getInstance().addMonitor(this); Watchdog.getInstance().addThread(mHandler); } 将PowerManagerService注册到ServiceManager中和LocalService中 PMS的systemReady()函数
在中SystemServer的run()函数中 private void run() { ....... Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices"); startBootstrapServices();//启动必要的引导服务如PMS startCoreServices(); startOtherServices(); ....... }在startOtherServices()中 private void startOtherServices() { ........ try { // TODO: use boot phase mPowerManagerService.systemReady(mActivityManagerService.getAppOpsService()); Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); } catch (Throwable e) { reportWtf("making Power Manager Service ready", e); } ........ }PMS的systemReady函数具体实现如下 public void systemReady(IAppOpsService appOps) { //这里持锁,意味者内部所有函数必须在规定事件内执行完毕 //否则watchDog将会检测到错误 synchronized (mLock) { mSystemReady = true; mAppOps = appOps; //注意下面的对象都是从LocalServices取出的,从之前PMS加入LocalServices的流程来看 //下面取出的实际上应该是继承抽象类的实际子类 //因此大概可以理解LocalServices的作用了,以抽象类名为key,保存实际的子类 //以key取出子类对象时,子类退化为抽象类,于是得到了实际对象,但仅能利用父类的接口 //整个设计演变为面向接口的编程 //从注释来看,与doze有关 mDreamManager = getLocalService(DreamManagerInternal.class); //显示管理相关 mDisplayManagerInternal = getLocalService(DisplayManagerInternal.class); //Window管理相关 mPolicy = getLocalService(WindowManagerPolicy.class); //电源管理相关 mBatteryManagerInternal = getLocalService(BatteryManagerInternal.class); //这里获取PowerManager就是为了方便获取下面三个系统属性 PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); mScreenBrightnessSettingMinimum = pm.getMinimumScreenBrightnessSetting(); mScreenBrightnessSettingMaximum = pm.getMaximumScreenBrightnessSetting(); mScreenBrightnessSettingDefault = pm.getDefaultScreenBrightnessSetting(); //Sensor相关 SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper()); //系统电量统计有关 mBatteryStats = BatteryStatsService.getService(); // 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"), mPolicy); //无线充电检测相关 mWirelessChargerDetector = new WirelessChargerDetector(sensorManager, createSuspendBlockerLocked("PowerManagerService.WirelessChargerDetector"), mHandler); mSettingsObserver = new SettingsObserver(mHandler); //lightService相关 mLightsManager = getLocalService(LightsManager.class); mAttentionLight = mLightsManager.getLight(LightsManager.LIGHT_ID_ATTENTION); // Initialize display power management. //调用DisplayManagerService内部的LocalService的函数 //创建出DisplayBlanker和DisplayPowerController mDisplayManagerInternal.initPowerManagement( mDisplayPowerCallbacks, mHandler, sensorManager); //定义一堆BroadcastReceiver .................. //利用mSettingsObserver监听一堆数据库字段的变化 .................. //VR相关 IVrManager vrManager = (IVrManager) getBinderService(VrManagerService.VR_MANAGER_BINDER_SERVICE); try { vrManager.registerListener(mVrStateCallbacks); } catch (RemoteException e) { Slog.e(TAG, "Failed to register VR mode state listener: " + e); } //从资源文件中读取大量配置信息 readConfigurationLocked(); //读取数据库字段,保存到本地变量中 //必要时会进行一些实际的操作,例如设置feature到native层的动态库 updateSettingsLocked(); mDirty |= DIRTY_BATTERY_STATE; //更新全局的电源状态 updatePowerStateLocked(); } } 进一步初始化PMS,获取与PowerManager相关的本地服务 比如屏保(mDreamManager 屏幕显示(mDisplayManagerInternal 窗口策略(mPolicy 电池电量(mBatteryManagerInternal)等服务,然后初始化屏幕最大亮度,最小亮度,和默认亮度; sensor(sensorManager)用于与sensor交互,比如距离传感器,光线传感器,加速度传感器(doze上使用) 背光(mLightsManager) 电池状态(mBatteryStats
创建mSettingsObserver 监听系统设置变化,比如亮屏时间,自动背光,屏幕亮度,屏保,低电模式等等
唤醒流程
屏保唤醒通过线程监听来实现,具体的在DreamManagerService.java中 private final Runnable mSystemPropertiesChanged = new Runnable() { @Override public void run() { if (DEBUG) Slog.d(TAG, "System properties changed"); synchronized (mLock) { if (mCurrentDreamName != null && mCurrentDreamCanDoze && !mCurrentDreamName.equals(getDozeComponent())) { // May have updated the doze component, wake up mPowerManager.wakeUp(SystemClock.uptimeMillis(), "android.server.dreams:SYSPROP"); } } } };
PM中的wakeUp方法最终会调用到PMS中的wakeUp方法,PMS具体如下 @Override // Binder call//该方法通过Binder白PM的wakeUp函数调用 public void wakeUp(long eventTime, String reason, String opPackageName) { if (eventTime > SystemClock.uptimeMillis()) { throw new IllegalArgumentException("event time must not be in the future"); } mContext.enforceCallingOrSelfPermission(//权限检查 android.Manifest.permission.DEVICE_POWER, null); final int uid = Binder.getCallingUid(); final long ident = Binder.clearCallingIdentity(); try { wakeUpInternal(eventTime, reason, uid, opPackageName, uid);//唤醒逻辑 } finally { Binder.restoreCallingIdentity(ident); } }具体唤醒逻辑如下: private void wakeUpInternal(long eventTime, String reason, int uid, String opPackageName, int opUid) { synchronized (mLock) { if (mIPOShutdown && reason != PowerManager.WAKE_UP_REASON_SHUTDOWN) return; if (wakeUpNoUpdateLocked(eventTime, reason, uid, opPackageName, opUid)) { updatePowerStateLocked();//此方法为PMS的核心方法,专门处理wakeUp与sleep的逻辑 } } } 只有wakeUpNoUpdateLocked返回true时才会执行updatePowerStateLocked()函数 private boolean wakeUpNoUpdateLocked(long eventTime, String reason, int reasonUid, String opPackageName, int opUid) { ...... switch (mWakefulness) { case WAKEFULNESS_ASLEEP: Slog.i(TAG, "Waking up from sleep (uid " + reasonUid +")..."); break; case WAKEFULNESS_DREAMING: Slog.i(TAG, "Waking up from dream (uid " + reasonUid +")..."); break; case WAKEFULNESS_DOZING: Slog.i(TAG, "Waking up from dozing (uid " + reasonUid +")..."); break; } mLastWakeTime = eventTime; setWakefulnessLocked(WAKEFULNESS_AWAKE, 0);//不论系统目前处于何种状态,都会将系统当前的状态设置为WAKE状态 ...... return true;//返回true }
updatePowerStateLocked函数用于更新整个系统的状态,决定系统当前所处的状态 private void updatePowerStateLocked() { ...... // Phase 0: Basic state updates. updateIsPoweredLocked(mDirty); 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; updateWakeLockSummaryLocked(dirtyPhase1); updateUserActivitySummaryLocked(now, dirtyPhase1); if (!updateWakefulnessLocked(dirtyPhase1)) { break; } } // Phase 2: Update display power state. boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2); // Phase 3: Update dream state (depends on display ready signal). updateDreamLocked(dirtyPhase2, displayBecameReady); // Phase 4: Send notifications, if needed. finishWakefulnessChangeIfNeededLocked(); // 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(); ...... }updatePowerStateLocked是PMS的核心函数,主要分为5个步骤进行
主要处理屏幕显示,背光处理,用户ACTION,suspend blockers的申请与释放 updateDisplayPowerStateLocked主要用于按键灯,屏幕亮度自动调节,处理显示请求