天天看點

Android wakelock 學習總結第一篇

轉載自: http://slightsnow.blog.chinaunix.net/uid-29269256-id-4090529.html

最近好好學習看了看Android 關于睡眠的代碼,從Framewake到Native到Kernel 學習了下,下面先對Framewake Native Kernel 做個簡單總結: 按照自己看代碼的了解和網上看得知識,如果不對,希望大牛們可以幫我指出來

以前從來沒有看過上層的代碼,最近看了之後,發現上層的代碼結構複雜程度和KERNEL有一拼,但是封裝的很好,學習了

言歸正傳:

我暫時把APP Framewake Native JNI看作成上層,底層包含kernel

需要先明白兩個類的關系,第一個是PowerManager,還有一個是PowerManagerService,第一個是提供給上層APP調用的封裝接口,第二個是具體的實作,

他們兩個關聯檔案是 IPowerManager.aidl ,由于沒有經驗找了半天IPowerManager.cpp,後來發現跟IPowerManager.cpp半毛錢關系都沒有,PowerManagerService繼承了

IPowerManager類,并且實作了相關的方法,具體接口定義都存在IPowerManager.aidl中,看到這裡是不是很迫不及待寫個應用去嘗試調用PowerManager去建立一個鎖了,不讓系統睡,哇哈哈

frameworks/base/services/java/com/android/server/power/PowerManagerService.cpp 這個目錄下所有的檔案都比較重要,這個會編譯到 services 中

frameworks/base/core/java/android/os/IPowerManager.aidl

frameworks/base/core/java/android/os/IPowerManager.java

我們需要看看給APP提供那些接口呢? 這裡不一一列舉,就說幾個,左邊就是APP可以調用的接口,而右邊是PowerManagerService對應的實作方法,這裡有一個很重要的問題,

他們兩個是通過什麼通信呢?沒錯,是使用binder,我沒有看過,還不太明白,以後再說。

PowerManager PowerManagerService
goToSleep(long time) goToSleep(long eventTime, int reason)
isScreenOn() isScreenOn()
reboot(String reason) reboot(boolean confirm, String reason, boolean wait)
userActivity(long when, boolean noChangeLights) userActivity(long eventTime, int event, int flags)
wakeUp(long time) wakeUp(long eventTime)

我們先跟随goToSleep函數吧,這個是在PowerManager.cpp中的

479     public void goToSleep(long time) {

480         try {

481             mService.goToSleep(time, GO_TO_SLEEP_REASON_USER);                                                                             

482         } catch (RemoteException e) {

483         }

484     }

其中的mService就是PowerManagerService類中的goToSleep方法,

 988     public void goToSleep(long eventTime, int reason) {

 989         if (eventTime > SystemClock.uptimeMillis()) {

 990             throw new IllegalArgumentException("event time must not be in the future");

 991         }

 992

 993         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);

 994

 995         final long ident = Binder.clearCallingIdentity();

 996         try {

 997             goToSleepInternal(eventTime, reason);

 998         } finally {

 999             Binder.restoreCallingIdentity(ident);

1000         }

1001     }

這個函數主要權限檢查,然後調用自己類中的goToSleepInternel方法,

1008     private void goToSleepInternal(long eventTime, int reason) {

1009         synchronized (mLock) {

1010             if (goToSleepNoUpdateLocked(eventTime, reason)) {

1011                 updatePowerStateLocked();

1012                 mDisplayPowerController.requestButtonLedState(false);

1013             }

1014         }

1015     }

goToSleepNoUpdateLocked() 和updatePowerStateLocked(),而 goToSleepNoUpdateLocked是goToSleep功能的計算者,來決定是否要休眠,而updatePowerStateLocked函數算是 功能的執行者,而且這個執行者同時負責執行了很多其他的功能, 這裡就不都貼兩段代碼了,因為太長了,下面簡單的介紹下,

goToSleepNoUpdateLocked函數的主要功能就是進行必要屬性的指派,在PowerManagerService代碼可以看到各種NoUpdateLocked這樣的字尾,都類似與goToSleepNoUpdateLocked方法,隻不過進行必要屬性更新/

updatePowerStateLocked函數

1114     private void updatePowerStateLocked() {

1115         if (!mSystemReady || mDirty == 0) {                   //檢查系統是否準備好了

1116             return;

1117         }                                                                                                                                 

1118

1119         // Phase 0: Basic state updates.                         //基本狀态更新,檢查是否插着充電器

1120         updateIsPoweredLocked(mDirty);

1121         updateStayOnLocked(mDirty);

1122

1123         // Phase 1: Update wakefulness.

1124         // Loop because the wake lock and user activity computations are influenced

1125         // by changes in wakefulness.

1126         final long now = SystemClock.uptimeMillis();

1127         int dirtyPhase2 = 0;

1128         for (;;) {

1129             int dirtyPhase1 = mDirty;

1130             dirtyPhase2 |= dirtyPhase1;

1131             mDirty = 0;

1132

1133             updateWakeLockSummaryLocked(dirtyPhase1);

1134             updateUserActivitySummaryLocked(now, dirtyPhase1);

1135             if (!updateWakefulnessLocked(dirtyPhase1)) {

1136                 break;

1137             }

1138         }

1139

1140         // Phase 2: Update dreams and display power state.                   //dream和display狀态的更新

1141         updateDreamLocked(dirtyPhase2);

1142         updateDisplayPowerStateLocked(dirtyPhase2);

1143

1144         // Phase 3: Send notifications, if needed.                                    

1145         if (mDisplayReady) {

1146             sendPendingNotificationsLocked();

1147         }

1148

1149         // Phase 4: Update suspend blocker.                                              //suspend blocker的更新

1150         // Because we might release the last suspend blocker here, we need to make sure

1151         // we finished everything else first!

1152         updateSuspendBlockerLocked();                        //真正的執行者

1153     }

這段函數看得不仔細,大概可以看出來的都表明出來了,最後updateSuspendBlockerLocked是繼續往下調用

1768     private void updateSuspendBlockerLocked() {

1769         boolean wantCpu = isCpuNeededLocked();

1770         if (wantCpu != mHoldingWakeLockSuspendBlocker) {

1771             mHoldingWakeLockSuspendBlocker = wantCpu;

1772             if (wantCpu) {

1773                 if (DEBUG) {

1774                     Slog.d(TAG, "updateSuspendBlockerLocked: Acquiring suspend blocker.");

1775                 }

1776                 mWakeLockSuspendBlocker.acquire();                                                                                        

1777             } else {

1778                 if (DEBUG) {

1779                     Slog.d(TAG, "updateSuspendBlockerLocked: Releasing suspend blocker.");

1780                 }

1781                 mWakeLockSuspendBlocker.release();

1782             }

1783         }

1784     }

其中的mWakeLockSuspendBlocker.acquire() 函數就是執行,加鎖過程,

2579         public void acquire() {                                                                                                           

2580             synchronized (this) {

2581                 mReferenceCount += 1;

2582                 if (mReferenceCount == 1) {

2583                     nativeAcquireSuspendBlocker(mName);

2584                 }

2585             }

2586         }

這個時候調用的函數nativeAcquireSuspendBlocker就是JNI接口函數,函數位置在:

frameworks/base/services/jni/com_android_server_power_PowerManagerService.cpp,這個統一編譯成libandroid_servers.so供FarmeWork使用,JNI真是個牛叉的玩意。

還沒有結束呢,早着呢,系統剛剛走了一半的路,我們繼續跟随:

JNI裡面的實作

160 static void nativeAcquireSuspendBlocker(JNIEnv *env, jclass clazz, jstring nameStr) {

161     ScopedUtfChars name(env, nameStr);

162     acquire_wake_lock(PARTIAL_WAKE_LOCK, name.c_str());                                                                                    

163 }

這個函數調用的acquire_wake_lock(PARTIAL_WAKE_LOCK, name.c_str())是真正幹活的嗎?不是的,它調用了power.c中的acquire_wake_lock(),話說我看到這個函數,好熟悉啊,終于到了底層了,這個檔案存在:

hardware/libhardware_legacy/power/power.c 這個檔案會被編譯成libpower.so。

現在我們再看看power.c中的acquire_wake_lock()實作,

 93 int

 94 acquire_wake_lock(int lock, const char* id)

 95 {

 96     initialize_fds();

 97

 98 //    ALOGI("acquire_wake_lock lock=%d id='%s'\n", lock, id);

 99

100     if (g_error) return g_error;

101

102     int fd;                                                                                                                                

103

104     if (lock == PARTIAL_WAKE_LOCK) {

105         fd = g_fds[ACQUIRE_PARTIAL_WAKE_LOCK];

106     }

107     else {

108         return EINVAL;

109     }

110

111     return write(fd, id, strlen(id));

112 }

^_^,沒錯,這個就是真正要往/sys/power/wake_lock 節點寫值的函數了,走了這一大段路,終于走到了頭?不是的,隻能說上層已經把想要幹什麼活告訴了driver,現在要輪到driver幹活了。

我們隻是簡單的分析了下,APP調用的過程,當然也有可能和系統别的子產品互動,PowerManagerService不僅可以被動接受使用者的操作請求,也可以主動的去監聽一些重要的屬性變化和重要的時間發生,在PowerManagerService主要注冊這幾個Reciver,看下

BatteryReceiver ACTION_BATTERY_CHANGED handleBatterStateChangeLocked()
BootCompleteReceiver ACTION_BOOT_COMPLETED startWatchingForBootAnimationFinished()
userSwitchReceiver ACTION_USER_SWITCHED handleSettingsChangedLocked
DockReceiver ACTION_DOCK_EVENT updatePowerStateLocked
DreamReceiver

ACTION_DREAMING_STARTED

ACTION_DREAMING_STOPPED

scheduleSandmanLocked

不管什麼接口調用最終都會是用以接口updatePowerStateLocked這個是不會變化的,因為對于JNI都是統一的,不管什麼請求,都是調用JNI提供的标準接口

Android wakelock 學習總結第一篇

上面的圖盜用網絡。

下面一篇我介紹下學習的updatePowerStateLocked() 的這個函數