赞
踩
Android使用唤醒锁的方法
- PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
- wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, this.getClass().getName());//持有唤醒锁
- wakeLock.setReferenceCounted(false);
- wakeLock.acquire();//获取锁
- wakeLock.release();//释放锁
- 或者自动释放锁
- wakeLock.acquire(30*1000);//30s后自动释放
http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/os/PowerManager.java
- * @param levelAndFlags Combination of wake lock level and flag values defining
- * the requested behavior of the WakeLock.
- * @param tag Your class name (or other tag) for debugging purposes.
- *
- * @see WakeLock#acquire()
- * @see WakeLock#release()
- * @see #PARTIAL_WAKE_LOCK
- * @see #FULL_WAKE_LOCK
- * @see #SCREEN_DIM_WAKE_LOCK
- * @see #SCREEN_BRIGHT_WAKE_LOCK
- * @see #PROXIMITY_SCREEN_OFF_WAKE_LOCK
- * @see #ACQUIRE_CAUSES_WAKEUP
- * @see #ON_AFTER_RELEASE
- */
- public WakeLock newWakeLock(int levelAndFlags, String tag) {
- validateWakeLockParameters(levelAndFlags, tag);
- return new WakeLock(levelAndFlags, tag, mContext.getOpPackageName());
- }
- public final class WakeLock {
- private int mFlags;
- private String mTag;
- private final String mPackageName;
- private final IBinder mToken;
- private int mInternalCount;
- private int mExternalCount;
- private boolean mRefCounted = true;
- private boolean mHeld;
- private WorkSource mWorkSource;
- private String mHistoryTag;
- private final String mTraceName;
-
- private final Runnable mReleaser = new Runnable() {
- public void run() {
- release(RELEASE_FLAG_TIMEOUT);
- }
- };
-
- WakeLock(int flags, String tag, String packageName) {
- mFlags = flags;
- mTag = tag;
- mPackageName = packageName;
- mToken = new Binder();
- mTraceName = "WakeLock (" + mTag + ")";
- }
-
- @Override
- protected void finalize() throws Throwable {
- synchronized (mToken) {
- if (mHeld) {
- Log.wtf(TAG, "WakeLock finalized while still held: " + mTag);
- Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, mTraceName, 0);
- try {
- mService.releaseWakeLock(mToken, 0);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
- }
- }
-
- /**
- * Sets whether this WakeLock is reference counted.
- * <p>
- * Wake locks are reference counted by default. If a wake lock is
- * reference counted, then each call to {@link #acquire()} must be
- * balanced by an equal number of calls to {@link #release()}. If a wake
- * lock is not reference counted, then one call to {@link #release()} is
- * sufficient to undo the effect of all previous calls to {@link #acquire()}.
- * </p>
- *
- * @param value True to make the wake lock reference counted, false to
- * make the wake lock non-reference counted.
- */
- public void setReferenceCounted(boolean value) {
- synchronized (mToken) {
- mRefCounted = value;
- }
- }
-
- /**
- * Acquires the wake lock.
- * <p>
- * Ensures that the device is on at the level requested when
- * the wake lock was created.
- * </p>
- */
- public void acquire() {
- synchronized (mToken) {
- acquireLocked();
- }
- }
-
- /**
- * Acquires the wake lock with a timeout.
- * <p>
- * Ensures that the device is on at the level requested when
- * the wake lock was created. The lock will be released after the given timeout
- * expires.
- * </p>
- *
- * @param timeout The timeout after which to release the wake lock, in milliseconds.
- */
- public void acquire(long timeout) {
- synchronized (mToken) {
- acquireLocked();
- mHandler.postDelayed(mReleaser, timeout);
- }
- }
-
- private void acquireLocked() {
- mInternalCount++;
- mExternalCount++;
- if (!mRefCounted || mInternalCount == 1) {
- // Do this even if the wake lock is already thought to be held (mHeld == true)
- // because non-reference counted wake locks are not always properly released.
- // For example, the keyguard's wake lock might be forcibly released by the
- // power manager without the keyguard knowing. A subsequent call to acquire
- // should immediately acquire the wake lock once again despite never having
- // been explicitly released by the keyguard.
- mHandler.removeCallbacks(mReleaser);
- Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, mTraceName, 0);
- try {
- mService.acquireWakeLock(mToken, mFlags, mTag, mPackageName, mWorkSource,
- mHistoryTag);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- mHeld = true;
- }
- }
-
- /**
- * Releases the wake lock.
- * <p>
- * This method releases your claim to the CPU or screen being on.
- * The screen may turn off shortly after you release the wake lock, or it may
- * not if there are other wake locks still held.
- * </p>
- */
- public void release() {
- release(0);
- }
- @Override // Binder call
- public void acquireWakeLock(IBinder lock, int flags, String tag, String packageName,WorkSource ws, String historyTag) {
- acquireWakeLockInternal(lock, flags, tag, packageName, ws, historyTag, uid, pid);
- }
- private void acquireWakeLockInternal(IBinder lock, int flags, String tag, String packageName,WorkSource ws, String historyTag, int uid, int pid) {
- updatePowerStateLocked();
- }
- private void updatePowerStateLocked() {
- updateSuspendBlockerLocked();
- }
- private void updateSuspendBlockerLocked() {
- final boolean needWakeLockSuspendBlocker = ((mWakeLockSummary & WAKE_LOCK_CPU) != 0);
- final boolean needDisplaySuspendBlocker = needDisplaySuspendBlockerLocked();
-
- // 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 final String mTraceName;
- private int mReferenceCount;
-
- public SuspendBlockerImpl(String name) {
- mName = name;
- mTraceName = "SuspendBlocker (" + name + ")";
- }
-
- @Override
- public void acquire() {
- synchronized (this) {
- mReferenceCount += 1;
- if (mReferenceCount == 1) {
- if (DEBUG_SPEW) {
- Slog.d(TAG, "Acquiring suspend blocker \"" + mName + "\".");
- }
- Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, mTraceName, 0);
- nativeAcquireSuspendBlocker(mName);
- }
- }
- }
-
- @Override
- public void release() {
- synchronized (this) {
- mReferenceCount -= 1;
- if (mReferenceCount == 0) {
- if (DEBUG_SPEW) {
- Slog.d(TAG, "Releasing suspend blocker \"" + mName + "\".");
- }
- nativeReleaseSuspendBlocker(mName);
- Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, mTraceName, 0);
- } else if (mReferenceCount < 0) {
- Slog.wtf(TAG, "Suspend blocker \"" + mName
- + "\" was released without being acquired!", new Throwable());
- mReferenceCount = 0;
- }
- }
- }
- static void nativeAcquireSuspendBlocker(JNIEnv *env, jclass /* clazz */, jstring nameStr) {
- ScopedUtfChars name(env, nameStr);
- acquire_wake_lock(PARTIAL_WAKE_LOCK, name.c_str());
- }
-
- static void nativeReleaseSuspendBlocker(JNIEnv *env, jclass /* clazz */, jstring nameStr) {
- ScopedUtfChars name(env, nameStr);
- release_wake_lock(name.c_str());
- }
http://androidxref.com/9.0.0_r3/xref/hardware/libhardware_legacy/power.c
最终实现写内核的wake_lock和wake_unlock节点
- const char * const NEW_PATHS[] = {
- "/sys/power/wake_lock",
- "/sys/power/wake_unlock",
- };
-
- //XXX static pthread_once_t g_initialized = THREAD_ONCE_INIT;
- static int g_initialized = 0;
- static int g_fds[OUR_FD_COUNT];
- static int g_error = -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 | O_CLOEXEC);
- if (fd < 0) {
- g_error = -errno;
- fprintf(stderr, "fatal error opening \"%s\": %s\n", paths[i],
- strerror(errno));
- return -1;
- }
- g_fds[i] = fd;
- }
-
- g_error = 0;
- return 0;
- }
-
- static inline void
- initialize_fds(void)
- {
- // XXX: should be this:
- //pthread_once(&g_initialized, open_file_descriptors);
- // XXX: not this:
- if (g_initialized == 0) {
- if(open_file_descriptors(NEW_PATHS) < 0)
- open_file_descriptors(OLD_PATHS);
- g_initialized = 1;
- }
- }
-
- int
- acquire_wake_lock(int lock, const char* id)
- {
- initialize_fds();
-
- // ALOGI("acquire_wake_lock lock=%d id='%s'\n", lock, id);
-
- if (g_error) return g_error;
-
- int fd;
- ssize_t ret;
-
- if (lock != PARTIAL_WAKE_LOCK) {
- return -EINVAL;
- }
-
- fd = g_fds[ACQUIRE_PARTIAL_WAKE_LOCK];
-
- ret = write(fd, id, strlen(id));
- if (ret < 0) {
- return -errno;
- }
-
- return ret;
- }
-
- int
- release_wake_lock(const char* id)
- {
- initialize_fds();
-
- // ALOGI("release_wake_lock id='%s'\n", id);
-
- if (g_error) return g_error;
-
- ssize_t len = write(g_fds[RELEASE_WAKE_LOCK], id, strlen(id));
- if (len < 0) {
- return -errno;
- }
- return len;
- }
main.c « power « kernel - kernel/git/torvalds/linux.git - Linux kernel source tree
- static ssize_t wake_lock_show(struct kobject *kobj,
- struct kobj_attribute *attr,
- char *buf)
- {
- return pm_show_wakelocks(buf, true);
- }
-
- static ssize_t wake_lock_store(struct kobject *kobj,
- struct kobj_attribute *attr,
- const char *buf, size_t n)
- {
- int error = pm_wake_lock(buf);
- return error ? error : n;
- }
-
- power_attr(wake_lock);
wakelock.c « power « kernel - kernel/git/torvalds/linux.git - Linux kernel source tree
- int pm_wake_lock(const char *buf)
- {
- const char *str = buf;
- struct wakelock *wl;
- u64 timeout_ns = 0;
- size_t len;
- int ret = 0;
-
- if (!capable(CAP_BLOCK_SUSPEND))
- return -EPERM;
-
- while (*str && !isspace(*str))
- str++;
-
- len = str - buf;
- if (!len)
- return -EINVAL;
-
- if (*str && *str != '\n') {
- /* Find out if there's a valid timeout string appended. */
- ret = kstrtou64(skip_spaces(str), 10, &timeout_ns);
- if (ret)
- return -EINVAL;
- }
-
- mutex_lock(&wakelocks_lock);
-
- wl = wakelock_lookup_add(buf, len, true);
- if (IS_ERR(wl)) {
- ret = PTR_ERR(wl);
- goto out;
- }
- if (timeout_ns) {
- u64 timeout_ms = timeout_ns + NSEC_PER_MSEC - 1;
-
- do_div(timeout_ms, NSEC_PER_MSEC);
- __pm_wakeup_event(&wl->ws, timeout_ms);
- } else {
- __pm_stay_awake(&wl->ws);
- }
-
- wakelocks_lru_most_recent(wl);
-
- out:
- mutex_unlock(&wakelocks_lock);
- return ret;
- }
wakeup.c « power « base « drivers - kernel/git/torvalds/linux.git - Linux kernel source tree
- void __pm_stay_awake(struct wakeup_source *ws)
- {
- unsigned long flags;
-
- if (!ws)
- return;
-
- spin_lock_irqsave(&ws->lock, flags);
-
- wakeup_source_report_event(ws, false);
- del_timer(&ws->timer);
- ws->timer_expires = 0;
-
- spin_unlock_irqrestore(&ws->lock, flags);
- }
- static void wakeup_source_report_event(struct wakeup_source *ws, bool hard)
- {
- ws->event_count++;
- /* This is racy, but the counter is approximate anyway. */
- if (events_check_enabled)
- ws->wakeup_count++;
-
- if (!ws->active)
- wakeup_source_activate(ws);
-
- if (hard)
- pm_system_wakeup();
- }
- static void wakeup_source_activate(struct wakeup_source *ws)
- {
- unsigned int cec;
-
- if (WARN_ONCE(wakeup_source_not_registered(ws),
- "unregistered wakeup source\n"))
- return;
-
- ws->active = true;
- ws->active_count++;
- ws->last_time = ktime_get();
- if (ws->autosleep_enabled)
- ws->start_prevent_time = ws->last_time;
-
- /* Increment the counter of events in progress. */
- cec = atomic_inc_return(&combined_event_count);
-
- trace_wakeup_source_activate(ws->name, cec);
- }
static atomic_t combined_event_count = ATOMIC_INIT(0);
cec = atomic_inc_return(&combined_event_count);
combined_event_count计数+1,Android的整个唤醒锁都靠这个整数来实现。
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。