轉載自: 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提供的标準接口
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL0IjZwI2MhVGZ0ETO1kjM4IzY2QTMkBjZmNTMhBTM2QWL4AjM1cTMxAzLclDMzEDMy8CXwITM0ADNvw1ZvxmYvwVbvNmLn9GbiRXauNmLzV2Zh1Wavw1LcpDc0RHaiojIsJye.png)
上面的圖盜用網絡。
下面一篇我介紹下學習的updatePowerStateLocked() 的這個函數