当前位置:   article > 正文

Android唤醒锁实现_wakelock.setreferencecounted

wakelock.setreferencecounted

Android使用唤醒锁的方法

  1. PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
  2. wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, this.getClass().getName());//持有唤醒锁
  3. wakeLock.setReferenceCounted(false);
  4. wakeLock.acquire();//获取锁
  5. wakeLock.release();//释放锁
  6. 或者自动释放锁
  7. wakeLock.acquire(30*1000);//30s后自动释放

http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/os/PowerManager.java

  1. * @param levelAndFlags Combination of wake lock level and flag values defining
  2. * the requested behavior of the WakeLock.
  3. * @param tag Your class name (or other tag) for debugging purposes.
  4. *
  5. * @see WakeLock#acquire()
  6. * @see WakeLock#release()
  7. * @see #PARTIAL_WAKE_LOCK
  8. * @see #FULL_WAKE_LOCK
  9. * @see #SCREEN_DIM_WAKE_LOCK
  10. * @see #SCREEN_BRIGHT_WAKE_LOCK
  11. * @see #PROXIMITY_SCREEN_OFF_WAKE_LOCK
  12. * @see #ACQUIRE_CAUSES_WAKEUP
  13. * @see #ON_AFTER_RELEASE
  14. */
  15. public WakeLock newWakeLock(int levelAndFlags, String tag) {
  16. validateWakeLockParameters(levelAndFlags, tag);
  17. return new WakeLock(levelAndFlags, tag, mContext.getOpPackageName());
  18. }
  1. public final class WakeLock {
  2. private int mFlags;
  3. private String mTag;
  4. private final String mPackageName;
  5. private final IBinder mToken;
  6. private int mInternalCount;
  7. private int mExternalCount;
  8. private boolean mRefCounted = true;
  9. private boolean mHeld;
  10. private WorkSource mWorkSource;
  11. private String mHistoryTag;
  12. private final String mTraceName;
  13. private final Runnable mReleaser = new Runnable() {
  14. public void run() {
  15. release(RELEASE_FLAG_TIMEOUT);
  16. }
  17. };
  18. WakeLock(int flags, String tag, String packageName) {
  19. mFlags = flags;
  20. mTag = tag;
  21. mPackageName = packageName;
  22. mToken = new Binder();
  23. mTraceName = "WakeLock (" + mTag + ")";
  24. }
  25. @Override
  26. protected void finalize() throws Throwable {
  27. synchronized (mToken) {
  28. if (mHeld) {
  29. Log.wtf(TAG, "WakeLock finalized while still held: " + mTag);
  30. Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, mTraceName, 0);
  31. try {
  32. mService.releaseWakeLock(mToken, 0);
  33. } catch (RemoteException e) {
  34. throw e.rethrowFromSystemServer();
  35. }
  36. }
  37. }
  38. }
  39. /**
  40. * Sets whether this WakeLock is reference counted.
  41. * <p>
  42. * Wake locks are reference counted by default. If a wake lock is
  43. * reference counted, then each call to {@link #acquire()} must be
  44. * balanced by an equal number of calls to {@link #release()}. If a wake
  45. * lock is not reference counted, then one call to {@link #release()} is
  46. * sufficient to undo the effect of all previous calls to {@link #acquire()}.
  47. * </p>
  48. *
  49. * @param value True to make the wake lock reference counted, false to
  50. * make the wake lock non-reference counted.
  51. */
  52. public void setReferenceCounted(boolean value) {
  53. synchronized (mToken) {
  54. mRefCounted = value;
  55. }
  56. }
  57. /**
  58. * Acquires the wake lock.
  59. * <p>
  60. * Ensures that the device is on at the level requested when
  61. * the wake lock was created.
  62. * </p>
  63. */
  64. public void acquire() {
  65. synchronized (mToken) {
  66. acquireLocked();
  67. }
  68. }
  69. /**
  70. * Acquires the wake lock with a timeout.
  71. * <p>
  72. * Ensures that the device is on at the level requested when
  73. * the wake lock was created. The lock will be released after the given timeout
  74. * expires.
  75. * </p>
  76. *
  77. * @param timeout The timeout after which to release the wake lock, in milliseconds.
  78. */
  79. public void acquire(long timeout) {
  80. synchronized (mToken) {
  81. acquireLocked();
  82. mHandler.postDelayed(mReleaser, timeout);
  83. }
  84. }
  85. private void acquireLocked() {
  86. mInternalCount++;
  87. mExternalCount++;
  88. if (!mRefCounted || mInternalCount == 1) {
  89. // Do this even if the wake lock is already thought to be held (mHeld == true)
  90. // because non-reference counted wake locks are not always properly released.
  91. // For example, the keyguard's wake lock might be forcibly released by the
  92. // power manager without the keyguard knowing. A subsequent call to acquire
  93. // should immediately acquire the wake lock once again despite never having
  94. // been explicitly released by the keyguard.
  95. mHandler.removeCallbacks(mReleaser);
  96. Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, mTraceName, 0);
  97. try {
  98. mService.acquireWakeLock(mToken, mFlags, mTag, mPackageName, mWorkSource,
  99. mHistoryTag);
  100. } catch (RemoteException e) {
  101. throw e.rethrowFromSystemServer();
  102. }
  103. mHeld = true;
  104. }
  105. }
  106. /**
  107. * Releases the wake lock.
  108. * <p>
  109. * This method releases your claim to the CPU or screen being on.
  110. * The screen may turn off shortly after you release the wake lock, or it may
  111. * not if there are other wake locks still held.
  112. * </p>
  113. */
  114. public void release() {
  115. release(0);
  116. }

http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java

  1. @Override // Binder call
  2. public void acquireWakeLock(IBinder lock, int flags, String tag, String packageName,WorkSource ws, String historyTag) {
  3. acquireWakeLockInternal(lock, flags, tag, packageName, ws, historyTag, uid, pid);
  4. }
  1. private void acquireWakeLockInternal(IBinder lock, int flags, String tag, String packageName,WorkSource ws, String historyTag, int uid, int pid) {
  2. updatePowerStateLocked();
  3. }
  1. private void updatePowerStateLocked() {
  2. updateSuspendBlockerLocked();
  3. }

  1. private void updateSuspendBlockerLocked() {
  2. final boolean needWakeLockSuspendBlocker = ((mWakeLockSummary & WAKE_LOCK_CPU) != 0);
  3. final boolean needDisplaySuspendBlocker = needDisplaySuspendBlockerLocked();
  4. // First acquire suspend blockers if needed.
  5. if (needWakeLockSuspendBlocker && !mHoldingWakeLockSuspendBlocker) {
  6. mWakeLockSuspendBlocker.acquire();
  7. mHoldingWakeLockSuspendBlocker = true;
  8. }
  9. if (needDisplaySuspendBlocker && !mHoldingDisplaySuspendBlocker) {
  10. mDisplaySuspendBlocker.acquire();
  11. mHoldingDisplaySuspendBlocker = true;
  12. }
  13. // Then release suspend blockers if needed.
  14. if (!needWakeLockSuspendBlocker && mHoldingWakeLockSuspendBlocker) {
  15. mWakeLockSuspendBlocker.release();
  16. mHoldingWakeLockSuspendBlocker = false;
  17. }
  18. if (!needDisplaySuspendBlocker && mHoldingDisplaySuspendBlocker) {
  19. mDisplaySuspendBlocker.release();
  20. mHoldingDisplaySuspendBlocker = false;
  21. }
  22. }

  1. private final class SuspendBlockerImpl implements SuspendBlocker {
  2. private final String mName;
  3. private final String mTraceName;
  4. private int mReferenceCount;
  5. public SuspendBlockerImpl(String name) {
  6. mName = name;
  7. mTraceName = "SuspendBlocker (" + name + ")";
  8. }
  9. @Override
  10. public void acquire() {
  11. synchronized (this) {
  12. mReferenceCount += 1;
  13. if (mReferenceCount == 1) {
  14. if (DEBUG_SPEW) {
  15. Slog.d(TAG, "Acquiring suspend blocker \"" + mName + "\".");
  16. }
  17. Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, mTraceName, 0);
  18. nativeAcquireSuspendBlocker(mName);
  19. }
  20. }
  21. }
  22. @Override
  23. public void release() {
  24. synchronized (this) {
  25. mReferenceCount -= 1;
  26. if (mReferenceCount == 0) {
  27. if (DEBUG_SPEW) {
  28. Slog.d(TAG, "Releasing suspend blocker \"" + mName + "\".");
  29. }
  30. nativeReleaseSuspendBlocker(mName);
  31. Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, mTraceName, 0);
  32. } else if (mReferenceCount < 0) {
  33. Slog.wtf(TAG, "Suspend blocker \"" + mName
  34. + "\" was released without being acquired!", new Throwable());
  35. mReferenceCount = 0;
  36. }
  37. }
  38. }

http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/jni/com_android_server_power_PowerManagerService.cpp

  1. static void nativeAcquireSuspendBlocker(JNIEnv *env, jclass /* clazz */, jstring nameStr) {
  2. ScopedUtfChars name(env, nameStr);
  3. acquire_wake_lock(PARTIAL_WAKE_LOCK, name.c_str());
  4. }
  5. static void nativeReleaseSuspendBlocker(JNIEnv *env, jclass /* clazz */, jstring nameStr) {
  6. ScopedUtfChars name(env, nameStr);
  7. release_wake_lock(name.c_str());
  8. }

http://androidxref.com/9.0.0_r3/xref/hardware/libhardware_legacy/power.c

最终实现写内核的wake_lock和wake_unlock节点

  1. const char * const NEW_PATHS[] = {
  2. "/sys/power/wake_lock",
  3. "/sys/power/wake_unlock",
  4. };
  5. //XXX static pthread_once_t g_initialized = THREAD_ONCE_INIT;
  6. static int g_initialized = 0;
  7. static int g_fds[OUR_FD_COUNT];
  8. static int g_error = -1;
  9. static int
  10. open_file_descriptors(const char * const paths[])
  11. {
  12. int i;
  13. for (i=0; i<OUR_FD_COUNT; i++) {
  14. int fd = open(paths[i], O_RDWR | O_CLOEXEC);
  15. if (fd < 0) {
  16. g_error = -errno;
  17. fprintf(stderr, "fatal error opening \"%s\": %s\n", paths[i],
  18. strerror(errno));
  19. return -1;
  20. }
  21. g_fds[i] = fd;
  22. }
  23. g_error = 0;
  24. return 0;
  25. }
  26. static inline void
  27. initialize_fds(void)
  28. {
  29. // XXX: should be this:
  30. //pthread_once(&g_initialized, open_file_descriptors);
  31. // XXX: not this:
  32. if (g_initialized == 0) {
  33. if(open_file_descriptors(NEW_PATHS) < 0)
  34. open_file_descriptors(OLD_PATHS);
  35. g_initialized = 1;
  36. }
  37. }
  38. int
  39. acquire_wake_lock(int lock, const char* id)
  40. {
  41. initialize_fds();
  42. // ALOGI("acquire_wake_lock lock=%d id='%s'\n", lock, id);
  43. if (g_error) return g_error;
  44. int fd;
  45. ssize_t ret;
  46. if (lock != PARTIAL_WAKE_LOCK) {
  47. return -EINVAL;
  48. }
  49. fd = g_fds[ACQUIRE_PARTIAL_WAKE_LOCK];
  50. ret = write(fd, id, strlen(id));
  51. if (ret < 0) {
  52. return -errno;
  53. }
  54. return ret;
  55. }
  56. int
  57. release_wake_lock(const char* id)
  58. {
  59. initialize_fds();
  60. // ALOGI("release_wake_lock id='%s'\n", id);
  61. if (g_error) return g_error;
  62. ssize_t len = write(g_fds[RELEASE_WAKE_LOCK], id, strlen(id));
  63. if (len < 0) {
  64. return -errno;
  65. }
  66. return len;
  67. }

main.c « power « kernel - kernel/git/torvalds/linux.git - Linux kernel source tree

  1. static ssize_t wake_lock_show(struct kobject *kobj,
  2. struct kobj_attribute *attr,
  3. char *buf)
  4. {
  5. return pm_show_wakelocks(buf, true);
  6. }
  7. static ssize_t wake_lock_store(struct kobject *kobj,
  8. struct kobj_attribute *attr,
  9. const char *buf, size_t n)
  10. {
  11. int error = pm_wake_lock(buf);
  12. return error ? error : n;
  13. }
  14. power_attr(wake_lock);

wakelock.c « power « kernel - kernel/git/torvalds/linux.git - Linux kernel source tree

  1. int pm_wake_lock(const char *buf)
  2. {
  3. const char *str = buf;
  4. struct wakelock *wl;
  5. u64 timeout_ns = 0;
  6. size_t len;
  7. int ret = 0;
  8. if (!capable(CAP_BLOCK_SUSPEND))
  9. return -EPERM;
  10. while (*str && !isspace(*str))
  11. str++;
  12. len = str - buf;
  13. if (!len)
  14. return -EINVAL;
  15. if (*str && *str != '\n') {
  16. /* Find out if there's a valid timeout string appended. */
  17. ret = kstrtou64(skip_spaces(str), 10, &timeout_ns);
  18. if (ret)
  19. return -EINVAL;
  20. }
  21. mutex_lock(&wakelocks_lock);
  22. wl = wakelock_lookup_add(buf, len, true);
  23. if (IS_ERR(wl)) {
  24. ret = PTR_ERR(wl);
  25. goto out;
  26. }
  27. if (timeout_ns) {
  28. u64 timeout_ms = timeout_ns + NSEC_PER_MSEC - 1;
  29. do_div(timeout_ms, NSEC_PER_MSEC);
  30. __pm_wakeup_event(&wl->ws, timeout_ms);
  31. } else {
  32. __pm_stay_awake(&wl->ws);
  33. }
  34. wakelocks_lru_most_recent(wl);
  35. out:
  36. mutex_unlock(&wakelocks_lock);
  37. return ret;
  38. }

wakeup.c « power « base « drivers - kernel/git/torvalds/linux.git - Linux kernel source tree

  1. void __pm_stay_awake(struct wakeup_source *ws)
  2. {
  3. unsigned long flags;
  4. if (!ws)
  5. return;
  6. spin_lock_irqsave(&ws->lock, flags);
  7. wakeup_source_report_event(ws, false);
  8. del_timer(&ws->timer);
  9. ws->timer_expires = 0;
  10. spin_unlock_irqrestore(&ws->lock, flags);
  11. }
  1. static void wakeup_source_report_event(struct wakeup_source *ws, bool hard)
  2. {
  3. ws->event_count++;
  4. /* This is racy, but the counter is approximate anyway. */
  5. if (events_check_enabled)
  6. ws->wakeup_count++;
  7. if (!ws->active)
  8. wakeup_source_activate(ws);
  9. if (hard)
  10. pm_system_wakeup();
  11. }
  1. static void wakeup_source_activate(struct wakeup_source *ws)
  2. {
  3. unsigned int cec;
  4. if (WARN_ONCE(wakeup_source_not_registered(ws),
  5. "unregistered wakeup source\n"))
  6. return;
  7. ws->active = true;
  8. ws->active_count++;
  9. ws->last_time = ktime_get();
  10. if (ws->autosleep_enabled)
  11. ws->start_prevent_time = ws->last_time;
  12. /* Increment the counter of events in progress. */
  13. cec = atomic_inc_return(&combined_event_count);
  14. trace_wakeup_source_activate(ws->name, cec);
  15. }

static atomic_t combined_event_count = ATOMIC_INIT(0);

cec = atomic_inc_return(&combined_event_count);

combined_event_count计数+1,Android的整个唤醒锁都靠这个整数来实现。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/301704
推荐阅读
相关标签
  

闽ICP备14008679号