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 extends SystemService> T startService(Class<T> serviceClass) {......Constructor<T> 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");//控制CPUmDisplaySuspendBlocker = 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) {//创建一个全局引用对象,引用PMSgPowerManagerServiceObj = 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置为0gPowerModule->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()函数

    @Overridepublic void onStart() {publishBinderService(Context.POWER_SERVICE, new BinderService());//最终通过ServiceManager的Add函数注册BinderServicepublishLocalService(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();//启动必要的引导服务如PMSstartCoreServices();startOtherServices();.......
}

在startOtherServices()中

private void startOtherServices()
{........try {// TODO: use boot phasemPowerManagerService.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和DisplayPowerControllermDisplayManagerInternal.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() {@Overridepublic 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 upmPowerManager.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主要用于按键灯,屏幕亮度自动调节,处理显示请求

Android电源管理框架相关推荐

  1. Android电源管理介绍

    一.电源管理基础知识 1.1电源管理的几种状态 Android kernel源码中,定义了三种电源状态,在kernel/power/suspend.c中: 对应的宏定义/include/linux/s ...

  2. android 电源管理 wakelock 唤醒锁机制

    Android 电源管理 - 唤醒锁全新上市 大多数人可能都遭遇过手机的电池续航时间较短带来的尴尬. 这极其令人讨厌. 没电的手机和一块水泥砖没什么差别. 一般而言,如果用户的手机电池无法持续一整天, ...

  3. 关闭Android电池温度告警框,android电源信息查看(电量、温度、电压)实例代码

    本文实例讲述了android电源信息查看方法.分享给大家供大家参考.具体如下: 1. PowerTestActivity: import android.app.Activity; import an ...

  4. AliOS Things 电源管理框架使用说明

    一.电源管理框架简介 电源管理框架的目的在于节约CPU的功耗.传统上,当操作系统处于空闲状态时,比如所有用户任务和系统任务处于阻塞状态,将执行idle task.idle task的通常做法是一个wh ...

  5. Android 资源管理框架(Resources和AssetManager) 及 资源编译(aapt)

    android应用资源预编译,编译和打包全解析- https://cloud.tencent.com/developer/article/1033926   Android系统提供了一套强大的资源管理 ...

  6. RT-Thread 4.1.0 开启 PM 电源管理框架

    前言 如今嵌入式产品越来越关注低功耗设计,也就是PM电源管理 如果使用裸机程序,低功耗的管理流程相对简单一些,在多任务的操作系统中,如基于RT-Thread,如何进行低功耗管理呢? RT-Thread ...

  7. Android电源管理分析

    Android电源管理 1.电源管理服务–PowerManagerService ​ PowerManagerService提供Android系统的电源管理服务,主要功能是控制系统的待机状态,控制显示 ...

  8. Linux运行时I/O设备的电源管理框架

    本文介绍Linux运行时I/O设备的电源管理框架.属于Linux内核文档的翻译. 原文:http://www.kernel.org/doc/Documentation/power/runtime_pm ...

  9. Linux运行时I/O设备的电源管理框架【转】

    转自:https://www.cnblogs.com/coryxie/archive/2013/03/01/2951243.html 本文介绍Linux运行时I/O设备的电源管理框架.属于Linux内 ...

  10. Android资源管理框架(Asset Manager)简要介绍和学习计划

    Android应用程序主要由两部分内容组成:代码和资源.资源主要就是指那些与UI相关的东西,例如UI布局.字符串和图片等.代码和资源分开可以使得应用程序在运行时根据实际需要来组织UI.这样就可使得应用 ...

最新文章

  1. linux存储--可执行文件结构和进程内存模型(三)
  2. STM32 定时器中断
  3. java两个数之间质数求法,求任意两个整数之间质数的个数的代码!!!(新手编写)...
  4. Python_51job爬虫
  5. python 工具ScreenShoot
  6. 贪心算法—建立雷达(POJ 1328)
  7. 如何在ASP.NET Core中编写自定义日志记录提供程序
  8. 3gpp协议_C-V2X: 3GPP协议阅读前的一些准备
  9. matlab 概率论,matlab.概率论.doc
  10. 软件性能中几个主要的术语
  11. 易速联服务器稳定吗,异速联如何保障应用安全性?
  12. python对称加密算法库_对称加密算法
  13. 爱加密加固病毒分析-破解篇
  14. 登录mysql服务器的典型命令_Mysql 远程登录及常用命令
  15. Snipaste截图软件的下载和使用(日常常用的一些功能)
  16. 崔荣容,英语如法入门1-50讲
  17. PIX飞控中POS数据读取方法(实用工具)
  18. 三栏式布局详解(代码+图解)
  19. ISP—自动白平衡(AWB)
  20. win10系统c盘C:Users后面的用户名怎么更改

热门文章

  1. python安装目录插件
  2. 计算机网络回顾之计算机网络概述
  3. 【转载】ASP.Net请求处理机制初步探索之旅 - Part 3 管道
  4. JasperReport生成pdf文件 Java开发pdf文件 pdf文件生成及下载
  5. 9:JDBC-Java API 实战
  6. 腾讯的职级系统——看清自己的职场宿命
  7. Fiddler之自动修改数据包(Free HTTP插件)
  8. 华为路由器AAA配置与管理
  9. php动态页面加载慢,小结:PHP动态网页程序优化及高效提速问题
  10. 扇贝单词英语版_产品分析报告