【Android休眠】之休眠锁的获取和释放

一、PowerManagerService
引起休眠动作(进入休眠前执行一些必要的操作)的事件有两个:

PowerKey事件,通过JNI调用PowerManagerService中的goToSleepFromNative()方法
Timeout,指【设置->显示->休眠】中设置的Timeout数值
Android休眠在PowerManagerService中的流程如下图:

图示:最终都会调用到updatePowerStateLocked()方法,在更新一些标志的状态、发送休眠通知后,调用updateSuspendBlockerLocked()执行休眠锁的释放动作。

二、PowerManagerService中Timeout处理流程

  1. /**
  2. * PowerManagerService设置了很多的标志位,用来标识某个事件的状态是否发生改变,比如:
  3. * DIRTY_SETTINGS,一旦系统设置发生变化,DIRTY_SETTINGS位就会被设置,
  4. * 处理函数检测到DIRTY_SETTINGS被置位,就进行相应的动作
  5. * dirty:包含了所有发生变化的标志
  6. */
  7. private void updateUserActivitySummaryLocked(long now, int dirty) {
  8. // Update the status of the user activity timeout timer.
  9. if ((dirty & (DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS | DIRTY_SETTINGS)) != 0) {
  10. // 1、消息队列中含有尚未处理的MSG_USER_ACTIVITY_TIMEOUT,就移除,避免重复进入休眠操作
  11. mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT);
  12. long nextTimeout = 0;
  13. // 2、mWakefulness != WAKEFULNESS_ASLEEP:当前醒着
  14. if (mWakefulness != WAKEFULNESS_ASLEEP) {
  15. // 3、获取Timeout的值,比如30s
  16. final int screenOffTimeout = getScreenOffTimeoutLocked();
  17. // 屏幕在熄灭前,会先变暗一段时间,这段时间叫DimDuration,计算方式:
  18. // SCREEN_DIM_DURATION = 7s,MAXIMUM_SCREEN_DIM_RATIO = 0.2
  19. // Math.min(SCREEN_DIM_DURATION, (int)(screenOffTimeout * MAXIMUM_SCREEN_DIM_RATIO))
  20. // 4、获取DimDuration的值,30s x 0.2 = 6s
  21. final int screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);
  22. mUserActivitySummary = 0;
  23. // 5、mLastUserActivityTime >= mLastWakeTime: 用户最后使用机器的时间在上次唤醒时间之后
  24. if (mLastUserActivityTime >= mLastWakeTime) {
  25. // nextTimeout:此处指到屏幕Dim的时间间隔
  26. // 6、nextTimeout的时间:BASE + 30 - 6 = BASE + 24
  27. nextTimeout = mLastUserActivityTime
  28. + screenOffTimeout - screenDimDuration;
  29. if (now < nextTimeout) {
  30. // now在屏幕Dim之前,说明屏幕亮着,设置flag
  31. mUserActivitySummary |= USER_ACTIVITY_SCREEN_BRIGHT;
  32. } else {
  33. // extTimeout:此处指到屏幕熄灭的时间间隔
  34. //7、nextTimeout的时间:BASE + 30 = BASE + 30
  35. nextTimeout = mLastUserActivityTime + screenOffTimeout;
  36. // 8、now处于屏幕Dim之后、屏幕熄灭之前设置DIM flag
  37. if (now < nextTimeout) {
  38. mUserActivitySummary |= USER_ACTIVITY_SCREEN_DIM;
  39. }
  40. }
  41. }
  42. if (mUserActivitySummary == 0
  43. && mLastUserActivityTimeNoChangeLights >= mLastWakeTime) {
  44. nextTimeout = mLastUserActivityTimeNoChangeLights + screenOffTimeout;
  45. if (now < nextTimeout
  46. && mDisplayPowerRequest.screenState
  47. != DisplayPowerRequest.SCREEN_STATE_OFF) {
  48. mUserActivitySummary = mDisplayPowerRequest.screenState
  49. == DisplayPowerRequest.SCREEN_STATE_BRIGHT ?
  50. USER_ACTIVITY_SCREEN_BRIGHT : USER_ACTIVITY_SCREEN_DIM;
  51. }
  52. }
  53. // mUserActivitySummary发生了改变
  54. if (mUserActivitySummary != 0) {
  55. Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT);
  56. Slog.i(TAG, "updateUserActivitySummaryLocked, send MSG_USER_ACTIVITY_TIMEOUT");
  57. msg.setAsynchronous(true);
  58. mHandler.sendMessageAtTime(msg, nextTimeout);
  59. }
  60. } else {
  61. mUserActivitySummary = 0;
  62. }
  63. }
  64. }
  65. MSG_USER_ACTIVITY_TIMEOUT事件处理:
  66. private final class PowerManagerHandler extends Handler {
  67. @Override
  68. public void handleMessage(Message msg) {
  69. switch (msg.what) {
  70. case MSG_USER_ACTIVITY_TIMEOUT:
  71. handleUserActivityTimeout();
  72. break;
  73. }
  74. }
  75. /**
  76. * Called when a user activity timeout has occurred.
  77. * Simply indicates that something about user activity has changed so that the new
  78. * state can be recomputed when the power state is updated.
  79. */
  80. private void handleUserActivityTimeout() { // runs on handler thread
  81. mDirty |= DIRTY_USER_ACTIVITY;
  82. updatePowerStateLocked();
  83. }
  84. 三、PowerManagerService中休眠锁的获取/释放
  85. 这部分代码清晰,直接看下:
  86. private void updatePowerStateLocked() {
  87. if (!mSystemReady || mDirty == 0) {
  88. return;
  89. }
  90. // Phase 0: Basic state updates.
  91. // Phase 1: Update wakefulness.
  92. // Phase 2: Update dreams and display power state.
  93. // Phase 3: Send notifications, if needed.
  94. // Phase 4: Update suspend blocker.
  95. // Because we might release the last suspend blocker here, we need to make sure
  96. // we finished everything else first!
  97. updateSuspendBlockerLocked();
  98. }
  99. /**
  100. * Updates the suspend blocker that keeps the CPU alive.
  101. */
  102. private void updateSuspendBlockerLocked() {
  103. final boolean needWakeLockSuspendBlocker = ((mWakeLockSummary & WAKE_LOCK_CPU) != 0);
  104. final boolean needDisplaySuspendBlocker = needDisplaySuspendBlocker();
  105. // First acquire suspend blockers if needed.
  106. if (needWakeLockSuspendBlocker && !mHoldingWakeLockSuspendBlocker) {
  107. mWakeLockSuspendBlocker.acquire();
  108. mHoldingWakeLockSuspendBlocker = true;
  109. }
  110. if (needDisplaySuspendBlocker && !mHoldingDisplaySuspendBlocker) {
  111. mDisplaySuspendBlocker.acquire();
  112. mHoldingDisplaySuspendBlocker = true;
  113. }
  114. // Then release suspend blockers if needed.
  115. if (!needWakeLockSuspendBlocker && mHoldingWakeLockSuspendBlocker) {
  116. mWakeLockSuspendBlocker.release();
  117. mHoldingWakeLockSuspendBlocker = false;
  118. }
  119. if (!needDisplaySuspendBlocker && mHoldingDisplaySuspendBlocker) {
  120. mDisplaySuspendBlocker.release();
  121. mHoldingDisplaySuspendBlocker = false;
  122. }
  123. }
  124. private final class SuspendBlockerImpl implements SuspendBlocker {
  125. private final String mName;
  126. private int mReferenceCount;
  127. public SuspendBlockerImpl(String name) {
  128. mName = name;
  129. }
  130. @Override
  131. public void acquire() {
  132. synchronized (this) {
  133. mReferenceCount += 1;
  134. if (mReferenceCount == 1) {
  135. nativeAcquireSuspendBlocker(mName);
  136. }
  137. }
  138. }
  139. @Override
  140. public void release() {
  141. synchronized (this) {
  142. mReferenceCount -= 1;
  143. if (mReferenceCount == 0) {
  144. nativeReleaseSuspendBlocker(mName);
  145. }
  146. }
  147. }
  148. }
  149. 休眠锁的获取和释放,最终通过JNI方式读写/sys/power/wake_lock、/sys/power/wake_unlock:
  150. // 1、JNI接口
  151. com_android_server_power_PowerManagerService.cpp (frameworks\base\services\jni)
  152. static void nativeAcquireSuspendBlocker(JNIEnv *env, jclass clazz, jstring nameStr) {
  153. ScopedUtfChars name(env, nameStr);
  154. acquire_wake_lock(PARTIAL_WAKE_LOCK, name.c_str());
  155. }
  156. // 2、定义要操作的文件
  157. power.c (hardware\libhardware_legacy\power)
  158. const char * const NEW_PATHS[] = {
  159. "/sys/power/wake_lock",
  160. "/sys/power/wake_unlock",
  161. };
  162. // 3、初始化设备节点
  163. static inline void initialize_fds(void)
  164. {
  165. if (g_initialized == 0) {
  166. if(open_file_descriptors(NEW_PATHS) < 0)
  167. open_file_descriptors(OLD_PATHS);
  168. g_initialized = 1;
  169. }
  170. }
  171. static int open_file_descriptors(const char * const paths[])
  172. {
  173. int i;
  174. for (i=0; i<OUR_FD_COUNT; i++) {
  175. int fd = open(paths[i], O_RDWR);
  176. if (fd < 0) {
  177. fprintf(stderr, "fatal error opening \"%s\"\n", paths[i]);
  178. g_error = errno;
  179. return -1;
  180. }
  181. g_fds[i] = fd;
  182. }
  183. g_error = 0;
  184. return 0;
  185. }
  186. // 4、id即为锁的名字,之后就是读写设备
  187. int acquire_wake_lock(int lock, const char* id)
  188. {
  189. initialize_fds();
  190. if (g_error) return g_error;
  191. int fd;
  192. if (lock == PARTIAL_WAKE_LOCK) {
  193. fd = g_fds[ACQUIRE_PARTIAL_WAKE_LOCK];
  194. }
  195. else {
  196. return EINVAL;
  197. }
  198. return write(fd, id, strlen(id));
  199. }

MSG_USER_ACTIVITY_TIMEOUT事件处理:

  1. private final class PowerManagerHandler extends Handler {
  2. @Override
  3. public void handleMessage(Message msg) {
  4. switch (msg.what) {
  5. case MSG_USER_ACTIVITY_TIMEOUT:
  6. handleUserActivityTimeout();
  7. break;
  8. }
  9. }
  10. /**
  11. * Called when a user activity timeout has occurred.
  12. * Simply indicates that something about user activity has changed so that the new
  13. * state can be recomputed when the power state is updated.
  14. */
  15. private void handleUserActivityTimeout() { // runs on handler thread
  16. mDirty |= DIRTY_USER_ACTIVITY;
  17. updatePowerStateLocked();
  18. }

三、PowerManagerService中休眠锁的获取/释放

这部分代码清晰,直接看下:

  1. private void updatePowerStateLocked() {
  2. if (!mSystemReady || mDirty == 0) {
  3. return;
  4. }
  5. // Phase 0: Basic state updates.
  6. // Phase 1: Update wakefulness.
  7. // Phase 2: Update dreams and display power state.
  8. // Phase 3: Send notifications, if needed.
  9. // Phase 4: Update suspend blocker.
  10. // Because we might release the last suspend blocker here, we need to make sure
  11. // we finished everything else first!
  12. updateSuspendBlockerLocked();
  13. }
  14. /**
  15. * Updates the suspend blocker that keeps the CPU alive.
  16. */
  17. private void updateSuspendBlockerLocked() {
  18. final boolean needWakeLockSuspendBlocker = ((mWakeLockSummary & WAKE_LOCK_CPU) != 0);
  19. final boolean needDisplaySuspendBlocker = needDisplaySuspendBlocker();
  20. // First acquire suspend blockers if needed.
  21. if (needWakeLockSuspendBlocker && !mHoldingWakeLockSuspendBlocker) {
  22. mWakeLockSuspendBlocker.acquire();
  23. mHoldingWakeLockSuspendBlocker = true;
  24. }
  25. if (needDisplaySuspendBlocker && !mHoldingDisplaySuspendBlocker) {
  26. mDisplaySuspendBlocker.acquire();
  27. mHoldingDisplaySuspendBlocker = true;
  28. }
  29. // Then release suspend blockers if needed.
  30. if (!needWakeLockSuspendBlocker && mHoldingWakeLockSuspendBlocker) {
  31. mWakeLockSuspendBlocker.release();
  32. mHoldingWakeLockSuspendBlocker = false;
  33. }
  34. if (!needDisplaySuspendBlocker && mHoldingDisplaySuspendBlocker) {
  35. mDisplaySuspendBlocker.release();
  36. mHoldingDisplaySuspendBlocker = false;
  37. }
  38. }
  39. private final class SuspendBlockerImpl implements SuspendBlocker {
  40. private final String mName;
  41. private int mReferenceCount;
  42. public SuspendBlockerImpl(String name) {
  43. mName = name;
  44. }
  45. @Override
  46. public void acquire() {
  47. synchronized (this) {
  48. mReferenceCount += 1;
  49. if (mReferenceCount == 1) {
  50. nativeAcquireSuspendBlocker(mName);
  51. }
  52. }
  53. }
  54. @Override
  55. public void release() {
  56. synchronized (this) {
  57. mReferenceCount -= 1;
  58. if (mReferenceCount == 0) {
  59. nativeReleaseSuspendBlocker(mName);
  60. }
  61. }
  62. }
  63. }

休眠锁的获取和释放,最终通过JNI方式读写/sys/power/wake_lock、/sys/power/wake_unlock:

  1. // 1、JNI接口
  2. com_android_server_power_PowerManagerService.cpp (frameworks\base\services\jni)
  3. static void nativeAcquireSuspendBlocker(JNIEnv *env, jclass clazz, jstring nameStr) {
  4. ScopedUtfChars name(env, nameStr);
  5. acquire_wake_lock(PARTIAL_WAKE_LOCK, name.c_str());
  6. }
  7. // 2、定义要操作的文件
  8. power.c (hardware\libhardware_legacy\power)
  9. const char * const NEW_PATHS[] = {
  10. "/sys/power/wake_lock",
  11. "/sys/power/wake_unlock",
  12. };
  13. // 3、初始化设备节点
  14. static inline void initialize_fds(void)
  15. {
  16. if (g_initialized == 0) {
  17. if(open_file_descriptors(NEW_PATHS) < 0)
  18. open_file_descriptors(OLD_PATHS);
  19. g_initialized = 1;
  20. }
  21. }
  22. static int open_file_descriptors(const char * const paths[])
  23. {
  24. int i;
  25. for (i=0; i<OUR_FD_COUNT; i++) {
  26. int fd = open(paths[i], O_RDWR);
  27. if (fd < 0) {
  28. fprintf(stderr, "fatal error opening \"%s\"\n", paths[i]);
  29. g_error = errno;
  30. return -1;
  31. }
  32. g_fds[i] = fd;
  33. }
  34. g_error = 0;
  35. return 0;
  36. }
  37. // 4、id即为锁的名字,之后就是读写设备
  38. int acquire_wake_lock(int lock, const char* id)
  39. {
  40. initialize_fds();
  41. if (g_error) return g_error;
  42. int fd;
  43. if (lock == PARTIAL_WAKE_LOCK) {
  44. fd = g_fds[ACQUIRE_PARTIAL_WAKE_LOCK];
  45. }
  46. else {
  47. return EINVAL;
  48. }
  49. return write(fd, id, strlen(id));
  50. }

 

(0)

相关推荐