受不了xxxx恶心人的行为,遂搬迁至博客园。 始发:2016-12-16 13:11:41 版本信息: Linux:3.10 Android:4.4
一、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; } } }
SG_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)); }