轉寄請註明出處:
http://blog.csdn.net/codectq/article/details/7324879
最近,在學習讓系統進入休眠的過程中,學習了電源管理的相關知識。為了備忘和理清思路現整理成文,以便日後查閱。
行動裝置由於自身的限制有一個硬傷就是電量的消耗問題。由於電池的電量有限,所以電源電量的管理顯得就比較重要了。我們可以想象一下,當你去超市買完東西之後,卻發現無法運回家,是多麼難受的一件事情。
Android的電源管理是在Linux電源管理的基礎之上更好的一個電源管理方案,在這種策略下,通過Android framework層和本地的linux庫,服務和應用都通過“wake lock”來取得CPU,從而達到省電的目的。如果沒有活躍的喚醒鎖,Android將關閉CPU。
在Android 4.0 中,為上層提供的休眠函數為goToSleep()。下面詳細講解為什麼這個命令會讓系統進去睡眠模式。
首先,需要明白在Android 系統中一般會有這樣的一個檔案群,XXX.java、XXXservice.java、*XXX*.cpp、*XXX*.c。作為使用者我們首先需要瞭解的就是這個系統能夠為我們提供的服務,如果這些服務會讓我們滿意,我們才會願意為這個服務埋單。因此,在這裡我們就先從服務入手,也就是從PowerManagerService.java開始入手。在這個檔案的line2561出有goToSleep()函數的定義:
public void goToSleep(long time)
{
goToSleepWithReason(time, WindowManagerPolicy.OFF_BECAUSE_OF_USER);
}
goToSleep()函數接著調用了下面的goToSleepWithReason()函數。函數的定義如下:
public void goToSleepWithReason(long time, int reason)
{
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
synchronized (mLocks) {
goToSleepLocked(time, reason);
}
}
goToSleepLocked()函數的定義如下:
private void goToSleepLocked(long time, int reason) {
if (mLastEventTime <= time) {
mLastEventTime = time;
// cancel all of the wake locks
mWakeLockState = SCREEN_OFF;
int N = mLocks.size();
int numCleared = 0;
boolean proxLock = false;
for (int i=0; i<N; i++) {
WakeLock wl = mLocks.get(i);
if (isScreenLock(wl.flags)) {
if (((wl.flags & LOCK_MASK) == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)
&& reason == WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR) {
proxLock = true;
} else {
mLocks.get(i).activated = false;
numCleared++;
}
}
}
if (!proxLock) {
mProxIgnoredBecauseScreenTurnedOff = true;
if (mDebugProximitySensor) {
Slog.d(TAG, "setting mProxIgnoredBecauseScreenTurnedOff");
}
}
EventLog.writeEvent(EventLogTags.POWER_SLEEP_REQUESTED, numCleared);
mStillNeedSleepNotification = true;
mUserState = SCREEN_OFF;
setPowerState(SCREEN_OFF, false, reason);
cancelTimerLocked();
}
}
其中,對我們來講最有意義的函數為setPowerState()函數。此函數中調用了 setScreenStateLocked()函數
轉寄請註明出處:
http://blog.csdn.net/codectq/article/details/7324879
private int setScreenStateLocked(boolean on) {
if (DEBUG_SCREEN_ON) {
RuntimeException e = new RuntimeException("here");
e.fillInStackTrace();
Slog.i(TAG, "Set screen state: " + on, e);
}
if (on) {
if ((mPowerState & SCREEN_ON_BIT) == 0 || mSkippedScreenOn) {
// If we are turning the screen state on, but the screen
// light is currently off, then make sure that we set the
轉寄請註明出處:
http://blog.csdn.net/codectq/article/details/7324879
// light at this point to 0. This is the case where we are
// turning on the screen and waiting for the UI to be drawn
// before showing it to the user. We want the light off
// until it is ready to be shown to the user, not it using
// whatever the last value it had.
if (DEBUG_SCREEN_ON) {
Slog.i(TAG, "Forcing brightness 0: mPowerState=0x"
+ Integer.toHexString(mPowerState)
+ " mSkippedScreenOn=" + mSkippedScreenOn);
}
mScreenBrightness.forceValueLocked(Power.BRIGHTNESS_OFF);
}
}
int err = Power.setScreenState(on);
if (err == 0) {
mLastScreenOnTime = (on ? SystemClock.elapsedRealtime() : 0);
if (mUseSoftwareAutoBrightness) {
enableLightSensorLocked(on);
轉寄請註明出處:
http://blog.csdn.net/codectq/article/details/7324879
if (!on) {
// make sure button and key backlights are off too
mButtonLight.turnOff();
mKeyboardLight.turnOff();
// clear current value so we will update based on the new conditions
// when the sensor is reenabled.
mLightSensorValue = -1;
// reset our highest light sensor value when the screen turns off
mHighestLightSensorValue = -1;
}
}
}
return err;
}
轉寄請註明出處:
http://blog.csdn.net/codectq/article/details/7324879
此函數調用了Power類中的setScreenState()函數。此函數通過JNI機制,最終到達硬體層的libhardware_legacy/power/Power.c檔案通過對寄存器的操作完成對休眠的操作。在此函數中我們通過傳入的參數是on,來進行相應的處理。