Android电源管理框架

本文详细介绍了Android电源管理框架的层次结构,从应用层、框架层、HAL层到Kernel层的功能,强调了PowerManagerService在电源管理中的核心作用,以及低功耗模式如早期暂停、暂停和休眠。此外,还探讨了用户活动如何影响系统休眠以及PowerManagerService的工作流程。

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.youkuaiyun.com/gaugamela/article/details/52785041

http://www.myexception.cn/android/2076061.html

http://blog.youkuaiyun.com/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");//控制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主要用于按键灯,屏幕亮度自动调节,处理显示请求











评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值