Android6.0 wakelock深入分析
来源:互联网 发布:反潜鱼雷 知乎 编辑:程序博客网 时间:2024/05/01 13:01
这篇博客我们分析下Power的持锁,从PowerManager到PowerManagerService再到hal分析。
一、PowerManager的持锁接口
我们先来看下PowerManager对应用提供的接口:
- public WakeLock newWakeLock(int levelAndFlags, String tag) {
- validateWakeLockParameters(levelAndFlags, tag);//验证wakelock的flag是否有效
- return new WakeLock(levelAndFlags, tag, mContext.getOpPackageName());
- }
validateWakeLockParameters函数如下:主要对flag没有下面这些flag做过滤
- public static void validateWakeLockParameters(int levelAndFlags, String tag) {
- switch (levelAndFlags & WAKE_LOCK_LEVEL_MASK) {
- case PARTIAL_WAKE_LOCK://cpu锁
- case SCREEN_DIM_WAKE_LOCK://屏幕微亮,键盘暗
- case SCREEN_BRIGHT_WAKE_LOCK://屏幕亮,键盘暗
- case FULL_WAKE_LOCK://全亮
- case PROXIMITY_SCREEN_OFF_WAKE_LOCK:
- case DOZE_WAKE_LOCK:
- case DRAW_WAKE_LOCK:
- break;
- default:
- throw new IllegalArgumentException("Must specify a valid wake lock level.");
- }
- if (tag == null) {
- throw new IllegalArgumentException("The tag must not be null.");
- }
- }
我们再看WakeLock类,先看下面两个持锁,第二个timeout的持锁,先持锁,然后发送一个延迟消息再解锁。
- public void acquire() {
- synchronized (mToken) {
- acquireLocked();
- }
- }
- public void acquire(long timeout) {
- synchronized (mToken) {
- acquireLocked();
- mHandler.postDelayed(mReleaser, timeout);
- }
- }
- private final Runnable mReleaser = new Runnable() {
- public void run() {
- release();
- }
- };
再来看acquireLocked,流程最后是调用了service的acquireWakeLock,但是有一个细节我们注意下,这里有一个mCount的计数。也就是没调用一次这个函数,都会对wakelock的mCount加1。
- private void acquireLocked() {
- if (!mRefCounted || mCount++ == 0) {
- // 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) {
- }
- mHeld = true;
- }
- }
我们再来看看release函数,上面说的mCount计数,这里就会对这个计数进行判断,只有当计数为0,才会去调用service的releaseWakeLock函数。
- public void release(int flags) {
- synchronized (mToken) {
- if (!mRefCounted || --mCount == 0) {
- mHandler.removeCallbacks(mReleaser);
- if (mHeld) {
- Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, mTraceName, 0);
- try {
- mService.releaseWakeLock(mToken, flags);
- } catch (RemoteException e) {
- }
- mHeld = false;
- }
- }
- if (mCount < 0) {
- throw new RuntimeException("WakeLock under-locked " + mTag);
- }
- }
- }
所以我们总结下,使用PowerManager的wakelock持锁和释放锁。必须成对出现,当持了2次锁,也必须释放两次锁。才会调用service的释放锁,去真正释放。
二、PowerManagerService相关接口
Service的acquireWakeLock函数我们就不看了,主要是对wakelock的flag做验证,然后调用了acquireWakeLockInternal函数:
- private void acquireWakeLockInternal(IBinder lock, int flags, String tag, String packageName,
- WorkSource ws, String historyTag, int uid, int pid) {
- synchronized (mLock) {
- WakeLock wakeLock;
- int index = findWakeLockIndexLocked(lock);//查找wakelock,IBinder对象为wakelock唯一性
- boolean notifyAcquire;
- if (index >= 0) {
- wakeLock = mWakeLocks.get(index);
- if (!wakeLock.hasSameProperties(flags, tag, ws, uid, pid)) {
- // Update existing wake lock. This shouldn't happen but is harmless.
- notifyWakeLockChangingLocked(wakeLock, flags, tag, packageName,
- uid, pid, ws, historyTag);
- wakeLock.updateProperties(flags, tag, packageName, ws, historyTag, uid, pid);//更新参数
- }
- notifyAcquire = false;
- } else {
- wakeLock = new WakeLock(lock, flags, tag, packageName, ws, historyTag, uid, pid);//新建
- try {
- lock.linkToDeath(wakeLock, 0);
- } catch (RemoteException ex) {
- throw new IllegalArgumentException("Wake lock is already dead.");
- }
- mWakeLocks.add(wakeLock);
- setWakeLockDisabledStateLocked(wakeLock);
- notifyAcquire = true;
- }
- applyWakeLockFlagsOnAcquireLocked(wakeLock, uid);//看是否需要唤醒设备
- mDirty |= DIRTY_WAKE_LOCKS;
- updatePowerStateLocked();// 更新电源状态
- if (notifyAcquire) {
- notifyWakeLockAcquiredLocked(wakeLock);
- }
- }
- }
updatePowerStateLocked函数我们放在后面说,我们再来看看applyWakeLockFlagsOnAcquireLocked函数:
- private void applyWakeLockFlagsOnAcquireLocked(WakeLock wakeLock, int uid) {
- if ((wakeLock.mFlags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0//wakelock中的flag有这个flag就需要唤醒设备
- && isScreenLock(wakeLock)) {
- String opPackageName;
- int opUid;
- if (wakeLock.mWorkSource != null && wakeLock.mWorkSource.getName(0) != null) {
- opPackageName = wakeLock.mWorkSource.getName(0);
- opUid = wakeLock.mWorkSource.get(0);
- } else {
- opPackageName = wakeLock.mPackageName;
- opUid = wakeLock.mWorkSource != null ? wakeLock.mWorkSource.get(0)
- : wakeLock.mOwnerUid;
- }
- wakeUpNoUpdateLocked(SystemClock.uptimeMillis(), wakeLock.mTag, opUid,
- opPackageName, opUid);
- }
- }
同样release,我们也直接分析releaseWakeLockInternal函数:
- private void releaseWakeLockInternal(IBinder lock, int flags) {
- synchronized (mLock) {
- int index = findWakeLockIndexLocked(lock);//找wakelock
- if (index < 0) {
- if (DEBUG_LC) {
- Slog.d(TAG, "releaseWakeLockInternal: lock=" + Objects.hashCode(lock)
- + " [not found], flags=0x" + Integer.toHexString(flags));
- }
- return;
- }
- WakeLock wakeLock = mWakeLocks.get(index);
- if (DEBUG_LC) {
- Slog.d(TAG, "releaseWakeLockInternal: lock=" + Objects.hashCode(lock)
- + " [" + wakeLock.mTag + "], flags=0x" + Integer.toHexString(flags));
- }
- if ((flags & PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY) != 0) {//距离传感器相关
- mRequestWaitForNegativeProximity = true;
- }
- wakeLock.mLock.unlinkToDeath(wakeLock, 0);
- removeWakeLockLocked(wakeLock, index);
- }
- }
removeWakeLockLocked函数,去除wakelock,最后调用updatePowerStateLocked
- private void removeWakeLockLocked(WakeLock wakeLock, int index) {
- mWakeLocks.remove(index);//去除wakelock
- notifyWakeLockReleasedLocked(wakeLock);
- applyWakeLockFlagsOnReleaseLocked(wakeLock);//是否触发userActivity
- mDirty |= DIRTY_WAKE_LOCKS;
- updatePowerStateLocked();
- }
applyWakeLockFlagsOnReleaseLocked函数:
- private void applyWakeLockFlagsOnReleaseLocked(WakeLock wakeLock) {
- if ((wakeLock.mFlags & PowerManager.ON_AFTER_RELEASE) != 0//有这个flag触发userActivity
- && isScreenLock(wakeLock)) {
- userActivityNoUpdateLocked(SystemClock.uptimeMillis(),
- PowerManager.USER_ACTIVITY_EVENT_OTHER,
- PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS,
- wakeLock.mOwnerUid);
- }
- }
下面我们就来看看之前acquire和realease都调用的函数updatePowerStateLocked:
- private void updatePowerStateLocked() {
- if (!mSystemReady || mDirty == 0) {
- return;
- }
- if (!Thread.holdsLock(mLock)) {
- Slog.wtf(TAG, "Power manager lock was not held when calling updatePowerStateLocked");
- }
- Trace.traceBegin(Trace.TRACE_TAG_POWER, "updatePowerState");
- try {
- // Phase 0: Basic state updates.
- updateIsPoweredLocked(mDirty);
- updateStayOnLocked(mDirty);
- updateScreenBrightnessBoostLocked(mDirty);
- // Phase 1: Update wakefulness.
- // Loop because the wake lock and user activity computations are influenced
- // by changes in wakefulness.
- final long now = SystemClock.uptimeMillis();
- int dirtyPhase2 = 0;
- for (;;) {
- int dirtyPhase1 = mDirty;
- dirtyPhase2 |= dirtyPhase1;
- mDirty = 0;
- updateWakeLockSummaryLocked(dirtyPhase1);
- updateUserActivitySummaryLocked(now, dirtyPhase1);
- if (!updateWakefulnessLocked(dirtyPhase1)) {
- break;
- }
- }
- // Phase 2: Update display power state.
- boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);
- // Phase 3: Update dream state (depends on display ready signal).
- updateDreamLocked(dirtyPhase2, displayBecameReady);
- // Phase 4: Send notifications, if needed.
- finishWakefulnessChangeIfNeededLocked();
- // Phase 5: Update suspend blocker.
- // Because we might release the last suspend blocker here, we need to make sure
- // we finished everything else first!
- updateSuspendBlockerLocked();
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_POWER);
- }
- }
其实这个函数我们先看下updateWakeLockSummaryLocked函数,根据wakelock来指定mWakeLockSummary
- private void updateWakeLockSummaryLocked(int dirty) {
- if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_WAKEFULNESS)) != 0) {
- mWakeLockSummary = 0;
- final int numWakeLocks = mWakeLocks.size();
- for (int i = 0; i < numWakeLocks; i++) {
- final WakeLock wakeLock = mWakeLocks.get(i);
- switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
- case PowerManager.PARTIAL_WAKE_LOCK:
- if (!wakeLock.mDisabled) {
- // We only respect this if the wake lock is not disabled.
- mWakeLockSummary |= WAKE_LOCK_CPU;//持cpu锁
- }
- break;
- case PowerManager.FULL_WAKE_LOCK:
- mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_BUTTON_BRIGHT;
- break;
- case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
- mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT;
- break;
- case PowerManager.SCREEN_DIM_WAKE_LOCK:
- mWakeLockSummary |= WAKE_LOCK_SCREEN_DIM;
- break;
- case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
- mWakeLockSummary |= WAKE_LOCK_PROXIMITY_SCREEN_OFF;
- break;
- case PowerManager.DOZE_WAKE_LOCK:
- mWakeLockSummary |= WAKE_LOCK_DOZE;
- break;
- case PowerManager.DRAW_WAKE_LOCK:
- mWakeLockSummary |= WAKE_LOCK_DRAW;
- break;
- }
- }
- // Cancel wake locks that make no sense based on the current state.
- if (mWakefulness != WAKEFULNESS_DOZING) {
- mWakeLockSummary &= ~(WAKE_LOCK_DOZE | WAKE_LOCK_DRAW);
- }
- if (mWakefulness == WAKEFULNESS_ASLEEP
- || (mWakeLockSummary & WAKE_LOCK_DOZE) != 0) {
- mWakeLockSummary &= ~(WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM
- | WAKE_LOCK_BUTTON_BRIGHT);
- if (mWakefulness == WAKEFULNESS_ASLEEP) {
- mWakeLockSummary &= ~WAKE_LOCK_PROXIMITY_SCREEN_OFF;
- }
- }
- // Infer implied wake locks where necessary based on the current state.
- if ((mWakeLockSummary & (WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM)) != 0) {
- if (mWakefulness == WAKEFULNESS_AWAKE) {
- mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_STAY_AWAKE;
- } else if (mWakefulness == WAKEFULNESS_DREAMING) {
- mWakeLockSummary |= WAKE_LOCK_CPU;
- }
- }
- if ((mWakeLockSummary & WAKE_LOCK_DRAW) != 0) {
- mWakeLockSummary |= WAKE_LOCK_CPU;
- }
- if (DEBUG_SPEW) {
- Slog.d(TAG, "updateWakeLockSummaryLocked: mWakefulness="
- + PowerManagerInternal.wakefulnessToString(mWakefulness)
- + ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary));
- }
- }
- }
最后我们主要看下updateSuspendBlockerLocked这个函数:
- private void updateSuspendBlockerLocked() {
- final boolean needWakeLockSuspendBlocker = ((mWakeLockSummary & WAKE_LOCK_CPU) != 0);//是否需要持锁
- final boolean needDisplaySuspendBlocker = needDisplaySuspendBlockerLocked();
- final boolean autoSuspend = !needDisplaySuspendBlocker;
- final boolean interactive = mDisplayPowerRequest.isBrightOrDim();
- // Disable auto-suspend if needed.
- // FIXME We should consider just leaving auto-suspend enabled forever since
- // we already hold the necessary wakelocks.
- if (!autoSuspend && mDecoupleHalAutoSuspendModeFromDisplayConfig) {//配置是否需要自动持锁开启
- setHalAutoSuspendModeLocked(false);
- }
- // First acquire suspend blockers if needed.
- if (needWakeLockSuspendBlocker && !mHoldingWakeLockSuspendBlocker) {
- mWakeLockSuspendBlocker.acquire();//wakelock持锁
- mHoldingWakeLockSuspendBlocker = true;
- }
- if (needDisplaySuspendBlocker && !mHoldingDisplaySuspendBlocker) {
- mDisplaySuspendBlocker.acquire();//Display持锁
- mHoldingDisplaySuspendBlocker = true;
- }
- ......
- // Then release suspend blockers if needed.
- if (!needWakeLockSuspendBlocker && mHoldingWakeLockSuspendBlocker) {
- mWakeLockSuspendBlocker.release();//wakelock锁释放
- mHoldingWakeLockSuspendBlocker = false;
- }
- if (!needDisplaySuspendBlocker && mHoldingDisplaySuspendBlocker) {
- mDisplaySuspendBlocker.release();//Display锁释放
- mHoldingDisplaySuspendBlocker = false;
- }
- // Enable auto-suspend if needed.
- if (autoSuspend && mDecoupleHalAutoSuspendModeFromDisplayConfig) {//配置设置&&可以自动持锁
- setHalAutoSuspendModeLocked(true);//自动持锁开启
- }
- }
先来看看needDisPlaySuspendBlockerLocked函数,是否将Display锁释放
- private boolean needDisplaySuspendBlockerLocked() {
- if (!mDisplayReady) {
- return true;//需要持锁
- }
- if (mDisplayPowerRequest.isBrightOrDim()) {
- // If we asked for the screen to be on but it is off due to the proximity
- // sensor then we may suspend but only if the configuration allows it.
- // On some hardware it may not be safe to suspend because the proximity
- // sensor may not be correctly configured as a wake-up source.
- if (!mDisplayPowerRequest.useProximitySensor || !mProximityPositive
- || !mSuspendWhenScreenOffDueToProximityConfig) {
- return true;
- }
- }
- if (mScreenBrightnessBoostInProgress) {
- return true;
- }
- // Let the system suspend if the screen is off or dozing.
- return false;
- }
这里有两个锁Display和WakeLocks锁,但是这两个锁和之前PowerManager的锁意义不一样,这两个锁是针对hal层的是真正的锁。我们来看下这两个锁。
在PowerManagerService的构造函数中就创建了这两个锁。
- mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks");
- mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display");
- private SuspendBlocker createSuspendBlockerLocked(String name) {
- SuspendBlocker suspendBlocker = new SuspendBlockerImpl(name);
- mSuspendBlockers.add(suspendBlocker);
- return suspendBlocker;
- }
- 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
- protected void finalize() throws Throwable {
- try {
- if (mReferenceCount != 0) {
- Slog.wtf(TAG, "Suspend blocker \"" + mName
- + "\" was finalized without being released!");
- mReferenceCount = 0;
- nativeReleaseSuspendBlocker(mName);
- Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, mTraceName, 0);
- }
- } finally {
- super.finalize();
- }
- }
- @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);//持锁调用hal层函数
- }
- }
- }
- @Override
- public void release() {
- synchronized (this) {
- mReferenceCount -= 1;
- if (mReferenceCount == 0) {//使用计数
- if (DEBUG_SPEW) {
- Slog.d(TAG, "Releasing suspend blocker \"" + mName + "\".");
- }
- nativeReleaseSuspendBlocker(mName);//释放锁调用hal层
- 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;
- }
- }
- }
三、hal层持锁相关函数
hal层的持锁和释放锁的函数如下,在com_android_server_power_PowerManagerService.cpp文件
- 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());
- }
- 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));
- }
先来看initialize_fds函数,调用open_file_descriptors函数:
- 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;
- }
- }
我们先来看看NEW_PATHS
- const char * const NEW_PATHS[] = {
- "/sys/power/wake_lock",
- "/sys/power/wake_unlock",
- };
再来看看open_file_descriptors函数:
- 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) {
- fprintf(stderr, "fatal error opening \"%s\"\n", paths[i]);
- g_error = errno;
- return -1;
- }
- g_fds[i] = fd;//填充g_fds,一个是wake_lock另一个是wake_unlock
- }
- g_error = 0;
- return 0;
- }
- 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];//获取wake_lock的fd
- }
- else {
- return EINVAL;
- }
- return write(fd, id, strlen(id));//往里面写值
- }
- int
- release_wake_lock(const char* id)
- {
- initialize_fds();
- if (g_error) return g_error;
- ssize_t len = write(g_fds[RELEASE_WAKE_LOCK], id, strlen(id));//获取wake_unlock的fd,往里面写值
- return len >= 0;
- }
- root@lte26007:/sys/power # cat wake_lock
- PowerManagerService.Display PowerManagerService.WakeLocks
- root@lte26007:/sys/power # cat wake_unlock
- KeyEvents radio-interface
如果灭屏了,Display锁会释放
- root@lte26007:/sys/power # cat wake_unlock
- KeyEvents PowerManagerService.Broadcasts PowerManagerService.Display radio-interface
autosuspend我们这里也就不讲了。
四、总结
这篇博客我们主要分析了从PowerManager的持锁,然后到PowerManagerService的一些逻辑处理。最后由PowerManagerService调用hal层真正的锁来让cpu保持工作。
原文地址: http://46aae4d1e2371e4aa769798941cef698.devproxy.yunshipei.com/kc58236582/article/details/51564328
- Android6.0 wakelock深入分析
- Android6.0 wakelock深入分析
- Android6.0 init 深入分析
- Android6.0 init 深入分析
- android6.0 power按键深入分析
- android6.0系统Healthd深入分析
- android6.0系统Healthd深入分析
- android6.0 power按键深入分析
- android6.0系统Healthd深入分析
- android6.0 power按键深入分析
- android6.0系统Healthd深入分析
- android6.0 power按键深入分析
- (原创)android6.0系统Healthd深入分析
- android6.0 power显示(亮度等)深入分析(二)DisplayManagerService
- android6.0 power显示(亮度等)深入分析(二)DisplayManagerService
- android6.0系统 PowerManager深入分析(非常详细)
- Android6.0权限分析
- (原创)android6.0系统 PowerManager深入分析(非常详细)
- TCP和UDP差异
- 聊天气泡框模块源码 (高仿微信、QQ聊天的气泡聊天框)
- java静态方法与成员方法及成员变量的区分
- swift代码之路(五)NSTimer
- Nagios 配置及监控
- Android6.0 wakelock深入分析
- CentOS 6.3安装配置LAMP服务器(Apache+PHP5+MySQL)
- hdu 4185 Oil Skimming【二分匹配】
- 3.5
- tomcat eclipse 插件配置
- UVa 10820 Send a Table
- Windows文件链接的四种方式
- 到哪里搞TMS320F28的各种资料,函数库等等
- Mac OS 环境配置 for caffe