小工具知识网

当前位置: 首页 > 行业知识 > Android休眠流程

行业知识

Android休眠流程

2026-11-05 16:36:09 来源:互联网转载
  1. 概述

    设备的休眠是功耗分析中的重要篇章,有些问题经常会涉及到系统无法休眠,经常被唤醒等情况。在这里将从代码角度来分析下Android系统休眠和唤醒的机制,而本篇将着重阐述休眠机制。

Android系统的电源管理子系统是已Linux的电源管理系统为基础,针对现实问题又进行了改造,而这里的现实问题来自于PC和移动设备的差异,其核心在于什么时候休眠,什么时候唤醒。在PC系统中,什么时候让系统进入休眠(通常是STR、Standby、Hibernate等suspend操作)这个问题很容易理解:答案就是由用户在其不再使用时触发。

然而移动设备的特性决定了用户可能随时随地会使用设备,那么休眠的时机就变得非常不明确了。于是Android上提出了Opportunistic suspend这个概念,通俗的讲就是逮住机会就赶紧休眠一会儿直到下次被唤醒,而这个机会就是系统没有任务需要处理的时候。由此就衍生除了autosleep机制和wake source的概念。Android的休眠是一种自动休眠,当系统中不存在唤醒源时就进行系统整体休眠。相比于Linux内核中复杂的单独模块休眠管理(Dynamic PM),Android的此套设计方式简单粗暴,但是实实在在的解决了移动设备上面临的燃眉之急。

2.自动休眠

2. 1.Frameworks层

备注:自动休眠一定不能插上usb抓取log,因插上usb不会进入休眠模式。

系统休眠又用户主动发起的关系并不是很大,在用户和应用的行为中,主动通过power键发起灭屏或者是调用PowerManager的goToSleep接口来进行系统休眠是较常用的操作,其他也没有更多的手段。而系统休眠大多是系统主动检测并发起休眠流程,所以本篇中就不涉及上层的流程了,直接从Frameworks开始。

Frameworks层这部分的设计思想比较简单,主要是:电源管理通过监测display的状态,当灭屏时则发起休眠的流程,调用native层的方法继续往下走。这里就很好的体现了前文提到的Opportunistic suspend概念,伺机休眠这里的“机”的第一层就是以灭屏作为契机的。果然是简单粗暴的判断,但是非常实用,从用户角度来将,灭屏的现象确实是让设备休眠的理想触发。当然,在灭屏时需要后台处理任务的情况也是存在,所以在后面流程中会继续判断是否真正能够进入休眠。接下来从代码角度解读下frameworks层的实现。

  流程就先从灭屏开始看,系统中除了PowerManagerService外还有个叫做DisplayManagerService的核心服务来管理display相关的电源状态,它也是在SystemServer中启动起来的。在PowerManagerService中systemReady方法中会去初始化DisplayManagerService

frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java

// Initialize display power management.mDisplayManagerInternal.initPowerManagement(        mDisplayPowerCallbacks, mHandler, sensorManager);

DisplayManagerService中的initPowerManagement相关部分如下:

private final class LocalService extends DisplayManagerInternal {    @Override    public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler,            SensorManager sensorManager) {        synchronized (mSyncRoot) {            DisplayBlanker blanker = new DisplayBlanker() {                @Override                public void requestDisplayState(int state, int brightness) {                    // The order of operations is important for legacy reasons.                    if (state == Display.STATE_OFF) {                        requestGlobalDisplayStateInternal(state, brightness);                    }                    callbacks.onDisplayStateChange(state);                    if (state != Display.STATE_OFF) {                        requestGlobalDisplayStateInternal(state, brightness);                    }                }            };            mDisplayPowerController = new DisplayPowerController(                    mContext, callbacks, handler, sensorManager, blanker);        }        mHandler.sendEmptyMessage(MSG_LOAD_BRIGHTNESS_CONFIGURATION);    }

实现了DisplayBlanker接口,并重写了其requestDisplayState方法,在此方法中又调用DisplayPowerCallbacks接口的onDisplayStateChange方法来进行display发生变化之后的操作。这一段为整个frameworks流程中的核心部分也是流程的中间部分,接下来补上它的头和尾。

首先是display改变的消息传递,也就是代码流程中如何会调用到DisplayBlanker接口的requestDisplayState,来看图就可以了:

首先是在DisplayPowerController中收到MSG_UPDATE_POWER_STATE消息,随后经过一系列的回调了DisplayBlanker接口的requestDisplayState,其中每个细节不是这里的重点就不展开一一分析了。然后是尾,DisplayPowerCallbacks接口的onDisplayStateChange方法在PowerManagerService中

public void onDisplayStateChange(int state) {    // This method is only needed to support legacy display blanking behavior    // where the display's power state is coupled to suspend or to the power HAL.    // The order of operations matters here.    synchronized (mLock) {        if (mDisplayState != state) {// display的状态发生改变            mDisplayState = state;            if (state == Display.STATE_OFF) {// 灭屏                if (!mDecoupleHalInteractiveModeFromDisplayConfig) {// 默认false                    setHalInteractiveModeLocked(false);// 关闭交互模式                }                if (!mDecoupleHalAutoSuspendModeFromDisplayConfig) {// 默认false                    setHalAutoSuspendModeLocked(true);// 开启autosleep模式                }            } else {// 亮屏                if (!mDecoupleHalAutoSuspendModeFromDisplayConfig) {                    setHalAutoSuspendModeLocked(false);// 关闭autosleep模式                }                if (!mDecoupleHalInteractiveModeFromDisplayConfig) {                    setHalInteractiveModeLocked(true);// 开启交互模式                }            }        }    }}

这一段中有一个非常重要的核心:前面提到了将灭屏作为休眠发起的条件,也就是说将灭屏和休眠作为了耦合的关系,而这里提供了解耦的操作,可以在代码配置中来选择是否要解耦。判断的依据就是mDecoupleHalAutoSuspendModeFromDisplayConfig这个变量,它的默认值定义在frameworks/base/core/res/res/values/config.xml中:

false

解读:默认情况下将suspend流程和display的状态耦合在一起,默认为false(不解耦),在默认情况下,在屏幕off之后调用启用autosuspend,在屏幕on之前关闭autosuspend_enable。而如果解耦,那么suspend的流程将被独立调用而不管屏幕状态,在此模式下就算是屏幕on也允许系统休眠。

这一段代码中还包括了另外一个操作,setHalInteractiveModeLocked来设置系统可交互模式,由mDecoupleHalInteractiveModeFromDisplayConfig这个变量来控制和display的耦合关系。同样附上这个默认值的定义:

false

解读:这里描述了系统的可交互模式和display的耦合关系。当设置为false时,两者为耦合的关系,在display状态on之前setInteractive(…, true)设置为可交互;在display状态为off之后设置为不可交互。而如果为解耦状态,那么交互模式也将可以被独立设置不论display的状态如何。

我们还是来继续看auto sleep的流程,当灭屏时,调用PowerManagerService的setHalAutoSuspendModeLocked(true)

frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java

private void setHalAutoSuspendModeLocked(boolean enable) {    if (enable != mHalAutoSuspendModeEnabled) {        if (DEBUG) {            Slog.d(TAG, "Setting HAL auto-suspend mode to " + enable);        }        mHalAutoSuspendModeEnabled = enable;        Trace.traceBegin(Trace.TRACE_TAG_POWER, "setHalAutoSuspend(" + enable + ")");        try {            mNativeWrapper.nativeSetAutoSuspend(enable);        } finally {            Trace.traceEnd(Trace.TRACE_TAG_POWER);        }    }}

这里只是做了些判断和加调试代码,然后将流程通过nativeSetAutoSuspend带入到了native库中。

2.2. Native层

根据JNI的机制可以找到代码进入到了com_android_server_power_PowerManagerService.cpp中的nativeSetAutoSuspend中:

frameworks/base/services/core/jni/com_android_server_power_PowerManagerService.cpp

static void nativeSetAutoSuspend(JNIEnv* /* env /, jclass / clazz */, jboolean enable) {

if (enable) {

android::base::Timer t;

enableAutoSuspend();

if (t.duration() > 100ms) {

ALOGD(“Excessive delay in autosuspend_enable() while turning screen off”);

}

} else {

android::base::Timer t;

disableAutoSuspend();

if (t.duration() > 100ms) {

ALOGD(“Excessive delay in autosuspend_disable() while turning screen on”);

}

}

}

当灭屏时(默认情况下)调用autosuspend_enable(),然后进一步的实现在hal文件中,源代码位于system/hardware/interfaces/suspend/1.0/default/目录下。

2.2.1 休眠机制初始化

来看一下开启自动挂起模式的实现方法——enableAutoSuspend

com_android_server_power_PowerManagerService.cpp

void enableAutoSuspend() {

static bool enabled = false;

//suspendService != nullptr && suspendService->enableAutosuspend():从后面的代码可以看到这个值决定了enlable的值,在开机执行一次

if (!enabled) {

sp suspendControl = getSuspendControl();

suspendControl->enableAutosuspend(&enabled);

}

{    std::lock_guard lock(gSuspendMutex);    if (gSuspendBlocker) {        gSuspendBlocker->release();        gSuspendBlocker.clear();    }}

}

sp getSuspendControl() {

static std::once_flag suspendControlFlag;

std::call_once(suspendControlFlag, {

while(gSuspendControl == nullptr) {

sp control =

defaultServiceManager()->getService(String16(“suspend_control”));

if (control != nullptr) {

gSuspendControl = interface_cast(control);

}

}

});

return gSuspendControl;

}

这里有一个难点,通过getSuspendControl方法获得的ISuspendControlService实现类是什么? 请注意getSuspendControl方法里的这条语句: defaultServiceManager()->getService(String16(“suspend_control”)),这是一个典型的Binder调用,它请求了服务名称为 suspend_control 的远端服务。注册名称为suspend_control的服务到底是谁,我们可以在/system/hardware/interfaces/suspend/1.0/default/main.cpp中找到答案。

sp suspendControl = new SuspendControlService();

auto controlStatus = android::defaultServiceManager()->addService(

android::String16(“suspend_control”), suspendControl);

可以清楚的看到,SuspendControlService就是我们要寻找的答案。

SuspendControlService.cpp

binder::Status SuspendControlService::enableAutosuspend(bool* _aidl_return) {

//wp 升级为 sp,这条语句牵涉到 android 智能指针相关的知识点 promote方法可以将弱指针升级为强指针

const auto suspendService = mSuspend.promote();

//调用到了 SystemSuspend.cpp 的enableAutosuspend 方法

return retOk(suspendService != nullptr && suspendService->enableAutosuspend(), _aidl_return);

}

SuspendControlService.cpp

binder::Status retOk(const T& value, T* ret_val) {

*ret_val = value;

return binder::Status::ok();

}

SystemSuspend.cpp

bool SystemSuspend::enableAutosuspend() {

static bool initialized = false;

if (initialized) {

LOG(ERROR)

上一篇:揭秘智能点餐源码,开启轻松餐饮新时代!

下一篇:手机qq群怎么加好友?