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主要用于按键灯,屏幕亮度自动调节,处理显示请求