Android7.0 PowerManagerService(1) 启动过程

本文详细解析了Android系统的PowerManagerService(PMS)启动过程,包括构造函数、onStart方法及systemReady方法的具体流程。介绍了PMS如何通过Binder注册自身服务,并与其他系统组件交互。

PowerManagerService负责Android系统中电源管理方面的工作,为了简便我们在下文中将其简称为PMS。

我们先大致了解一下PMS在Android中的整体结构: 
 
如上图所示,可以看出PMS的对外接口是PowerManager,其通过Binder通信来调用PMS中定义的BinderService的接口。 
BinderService与PowerManger之间的通信接口由IPowerManager.aidl来进行约束。

PMS由SystemServer来启动,我们看看SystemServer.java中相关的代码:

private void startBootstrapServices() {
    ..........
    mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
    ..........
}

private void startOtherServices() {
    ........
    try {
        mPowerManagerService.systemReady(mActivityManagerService.getAppOpsService());
        .........
    } catch (Throwable e) {
        .........
    }
    ........
}
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

SystemServer.java中PMS涉及的地方主要有两处: 
1、利用startService启动PMS。 
之前分析PKMS时我们已经提过,startService主要通过反射调用服务的构造函数,然后再调用服务的onStart函数。 
2、调用PMS的systemReady方法。 
接下来我们就分三部分,分别看看PMS的构造函数、onStart函数及systemReady函数涉及到的流程。

一、构造函数 
PowerManagerService的构造函数如下所示:

public PowerManagerService(Context context) {
    ............
    //ServiceThread继承自HandlerThread,专门针对系统服务定义的,应该是优先级更高吧
    mHandlerThread = new ServiceThread(TAG,
            Process.THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
    mHandlerThread.start();
    mHandler = new PowerManagerHandler(mHandlerThread.getLooper());

    synchronized (mLock) {
        //创建一些锁对象,同构acquire和release修改引用数
        mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks");
        mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display");
        mDisplaySuspendBlocker.acquire();
        mHoldingDisplaySuspendBlocker = true;
        mHalAutoSuspendModeEnabled = false;
        mHalInteractiveModeEnabled = true;

        mWakefulness = WAKEFULNESS_AWAKE;

        nativeInit();
        nativeSetAutoSuspend(false);
        nativeSetInteractive(true);
        nativeSetFeature(POWER_FEATURE_DOUBLE_TAP_TO_WAKE, 0);
    }
}
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

容易看出PMS的构造函数较为简单,仅需要进一步分析其native函数的作用。 
在com_android_server_power_PowerManagerService.cpp中:

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);
    }
}
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

从上面的代码可以看出,PMS的构造函数还是比较简单的,就是创建一些基本的成员,然后利用native函数加载底层的动态库,并设置一些状态和标志位。

二、onStart 
接下来我们看看PMS的onStart函数:

public void onStart() {
    publishBinderService(Context.POWER_SERVICE, new BinderService());
    publishLocalService(PowerManagerInternal.class, new LocalService());

    Watchdog.getInstance().addMonitor(this);
    Watchdog.getInstance().addThread(mHandler);
}
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

从代码来看,onStart内容可以分成3类,即发布BinderService、发布LocalService和完成watchdog相关的工作。 
我们分别看看这3类工作具体的流程。

1、publishBinderService 
publishBinderService定义在PMS的父类SystemService中:

//PMS中的BinderService继承自IPowerManager.Stub,实现了IBinder接口
//name为PMS的名称,power
protected final void publishBinderService(String name, IBinder service) {
    publishBinderService(name, service, false);
}

protected final void publishBinderService(String name, IBinder service,
        boolean allowIsolated) {
    //调用ServiceManger的接口,实际上利用Binder通信向Service Manger进程注册服务
    ServiceManager.addService(name, service, allowIsolated);
}
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

通过上述代码,PMS就将内部定义的BinderService注册到Service Manager进程,对应的名称为”power”。

2、publishLocalService 
publishLocalService同样定义在PMS的父类SystemService中:

//参数中的LocalService继承自PowerManagerInternal类
protected final <T> void publishLocalService(Class<T> type, T service) {
    LocalServices.addService(type, service);
}
 
  • 1
  • 2
  • 3
  • 4

我们来看看LocalServices类的addService函数:

/**
* Adds a service instance of the specified interface to the global registry of local services.
*/
public static <T> void addService(Class<T> type, T service) {
    synchronized (sLocalServiceObjects) {
        if (sLocalServiceObjects.containsKey(type)) {
            throw new IllegalStateException("Overriding service registration");
        }
        sLocalServiceObjects.put(type, service);
    }
}
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

从代码来看,LocalServices的作用与单例模式有些相似,不过更为严格。 
单例模式用于保证某个类只能创建出一个对象; LocalServices管理对象时,确保继承某个类或接口的对象只有一个。 
目前,还看不出PMS利用LocalServices管理其内部的LocalService的理由,先在此留个悬念。

3、watchdog相关工作 
在之前的博客中,分析过Android 6.0中watchdog流程。 
对于watchdog而言,Android 7.0与Android 6.0基本类似,这里仅再简单介绍一下涉及到的流程。

//PMS实现了Watchdog.Monitor接口,下面的代码将PMS加入到watchdog的mMonitorChecker中
Watchdog.getInstance().addMonitor(this);
//将PMS的ServiceThread对对应的handler传入watchdog中,watchdog将利用该handler构造一个HandlerChecker
Watchdog.getInstance().addThread(mHandler);
 
  • 1
  • 2
  • 3
  • 4

3.1 addThread 
当PMS调用addThread时,watchDog利用mHandler构造一个HandlerChecker,然后周期性地调用HandlerChecker的scheduleCheckLocked方法:

public void scheduleCheckLocked() {
    //PMS对应的HandlerChecker没有monitor,因此mMonitors.size()恒等于0
    //调用MessageQueue的isPolling函数,判断是否处于polling状态;
    //当MessageQueue native层的looper处于等待状态,即没有事件需要处理时,isPolling返回true
    if (mMonitors.size() == 0 && mHandler.getLooper().getQueue().isPolling()) {
        mCompleted = true;
        return;
    }

    if (!mCompleted) {
        // we already have a check in flight, so no need
        return;
    }

    mCompleted = false;
    mCurrentMonitor = null;
    mStartTime = SystemClock.uptimeMillis();
    //HandlerChecker继承runnable,这里的意思是向PMS的handler发送一个HandlerChecker类型的runnable事件
    mHandler.postAtFrontOfQueue(this);
}

public void run() {
    final int size = mMonitors.size();
    //PMS对应的HandlerChecker的mMonitors.size为0,跳过
    for (int i = 0 ; i < size ; i++) {
        synchronized (Watchdog.this) {
            mCurrentMonitor = mMonitors.get(i);
        }
        mCurrentMonitor.monitor();
    }

    //只要PMS的mHandler在规定事件内,执行了上文传入的runnable事件,就说明没有阻塞,PMS是正常的
    synchronized (Watchdog.this) {
        mCompleted = true;
        mCurrentMonitor = null;
    }
}
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

3.2 addMonitor 
当PMS调用watchDog的addMonitor函数后,watchDog就会周期性地调用PMS的monitor接口:

public void monitor() {
    // Grab and release lock for watchdog monitor to detect deadlocks.
    synchronized (mLock) {
    }
}
 
  • 1
  • 2
  • 3
  • 4
  • 5

PMS只要能在规定时间内获得mLock锁,watchDog就能确认PMS没有死锁,状态正常。

以上只是简略介绍了一下watchDog相关的内容,详情可以参考下面的博客。 
Android6.0 watchdog

三、systemReady 
接下来我们看一下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();
    }
}
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84

从代码来看,PMS在systemReady中主要是获得一些成员变量,注册一些广播接收对象、读取一些配置参数等。虽然PMS会与多个服务打交道,使得systemReady内容较为庞杂,但整个过程比较简单。

在systemReady函数的最后,调用了一个比较重要的函数updatePowerStateLocked。当PMS监控到终端发生重大变化时,将利用该函数集中更新所有相关的状态。updatePowerStateLocked涉及的内容较多,等对PMS整体有了初步的了解后,再来分析这个函数。

总结 

本篇博客侧重于介绍PMS的启动过程,同时对PMS需要打交道的服务建立一个基本的认识。


原文地址: http://blog.youkuaiyun.com/gaugamela/article/details/52785041

<think>我们正在分析Android系统中Power Manager服务(PMS)的屏幕亮灭流程。根据引用内容,我们可以构建一个从按键事件到屏幕状态变化的完整流程。以下将结合引用信息逐步分析: ### 1. **按键事件触发** 当用户按下Power键时,Input子系统会捕获该事件并传递给上层。在`PhoneWindowManager`中,会调用`wakeUpFromWakeKey`方法处理亮屏请求(引用[5]): ```java private void wakeUpFromWakeKey(KeyEvent event) { // 亮屏,原因是WAKE_REASON_WAKE_KEY,details是"android.policy:KEY" if (wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, PowerManager.WAKE_REASON_WAKE_KEY, "android.policy:KEY")) { // ... 可能启动HOME界面 } } ``` 这里通过`wakeUp`方法向PowerManagerService发起亮屏请求。 ### 2. **PowerManagerService处理亮屏请求** 在PMS中,会计算屏幕状态、亮度等参数,并与ActivityManagerService(AMS)、WindowManagerService(WMS)等模块交互(引用[3])。核心流程包括: - 更新电源状态(如从休眠状态切换到亮屏状态) - 计算屏幕亮度曲线(考虑自动亮度、环境光等) - 通知AMS/WMS准备界面绘制 ### 3. **底层LCD控制** PMS最终会通过写入`/sys/power/state`节点控制屏幕状态(引用[4]): - 亮屏:调用`autosuspend_disable()`,向节点写入`on` - 灭屏:写入`mem`(或其他休眠状态字符串) 在写入节点后,会触发LCD的`late_resume`操作(如`sprdfb_dispc_resume`函数),硬件完成屏幕点亮。 ### 4. **灭屏流程** 灭屏流程与亮屏类似,但方向相反(引用[1][2]): 1. Power键事件触发`goToSleep`方法 2. PMS计算休眠状态 3. 通知AMS/WMS进入休眠(暂停界面绘制) 4. 写入`/sys/power/state`节点(如`mem`)关闭屏幕 ### 5. **关键节点总结** | **阶段** | **关键操作** | |----------------|-----------------------------------------------------------------------------| | **按键捕获** | `PhoneWindowManager`处理Power键事件,调用`wakeUp`或`goToSleep` | | **PMS状态计算**| 更新全局电源状态,与AMS/WMS交互,计算亮度/超时等参数 | | **底层控制** | 通过`/sys/power/state`节点控制LCD电源,调用驱动层`resume/suspend`函数 | > **注意**:不同Android版本或厂商定制可能修改流程细节,但核心框架保持一致。 §§相关问题§§ 1. Power键事件如何从内核传递到Android框架层? 2. PMS与WakeLock机制如何协同工作? 3. 自动亮度调节在亮灭屏流程中如何生效? 4. 灭屏时如何保证应用数据安全?</think>### Android Power Manager 屏幕亮灭流程分析 Android的电源管理核心是`PowerManagerService`(PMS),屏幕亮灭流程涉及**输入事件处理、状态计算、跨模块协作、硬件控制**四个关键阶段。以下是基于Android 7.0+的流程解析(兼容至Android 11): --- #### **1. 输入事件捕获** 当用户按下Power键: - **Input子系统**捕获按键事件,通过`InputReader`/`InputDispatcher`传递到上层。 - **`PhoneWindowManager`** 处理事件: ```java // PhoneWindowManager.java private void wakeUpFromWakeKey(KeyEvent event) { if (wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, PowerManager.WAKE_REASON_WAKE_KEY, "android.policy:KEY")) { // 若满足条件(如长按HOME键),启动HOME界面 } } ``` 调用`PowerManager.wakeUp()`触发亮屏流程[^5]。 --- #### **2. PMS状态计算与决策** **`PowerManagerService`** 执行核心逻辑: - **状态机切换**:从`OFF`状态切换到`ON`或`DREAM`状态。 - **参数计算**: - 屏幕亮度(结合自动亮度调节) - 超时时间(根据用户设置、传感器数据) - 电源策略(如是否允许剧院模式唤醒) - **跨模块协作**: - 通知`ActivityManagerService`(AMS)准备应用界面绘制。 - 同步`WindowManagerService`(WMS)更新窗口状态[^3]。 --- #### **3. 底层硬件控制** PMS通过**HAL层**操作显示设备: 1. **禁用自动挂起**: ```c autosuspend_disable(); // 向/sys/power/state写入"on" ``` 2. **唤醒显示控制器**: - 调用`late_resume()`恢复LCD(如`sprdfb_dispc_resume`函数)。 - 硬件初始化时间因设备而异[^4]。 3. **设置亮度**: - 通过`/sys/class/backlight`节点写入亮度值。 > 💡 **灭屏流程相反**: > 1. PMS计算休眠策略(如`USER_ACTIVITY`超时)。 > 2. 通知AMS/WMS暂停界面。 > 3. 向`/sys/power/state`写入`mem`触发LCD休眠[^1][^2]。 --- #### **4. 关键参与模块** | **模块** | **职责** | |------------------------|---------------------------------------| | `PhoneWindowManager` | 输入事件路由 | | `PowerManagerService` | 电源策略决策、状态管理 | | `DisplayManagerService`| 显示设备控制(亮度/状态) | | `ActivityManagerService` | 协调应用生命周期 | | 内核驱动 | 操作`/sys/power`节点控制硬件电源状态 | --- ### 流程总结 ```mermaid graph TD A[Power键按下] --> B{Input子系统捕获} B --> C[PhoneWindowManager处理] C --> D[PMS唤醒请求] D --> E[状态计算+跨模块协作] E --> F[写入/sys/power/state] F --> G[内核控制LCD亮起] ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值