【Android休眠】之休眠锁的获取和释放
一、PowerManagerService
引起休眠动作(进入休眠前执行一些必要的操作)的事件有两个:
PowerKey事件,通过JNI调用PowerManagerService中的goToSleepFromNative()方法
Timeout,指【设置->显示->休眠】中设置的Timeout数值
Android休眠在PowerManagerService中的流程如下图:
图示:最终都会调用到updatePowerStateLocked()方法,在更新一些标志的状态、发送休眠通知后,调用updateSuspendBlockerLocked()执行休眠锁的释放动作。
二、PowerManagerService中Timeout处理流程
/**
* PowerManagerService设置了很多的标志位,用来标识某个事件的状态是否发生改变,比如:
* DIRTY_SETTINGS,一旦系统设置发生变化,DIRTY_SETTINGS位就会被设置,
* 处理函数检测到DIRTY_SETTINGS被置位,就进行相应的动作
* dirty:包含了所有发生变化的标志
*/
private void updateUserActivitySummaryLocked(long now, int dirty) {
// Update the status of the user activity timeout timer.
if ((dirty & (DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS | DIRTY_SETTINGS)) != 0) {
// 1、消息队列中含有尚未处理的MSG_USER_ACTIVITY_TIMEOUT,就移除,避免重复进入休眠操作
mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT);
long nextTimeout = 0;
// 2、mWakefulness != WAKEFULNESS_ASLEEP:当前醒着
if (mWakefulness != WAKEFULNESS_ASLEEP) {
// 3、获取Timeout的值,比如30s
final int screenOffTimeout = getScreenOffTimeoutLocked();
// 屏幕在熄灭前,会先变暗一段时间,这段时间叫DimDuration,计算方式:
// SCREEN_DIM_DURATION = 7s,MAXIMUM_SCREEN_DIM_RATIO = 0.2
// Math.min(SCREEN_DIM_DURATION, (int)(screenOffTimeout * MAXIMUM_SCREEN_DIM_RATIO))
// 4、获取DimDuration的值,30s x 0.2 = 6s
final int screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);
mUserActivitySummary = 0;
// 5、mLastUserActivityTime >= mLastWakeTime: 用户最后使用机器的时间在上次唤醒时间之后
if (mLastUserActivityTime >= mLastWakeTime) {
// nextTimeout:此处指到屏幕Dim的时间间隔
// 6、nextTimeout的时间:BASE + 30 - 6 = BASE + 24
nextTimeout = mLastUserActivityTime
+ screenOffTimeout - screenDimDuration;
if (now < nextTimeout) {
// now在屏幕Dim之前,说明屏幕亮着,设置flag
mUserActivitySummary |= USER_ACTIVITY_SCREEN_BRIGHT;
} else {
// extTimeout:此处指到屏幕熄灭的时间间隔
//7、nextTimeout的时间:BASE + 30 = BASE + 30
nextTimeout = mLastUserActivityTime + screenOffTimeout;
// 8、now处于屏幕Dim之后、屏幕熄灭之前设置DIM flag
if (now < nextTimeout) {
mUserActivitySummary |= USER_ACTIVITY_SCREEN_DIM;
}
}
}
if (mUserActivitySummary == 0
&& mLastUserActivityTimeNoChangeLights >= mLastWakeTime) {
nextTimeout = mLastUserActivityTimeNoChangeLights + screenOffTimeout;
if (now < nextTimeout
&& mDisplayPowerRequest.screenState
!= DisplayPowerRequest.SCREEN_STATE_OFF) {
mUserActivitySummary = mDisplayPowerRequest.screenState
== DisplayPowerRequest.SCREEN_STATE_BRIGHT ?
USER_ACTIVITY_SCREEN_BRIGHT : USER_ACTIVITY_SCREEN_DIM;
}
}
// mUserActivitySummary发生了改变
if (mUserActivitySummary != 0) {
Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT);
Slog.i(TAG, "updateUserActivitySummaryLocked, send MSG_USER_ACTIVITY_TIMEOUT");
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, nextTimeout);
}
} else {
mUserActivitySummary = 0;
}
}
}
MSG_USER_ACTIVITY_TIMEOUT事件处理:
private final class PowerManagerHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_USER_ACTIVITY_TIMEOUT:
handleUserActivityTimeout();
break;
}
}
/**
* Called when a user activity timeout has occurred.
* Simply indicates that something about user activity has changed so that the new
* state can be recomputed when the power state is updated.
*/
private void handleUserActivityTimeout() { // runs on handler thread
mDirty |= DIRTY_USER_ACTIVITY;
updatePowerStateLocked();
}
三、PowerManagerService中休眠锁的获取/释放
这部分代码清晰,直接看下:
private void updatePowerStateLocked() {
if (!mSystemReady || mDirty == 0) {
return;
}
// Phase 0: Basic state updates.
// Phase 1: Update wakefulness.
// Phase 2: Update dreams and display power state.
// Phase 3: Send notifications, if needed.
// Phase 4: Update suspend blocker.
// Because we might release the last suspend blocker here, we need to make sure
// we finished everything else first!
updateSuspendBlockerLocked();
}
/**
* Updates the suspend blocker that keeps the CPU alive.
*/
private void updateSuspendBlockerLocked() {
final boolean needWakeLockSuspendBlocker = ((mWakeLockSummary & WAKE_LOCK_CPU) != 0);
final boolean needDisplaySuspendBlocker = needDisplaySuspendBlocker();
// First acquire suspend blockers if needed.
if (needWakeLockSuspendBlocker && !mHoldingWakeLockSuspendBlocker) {
mWakeLockSuspendBlocker.acquire();
mHoldingWakeLockSuspendBlocker = true;
}
if (needDisplaySuspendBlocker && !mHoldingDisplaySuspendBlocker) {
mDisplaySuspendBlocker.acquire();
mHoldingDisplaySuspendBlocker = true;
}
// Then release suspend blockers if needed.
if (!needWakeLockSuspendBlocker && mHoldingWakeLockSuspendBlocker) {
mWakeLockSuspendBlocker.release();
mHoldingWakeLockSuspendBlocker = false;
}
if (!needDisplaySuspendBlocker && mHoldingDisplaySuspendBlocker) {
mDisplaySuspendBlocker.release();
mHoldingDisplaySuspendBlocker = false;
}
}
private final class SuspendBlockerImpl implements SuspendBlocker {
private final String mName;
private int mReferenceCount;
public SuspendBlockerImpl(String name) {
mName = name;
}
@Override
public void acquire() {
synchronized (this) {
mReferenceCount += 1;
if (mReferenceCount == 1) {
nativeAcquireSuspendBlocker(mName);
}
}
}
@Override
public void release() {
synchronized (this) {
mReferenceCount -= 1;
if (mReferenceCount == 0) {
nativeReleaseSuspendBlocker(mName);
}
}
}
}
休眠锁的获取和释放,最终通过JNI方式读写/sys/power/wake_lock、/sys/power/wake_unlock:
// 1、JNI接口
com_android_server_power_PowerManagerService.cpp (frameworks\base\services\jni)
static void nativeAcquireSuspendBlocker(JNIEnv *env, jclass clazz, jstring nameStr) {
ScopedUtfChars name(env, nameStr);
acquire_wake_lock(PARTIAL_WAKE_LOCK, name.c_str());
}
// 2、定义要操作的文件
power.c (hardware\libhardware_legacy\power)
const char * const NEW_PATHS[] = {
"/sys/power/wake_lock",
"/sys/power/wake_unlock",
};
// 3、初始化设备节点
static inline void initialize_fds(void)
{
if (g_initialized == 0) {
if(open_file_descriptors(NEW_PATHS) < 0)
open_file_descriptors(OLD_PATHS);
g_initialized = 1;
}
}
static int open_file_descriptors(const char * const paths[])
{
int i;
for (i=0; i<OUR_FD_COUNT; i++) {
int fd = open(paths[i], O_RDWR);
if (fd < 0) {
fprintf(stderr, "fatal error opening \"%s\"\n", paths[i]);
g_error = errno;
return -1;
}
g_fds[i] = fd;
}
g_error = 0;
return 0;
}
// 4、id即为锁的名字,之后就是读写设备
int acquire_wake_lock(int lock, const char* id)
{
initialize_fds();
if (g_error) return g_error;
int fd;
if (lock == PARTIAL_WAKE_LOCK) {
fd = g_fds[ACQUIRE_PARTIAL_WAKE_LOCK];
}
else {
return EINVAL;
}
return write(fd, id, strlen(id));
}
MSG_USER_ACTIVITY_TIMEOUT事件处理:
private final class PowerManagerHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_USER_ACTIVITY_TIMEOUT:
handleUserActivityTimeout();
break;
}
}
/**
* Called when a user activity timeout has occurred.
* Simply indicates that something about user activity has changed so that the new
* state can be recomputed when the power state is updated.
*/
private void handleUserActivityTimeout() { // runs on handler thread
mDirty |= DIRTY_USER_ACTIVITY;
updatePowerStateLocked();
}
三、PowerManagerService中休眠锁的获取/释放
这部分代码清晰,直接看下:
private void updatePowerStateLocked() {
if (!mSystemReady || mDirty == 0) {
return;
}
// Phase 0: Basic state updates.
// Phase 1: Update wakefulness.
// Phase 2: Update dreams and display power state.
// Phase 3: Send notifications, if needed.
// Phase 4: Update suspend blocker.
// Because we might release the last suspend blocker here, we need to make sure
// we finished everything else first!
updateSuspendBlockerLocked();
}
/**
* Updates the suspend blocker that keeps the CPU alive.
*/
private void updateSuspendBlockerLocked() {
final boolean needWakeLockSuspendBlocker = ((mWakeLockSummary & WAKE_LOCK_CPU) != 0);
final boolean needDisplaySuspendBlocker = needDisplaySuspendBlocker();
// First acquire suspend blockers if needed.
if (needWakeLockSuspendBlocker && !mHoldingWakeLockSuspendBlocker) {
mWakeLockSuspendBlocker.acquire();
mHoldingWakeLockSuspendBlocker = true;
}
if (needDisplaySuspendBlocker && !mHoldingDisplaySuspendBlocker) {
mDisplaySuspendBlocker.acquire();
mHoldingDisplaySuspendBlocker = true;
}
// Then release suspend blockers if needed.
if (!needWakeLockSuspendBlocker && mHoldingWakeLockSuspendBlocker) {
mWakeLockSuspendBlocker.release();
mHoldingWakeLockSuspendBlocker = false;
}
if (!needDisplaySuspendBlocker && mHoldingDisplaySuspendBlocker) {
mDisplaySuspendBlocker.release();
mHoldingDisplaySuspendBlocker = false;
}
}
private final class SuspendBlockerImpl implements SuspendBlocker {
private final String mName;
private int mReferenceCount;
public SuspendBlockerImpl(String name) {
mName = name;
}
@Override
public void acquire() {
synchronized (this) {
mReferenceCount += 1;
if (mReferenceCount == 1) {
nativeAcquireSuspendBlocker(mName);
}
}
}
@Override
public void release() {
synchronized (this) {
mReferenceCount -= 1;
if (mReferenceCount == 0) {
nativeReleaseSuspendBlocker(mName);
}
}
}
}
休眠锁的获取和释放,最终通过JNI方式读写/sys/power/wake_lock、/sys/power/wake_unlock:
// 1、JNI接口
com_android_server_power_PowerManagerService.cpp (frameworks\base\services\jni)
static void nativeAcquireSuspendBlocker(JNIEnv *env, jclass clazz, jstring nameStr) {
ScopedUtfChars name(env, nameStr);
acquire_wake_lock(PARTIAL_WAKE_LOCK, name.c_str());
}
// 2、定义要操作的文件
power.c (hardware\libhardware_legacy\power)
const char * const NEW_PATHS[] = {
"/sys/power/wake_lock",
"/sys/power/wake_unlock",
};
// 3、初始化设备节点
static inline void initialize_fds(void)
{
if (g_initialized == 0) {
if(open_file_descriptors(NEW_PATHS) < 0)
open_file_descriptors(OLD_PATHS);
g_initialized = 1;
}
}
static int open_file_descriptors(const char * const paths[])
{
int i;
for (i=0; i<OUR_FD_COUNT; i++) {
int fd = open(paths[i], O_RDWR);
if (fd < 0) {
fprintf(stderr, "fatal error opening \"%s\"\n", paths[i]);
g_error = errno;
return -1;
}
g_fds[i] = fd;
}
g_error = 0;
return 0;
}
// 4、id即为锁的名字,之后就是读写设备
int acquire_wake_lock(int lock, const char* id)
{
initialize_fds();
if (g_error) return g_error;
int fd;
if (lock == PARTIAL_WAKE_LOCK) {
fd = g_fds[ACQUIRE_PARTIAL_WAKE_LOCK];
}
else {
return EINVAL;
}
return write(fd, id, strlen(id));
}
赞 (0)