Android6.0 wakelock深入分析

来源:互联网 发布:反潜鱼雷 知乎 编辑:程序博客网 时间:2024/05/01 13:01

这篇博客我们分析下Power的持锁,从PowerManager到PowerManagerService再到hal分析。

一、PowerManager的持锁接口

我们先来看下PowerManager对应用提供的接口:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. public WakeLock newWakeLock(int levelAndFlags, String tag) {  
  2.     validateWakeLockParameters(levelAndFlags, tag);//验证wakelock的flag是否有效  
  3.     return new WakeLock(levelAndFlags, tag, mContext.getOpPackageName());  
  4. }  

validateWakeLockParameters函数如下:主要对flag没有下面这些flag做过滤

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. public static void validateWakeLockParameters(int levelAndFlags, String tag) {  
  2.     switch (levelAndFlags & WAKE_LOCK_LEVEL_MASK) {  
  3.         case PARTIAL_WAKE_LOCK://cpu锁  
  4.         case SCREEN_DIM_WAKE_LOCK://屏幕微亮,键盘暗  
  5.         case SCREEN_BRIGHT_WAKE_LOCK://屏幕亮,键盘暗  
  6.         case FULL_WAKE_LOCK://全亮  
  7.         case PROXIMITY_SCREEN_OFF_WAKE_LOCK:  
  8.         case DOZE_WAKE_LOCK:  
  9.         case DRAW_WAKE_LOCK:  
  10.             break;  
  11.         default:  
  12.             throw new IllegalArgumentException("Must specify a valid wake lock level.");  
  13.     }  
  14.     if (tag == null) {  
  15.         throw new IllegalArgumentException("The tag must not be null.");  
  16.     }  
  17. }  

我们再看WakeLock类,先看下面两个持锁,第二个timeout的持锁,先持锁,然后发送一个延迟消息再解锁。

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. public void acquire() {  
  2.     synchronized (mToken) {  
  3.         acquireLocked();  
  4.     }  
  5. }  
  6.   
  7. public void acquire(long timeout) {  
  8.     synchronized (mToken) {  
  9.         acquireLocked();  
  10.         mHandler.postDelayed(mReleaser, timeout);  
  11.     }  
  12. }  
[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. private final Runnable mReleaser = new Runnable() {  
  2.     public void run() {  
  3.         release();  
  4.     }  
  5. };  

再来看acquireLocked,流程最后是调用了service的acquireWakeLock,但是有一个细节我们注意下,这里有一个mCount的计数。也就是没调用一次这个函数,都会对wakelock的mCount加1。

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. private void acquireLocked() {  
  2.     if (!mRefCounted || mCount++ == 0) {  
  3.         // Do this even if the wake lock is already thought to be held (mHeld == true)  
  4.         // because non-reference counted wake locks are not always properly released.  
  5.         // For example, the keyguard's wake lock might be forcibly released by the  
  6.         // power manager without the keyguard knowing.  A subsequent call to acquire  
  7.         // should immediately acquire the wake lock once again despite never having  
  8.         // been explicitly released by the keyguard.  
  9.         mHandler.removeCallbacks(mReleaser);  
  10.         Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, mTraceName, 0);  
  11.         try {  
  12.             mService.acquireWakeLock(mToken, mFlags, mTag, mPackageName, mWorkSource,  
  13.                     mHistoryTag);  
  14.         } catch (RemoteException e) {  
  15.         }  
  16.         mHeld = true;  
  17.     }  
  18. }  

我们再来看看release函数,上面说的mCount计数,这里就会对这个计数进行判断,只有当计数为0,才会去调用service的releaseWakeLock函数。

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. public void release(int flags) {  
  2.     synchronized (mToken) {  
  3.         if (!mRefCounted || --mCount == 0) {  
  4.             mHandler.removeCallbacks(mReleaser);  
  5.             if (mHeld) {  
  6.                 Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, mTraceName, 0);  
  7.                 try {  
  8.                     mService.releaseWakeLock(mToken, flags);  
  9.                 } catch (RemoteException e) {  
  10.                 }  
  11.                 mHeld = false;  
  12.             }  
  13.         }  
  14.         if (mCount < 0) {  
  15.             throw new RuntimeException("WakeLock under-locked " + mTag);  
  16.         }  
  17.     }  
  18. }  

所以我们总结下,使用PowerManager的wakelock持锁和释放锁。必须成对出现,当持了2次锁,也必须释放两次锁。才会调用service的释放锁,去真正释放。


二、PowerManagerService相关接口

Service的acquireWakeLock函数我们就不看了,主要是对wakelock的flag做验证,然后调用了acquireWakeLockInternal函数:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. private void acquireWakeLockInternal(IBinder lock, int flags, String tag, String packageName,  
  2.         WorkSource ws, String historyTag, int uid, int pid) {  
  3.     synchronized (mLock) {  
  4.         WakeLock wakeLock;  
  5.         int index = findWakeLockIndexLocked(lock);//查找wakelock,IBinder对象为wakelock唯一性  
  6.         boolean notifyAcquire;  
  7.         if (index >= 0) {  
  8.             wakeLock = mWakeLocks.get(index);  
  9.             if (!wakeLock.hasSameProperties(flags, tag, ws, uid, pid)) {  
  10.                 // Update existing wake lock.  This shouldn't happen but is harmless.  
  11.                 notifyWakeLockChangingLocked(wakeLock, flags, tag, packageName,  
  12.                         uid, pid, ws, historyTag);  
  13.                 wakeLock.updateProperties(flags, tag, packageName, ws, historyTag, uid, pid);//更新参数  
  14.             }  
  15.             notifyAcquire = false;  
  16.         } else {  
  17.             wakeLock = new WakeLock(lock, flags, tag, packageName, ws, historyTag, uid, pid);//新建  
  18.             try {  
  19.                 lock.linkToDeath(wakeLock, 0);  
  20.             } catch (RemoteException ex) {  
  21.                 throw new IllegalArgumentException("Wake lock is already dead.");  
  22.             }  
  23.             mWakeLocks.add(wakeLock);  
  24.             setWakeLockDisabledStateLocked(wakeLock);  
  25.             notifyAcquire = true;  
  26.         }  
  27.   
  28.         applyWakeLockFlagsOnAcquireLocked(wakeLock, uid);//看是否需要唤醒设备  
  29.         mDirty |= DIRTY_WAKE_LOCKS;  
  30.         updatePowerStateLocked();// 更新电源状态  
  31.         if (notifyAcquire) {  
  32.             notifyWakeLockAcquiredLocked(wakeLock);  
  33.         }  
  34.     }  
  35. }  

updatePowerStateLocked函数我们放在后面说,我们再来看看applyWakeLockFlagsOnAcquireLocked函数:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. private void applyWakeLockFlagsOnAcquireLocked(WakeLock wakeLock, int uid) {  
  2.     if ((wakeLock.mFlags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0//wakelock中的flag有这个flag就需要唤醒设备  
  3.             && isScreenLock(wakeLock)) {  
  4.         String opPackageName;  
  5.         int opUid;  
  6.         if (wakeLock.mWorkSource != null && wakeLock.mWorkSource.getName(0) != null) {  
  7.             opPackageName = wakeLock.mWorkSource.getName(0);  
  8.             opUid = wakeLock.mWorkSource.get(0);  
  9.         } else {  
  10.             opPackageName = wakeLock.mPackageName;  
  11.             opUid = wakeLock.mWorkSource != null ? wakeLock.mWorkSource.get(0)  
  12.                     : wakeLock.mOwnerUid;  
  13.         }  
  14.         wakeUpNoUpdateLocked(SystemClock.uptimeMillis(), wakeLock.mTag, opUid,  
  15.                 opPackageName, opUid);  
  16.     }  
  17. }  

同样release,我们也直接分析releaseWakeLockInternal函数:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. private void releaseWakeLockInternal(IBinder lock, int flags) {  
  2.     synchronized (mLock) {  
  3.         int index = findWakeLockIndexLocked(lock);//找wakelock  
  4.         if (index < 0) {  
  5.             if (DEBUG_LC) {  
  6.                 Slog.d(TAG, "releaseWakeLockInternal: lock=" + Objects.hashCode(lock)  
  7.                         + " [not found], flags=0x" + Integer.toHexString(flags));  
  8.             }  
  9.             return;  
  10.         }  
  11.   
  12.         WakeLock wakeLock = mWakeLocks.get(index);  
  13.         if (DEBUG_LC) {  
  14.             Slog.d(TAG, "releaseWakeLockInternal: lock=" + Objects.hashCode(lock)  
  15.                     + " [" + wakeLock.mTag + "], flags=0x" + Integer.toHexString(flags));  
  16.         }  
  17.   
  18.         if ((flags & PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY) != 0) {//距离传感器相关  
  19.             mRequestWaitForNegativeProximity = true;  
  20.         }  
  21.   
  22.         wakeLock.mLock.unlinkToDeath(wakeLock, 0);  
  23.         removeWakeLockLocked(wakeLock, index);  
  24.     }  
  25. }  

removeWakeLockLocked函数,去除wakelock,最后调用updatePowerStateLocked

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. private void removeWakeLockLocked(WakeLock wakeLock, int index) {  
  2.     mWakeLocks.remove(index);//去除wakelock  
  3.     notifyWakeLockReleasedLocked(wakeLock);  
  4.   
  5.     applyWakeLockFlagsOnReleaseLocked(wakeLock);//是否触发userActivity  
  6.     mDirty |= DIRTY_WAKE_LOCKS;  
  7.     updatePowerStateLocked();  
  8. }  

applyWakeLockFlagsOnReleaseLocked函数:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. private void applyWakeLockFlagsOnReleaseLocked(WakeLock wakeLock) {  
  2.     if ((wakeLock.mFlags & PowerManager.ON_AFTER_RELEASE) != 0//有这个flag触发userActivity  
  3.             && isScreenLock(wakeLock)) {  
  4.         userActivityNoUpdateLocked(SystemClock.uptimeMillis(),  
  5.                 PowerManager.USER_ACTIVITY_EVENT_OTHER,  
  6.                 PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS,  
  7.                 wakeLock.mOwnerUid);  
  8.     }  
  9. }  

下面我们就来看看之前acquire和realease都调用的函数updatePowerStateLocked:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. private void updatePowerStateLocked() {  
  2.     if (!mSystemReady || mDirty == 0) {  
  3.         return;  
  4.     }  
  5.     if (!Thread.holdsLock(mLock)) {  
  6.         Slog.wtf(TAG, "Power manager lock was not held when calling updatePowerStateLocked");  
  7.     }  
  8.   
  9.     Trace.traceBegin(Trace.TRACE_TAG_POWER, "updatePowerState");  
  10.     try {  
  11.         // Phase 0: Basic state updates.  
  12.         updateIsPoweredLocked(mDirty);  
  13.         updateStayOnLocked(mDirty);  
  14.         updateScreenBrightnessBoostLocked(mDirty);  
  15.   
  16.         // Phase 1: Update wakefulness.  
  17.         // Loop because the wake lock and user activity computations are influenced  
  18.         // by changes in wakefulness.  
  19.         final long now = SystemClock.uptimeMillis();  
  20.         int dirtyPhase2 = 0;  
  21.         for (;;) {  
  22.             int dirtyPhase1 = mDirty;  
  23.             dirtyPhase2 |= dirtyPhase1;  
  24.             mDirty = 0;  
  25.   
  26.             updateWakeLockSummaryLocked(dirtyPhase1);  
  27.             updateUserActivitySummaryLocked(now, dirtyPhase1);  
  28.             if (!updateWakefulnessLocked(dirtyPhase1)) {  
  29.                 break;  
  30.             }  
  31.         }  
  32.   
  33.         // Phase 2: Update display power state.  
  34.         boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);  
  35.   
  36.         // Phase 3: Update dream state (depends on display ready signal).  
  37.         updateDreamLocked(dirtyPhase2, displayBecameReady);  
  38.   
  39.         // Phase 4: Send notifications, if needed.  
  40.         finishWakefulnessChangeIfNeededLocked();  
  41.   
  42.         // Phase 5: Update suspend blocker.  
  43.         // Because we might release the last suspend blocker here, we need to make sure  
  44.         // we finished everything else first!  
  45.         updateSuspendBlockerLocked();  
  46.     } finally {  
  47.         Trace.traceEnd(Trace.TRACE_TAG_POWER);  
  48.     }  
  49. }  

其实这个函数我们先看下updateWakeLockSummaryLocked函数,根据wakelock来指定mWakeLockSummary

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. private void updateWakeLockSummaryLocked(int dirty) {  
  2.     if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_WAKEFULNESS)) != 0) {  
  3.         mWakeLockSummary = 0;  
  4.   
  5.         final int numWakeLocks = mWakeLocks.size();  
  6.         for (int i = 0; i < numWakeLocks; i++) {  
  7.             final WakeLock wakeLock = mWakeLocks.get(i);  
  8.             switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {  
  9.                 case PowerManager.PARTIAL_WAKE_LOCK:  
  10.                     if (!wakeLock.mDisabled) {  
  11.                         // We only respect this if the wake lock is not disabled.  
  12.                         mWakeLockSummary |= WAKE_LOCK_CPU;//持cpu锁  
  13.                     }  
  14.                     break;  
  15.                 case PowerManager.FULL_WAKE_LOCK:  
  16.                     mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_BUTTON_BRIGHT;  
  17.                     break;  
  18.                 case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:  
  19.                     mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT;  
  20.                     break;  
  21.                 case PowerManager.SCREEN_DIM_WAKE_LOCK:  
  22.                     mWakeLockSummary |= WAKE_LOCK_SCREEN_DIM;  
  23.                     break;  
  24.                 case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:  
  25.                     mWakeLockSummary |= WAKE_LOCK_PROXIMITY_SCREEN_OFF;  
  26.                     break;  
  27.                 case PowerManager.DOZE_WAKE_LOCK:  
  28.                     mWakeLockSummary |= WAKE_LOCK_DOZE;  
  29.                     break;  
  30.                 case PowerManager.DRAW_WAKE_LOCK:  
  31.                     mWakeLockSummary |= WAKE_LOCK_DRAW;  
  32.                     break;  
  33.             }  
  34.         }  
  35.   
  36.         // Cancel wake locks that make no sense based on the current state.  
  37.         if (mWakefulness != WAKEFULNESS_DOZING) {  
  38.             mWakeLockSummary &= ~(WAKE_LOCK_DOZE | WAKE_LOCK_DRAW);  
  39.         }  
  40.         if (mWakefulness == WAKEFULNESS_ASLEEP  
  41.                 || (mWakeLockSummary & WAKE_LOCK_DOZE) != 0) {  
  42.             mWakeLockSummary &= ~(WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM  
  43.                     | WAKE_LOCK_BUTTON_BRIGHT);  
  44.             if (mWakefulness == WAKEFULNESS_ASLEEP) {  
  45.                 mWakeLockSummary &= ~WAKE_LOCK_PROXIMITY_SCREEN_OFF;  
  46.             }  
  47.         }  
  48.   
  49.         // Infer implied wake locks where necessary based on the current state.  
  50.         if ((mWakeLockSummary & (WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM)) != 0) {  
  51.             if (mWakefulness == WAKEFULNESS_AWAKE) {  
  52.                 mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_STAY_AWAKE;  
  53.             } else if (mWakefulness == WAKEFULNESS_DREAMING) {  
  54.                 mWakeLockSummary |= WAKE_LOCK_CPU;  
  55.             }  
  56.         }  
  57.         if ((mWakeLockSummary & WAKE_LOCK_DRAW) != 0) {  
  58.             mWakeLockSummary |= WAKE_LOCK_CPU;  
  59.         }  
  60.   
  61.         if (DEBUG_SPEW) {  
  62.             Slog.d(TAG, "updateWakeLockSummaryLocked: mWakefulness="  
  63.                     + PowerManagerInternal.wakefulnessToString(mWakefulness)  
  64.                     + ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary));  
  65.         }  
  66.     }  
  67. }  

最后我们主要看下updateSuspendBlockerLocked这个函数:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. private void updateSuspendBlockerLocked() {  
  2.     final boolean needWakeLockSuspendBlocker = ((mWakeLockSummary & WAKE_LOCK_CPU) != 0);//是否需要持锁  
  3.     final boolean needDisplaySuspendBlocker = needDisplaySuspendBlockerLocked();  
  4.     final boolean autoSuspend = !needDisplaySuspendBlocker;  
  5.     final boolean interactive = mDisplayPowerRequest.isBrightOrDim();  
  6.   
  7.     // Disable auto-suspend if needed.  
  8.     // FIXME We should consider just leaving auto-suspend enabled forever since  
  9.     // we already hold the necessary wakelocks.  
  10.     if (!autoSuspend && mDecoupleHalAutoSuspendModeFromDisplayConfig) {//配置是否需要自动持锁开启  
  11.         setHalAutoSuspendModeLocked(false);  
  12.     }  
  13.   
  14.     // First acquire suspend blockers if needed.  
  15.     if (needWakeLockSuspendBlocker && !mHoldingWakeLockSuspendBlocker) {  
  16.         mWakeLockSuspendBlocker.acquire();//wakelock持锁  
  17.         mHoldingWakeLockSuspendBlocker = true;  
  18.     }  
  19.     if (needDisplaySuspendBlocker && !mHoldingDisplaySuspendBlocker) {  
  20.         mDisplaySuspendBlocker.acquire();//Display持锁  
  21.         mHoldingDisplaySuspendBlocker = true;  
  22.     }  
  23.   
  24.     ......  
  25.   
  26.     // Then release suspend blockers if needed.  
  27.     if (!needWakeLockSuspendBlocker && mHoldingWakeLockSuspendBlocker) {  
  28.         mWakeLockSuspendBlocker.release();//wakelock锁释放  
  29.         mHoldingWakeLockSuspendBlocker = false;  
  30.     }  
  31.     if (!needDisplaySuspendBlocker && mHoldingDisplaySuspendBlocker) {  
  32.         mDisplaySuspendBlocker.release();//Display锁释放  
  33.         mHoldingDisplaySuspendBlocker = false;  
  34.     }  
  35.   
  36.     // Enable auto-suspend if needed.  
  37.     if (autoSuspend && mDecoupleHalAutoSuspendModeFromDisplayConfig) {//配置设置&&可以自动持锁  
  38.         setHalAutoSuspendModeLocked(true);//自动持锁开启  
  39.     }  
  40. }  

先来看看needDisPlaySuspendBlockerLocked函数,是否将Display锁释放

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. private boolean needDisplaySuspendBlockerLocked() {  
  2.     if (!mDisplayReady) {  
  3.         return true;//需要持锁  
  4.     }  
  5.     if (mDisplayPowerRequest.isBrightOrDim()) {  
  6.         // If we asked for the screen to be on but it is off due to the proximity  
  7.         // sensor then we may suspend but only if the configuration allows it.  
  8.         // On some hardware it may not be safe to suspend because the proximity  
  9.         // sensor may not be correctly configured as a wake-up source.  
  10.         if (!mDisplayPowerRequest.useProximitySensor || !mProximityPositive  
  11.                 || !mSuspendWhenScreenOffDueToProximityConfig) {  
  12.             return true;  
  13.         }  
  14.     }  
  15.     if (mScreenBrightnessBoostInProgress) {  
  16.         return true;  
  17.     }  
  18.     // Let the system suspend if the screen is off or dozing.  
  19.     return false;  
  20. }  

这里有两个锁Display和WakeLocks锁,但是这两个锁和之前PowerManager的锁意义不一样,这两个锁是针对hal层的是真正的锁。我们来看下这两个锁。


在PowerManagerService的构造函数中就创建了这两个锁。

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks");  
  2. mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display");  
createSuspendBlockerLocked函数就是新建SuspendBlockerImpl对象:
[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. private SuspendBlocker createSuspendBlockerLocked(String name) {  
  2.     SuspendBlocker suspendBlocker = new SuspendBlockerImpl(name);  
  3.     mSuspendBlockers.add(suspendBlocker);  
  4.     return suspendBlocker;  
  5. }  
再来看看SuspendBlockerImpl 类:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. private final class SuspendBlockerImpl implements SuspendBlocker {  
  2.     private final String mName;  
  3.     private final String mTraceName;  
  4.     private int mReferenceCount;  
  5.   
  6.     public SuspendBlockerImpl(String name) {  
  7.         mName = name;  
  8.         mTraceName = "SuspendBlocker (" + name + ")";  
  9.     }  
  10.   
  11.     @Override  
  12.     protected void finalize() throws Throwable {  
  13.         try {  
  14.             if (mReferenceCount != 0) {  
  15.                 Slog.wtf(TAG, "Suspend blocker \"" + mName  
  16.                         + "\" was finalized without being released!");  
  17.                 mReferenceCount = 0;  
  18.                 nativeReleaseSuspendBlocker(mName);  
  19.                 Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, mTraceName, 0);  
  20.             }  
  21.         } finally {  
  22.             super.finalize();  
  23.         }  
  24.     }  
  25.   
  26.     @Override  
  27.     public void acquire() {  
  28.         synchronized (this) {  
  29.             mReferenceCount += 1;  
  30.             if (mReferenceCount == 1) {//这里也使用了计数  
  31.                 if (DEBUG_SPEW) {  
  32.                     Slog.d(TAG, "Acquiring suspend blocker \"" + mName + "\".");  
  33.                 }  
  34.                 Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, mTraceName, 0);  
  35.                 nativeAcquireSuspendBlocker(mName);//持锁调用hal层函数  
  36.             }  
  37.         }  
  38.     }  
  39.   
  40.     @Override  
  41.     public void release() {  
  42.         synchronized (this) {  
  43.             mReferenceCount -= 1;  
  44.             if (mReferenceCount == 0) {//使用计数  
  45.                 if (DEBUG_SPEW) {  
  46.                     Slog.d(TAG, "Releasing suspend blocker \"" + mName + "\".");  
  47.                 }  
  48.                 nativeReleaseSuspendBlocker(mName);//释放锁调用hal层  
  49.                 Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, mTraceName, 0);  
  50.             } else if (mReferenceCount < 0) {  
  51.                 Slog.wtf(TAG, "Suspend blocker \"" + mName  
  52.                         + "\" was released without being acquired!"new Throwable());  
  53.                 mReferenceCount = 0;  
  54.             }  
  55.         }  
  56.     }  


三、hal层持锁相关函数

hal层的持锁和释放锁的函数如下,在com_android_server_power_PowerManagerService.cpp文件

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  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.   
  6. static void nativeReleaseSuspendBlocker(JNIEnv *env, jclass /* clazz */, jstring nameStr) {  
  7.     ScopedUtfChars name(env, nameStr);  
  8.     release_wake_lock(name.c_str());  
  9. }  
我们再看看power.c的代码,在hardware目录下。先来看持锁:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. int  
  2. acquire_wake_lock(int lock, const char* id)  
  3. {  
  4.     initialize_fds();  
  5.   
  6.     if (g_error) return g_error;  
  7.   
  8.     int fd;  
  9.   
  10.     if (lock == PARTIAL_WAKE_LOCK) {  
  11.         fd = g_fds[ACQUIRE_PARTIAL_WAKE_LOCK];  
  12.     }  
  13.     else {  
  14.         return EINVAL;  
  15.     }  
  16.   
  17.     return write(fd, id, strlen(id));  
  18. }  

先来看initialize_fds函数,调用open_file_descriptors函数:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. static inline void  
  2. initialize_fds(void)  
  3. {  
  4.     if (g_initialized == 0) {  
  5.         if(open_file_descriptors(NEW_PATHS) < 0)  
  6.             open_file_descriptors(OLD_PATHS);  
  7.         g_initialized = 1;  
  8.     }  
  9. }  

我们先来看看NEW_PATHS

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. const char * const NEW_PATHS[] = {  
  2.     "/sys/power/wake_lock",  
  3.     "/sys/power/wake_unlock",  
  4. };  

再来看看open_file_descriptors函数:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. static int  
  2. open_file_descriptors(const char * const paths[])  
  3. {  
  4.     int i;  
  5.     for (i=0; i<OUR_FD_COUNT; i++) {  
  6.         int fd = open(paths[i], O_RDWR | O_CLOEXEC);  
  7.         if (fd < 0) {  
  8.             fprintf(stderr, "fatal error opening \"%s\"\n", paths[i]);  
  9.             g_error = errno;  
  10.             return -1;  
  11.         }  
  12.         g_fds[i] = fd;//填充g_fds,一个是wake_lock另一个是wake_unlock  
  13.     }  
  14.   
  15.     g_error = 0;  
  16.     return 0;  
  17. }  
现在再来看看这两个函数
[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. int  
  2. acquire_wake_lock(int lock, const char* id)  
  3. {  
  4.     initialize_fds();  
  5.   
  6.     if (g_error) return g_error;  
  7.   
  8.     int fd;  
  9.   
  10.     if (lock == PARTIAL_WAKE_LOCK) {  
  11.         fd = g_fds[ACQUIRE_PARTIAL_WAKE_LOCK];//获取wake_lock的fd  
  12.     }  
  13.     else {  
  14.         return EINVAL;  
  15.     }  
  16.   
  17.     return write(fd, id, strlen(id));//往里面写值  
  18. }  
  19.   
  20. int  
  21. release_wake_lock(const char* id)  
  22. {  
  23.     initialize_fds();  
  24.   
  25.     if (g_error) return g_error;  
  26.   
  27.     ssize_t len = write(g_fds[RELEASE_WAKE_LOCK], id, strlen(id));//获取wake_unlock的fd,往里面写值  
  28.     return len >= 0;  
  29. }  
这样看上层PowerManager的两个锁是否存在我们可以查看/sys/power/wake_lock和/sys/power/wake_unlock这两个目录。

[html] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. root@lte26007:/sys/power # cat wake_lock  
  2. PowerManagerService.Display PowerManagerService.WakeLocks  

[html] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. root@lte26007:/sys/power # cat wake_unlock  
  2. KeyEvents radio-interface  

如果灭屏了,Display锁会释放

[html] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. root@lte26007:/sys/power # cat wake_unlock  
  2. KeyEvents PowerManagerService.Broadcasts PowerManagerService.Display radio-interface  

autosuspend我们这里也就不讲了。


四、总结

这篇博客我们主要分析了从PowerManager的持锁,然后到PowerManagerService的一些逻辑处理。最后由PowerManagerService调用hal层真正的锁来让cpu保持工作。

原文地址: http://46aae4d1e2371e4aa769798941cef698.devproxy.yunshipei.com/kc58236582/article/details/51564328

0 0
原创粉丝点击