轉載地址:http://blog.csdn.net/wh_19910525/article/details/8287202html
Wake Lock是一種鎖的機制, 只要有人拿着這個鎖,系統就沒法進入休眠, 能夠被用戶態程序和內核得到. 這個鎖能夠是有超時的 或者 是沒有超時的, 超時的鎖會在時間過去之後自動解鎖。若是沒有鎖了或者超時了, 內核就會啓動休眠的那套機制來進入休眠.java
PowerManager.WakeLock 有加鎖和解鎖兩種狀態,加鎖的方式有兩種:android
第一種是永久的鎖住,這樣的鎖除非顯式的放開,不然是不會解鎖的,因此這種鎖用起來要很是的當心。框架
第二種鎖是超時鎖,這種鎖會在鎖住後一段時間解鎖。函數
在建立了 PowerManager.WakeLock 後,有兩種機制,第一種是不計數鎖機制,另外一種是計數鎖機制。能夠經過 setReferenceCounted(boolean value) 來指定,通常默認爲計數機制。這兩種機制的區別在於,前者不管 acquire() 了多少次,只要經過一次 release()便可解鎖。而後者正真解鎖是在( --count == 0 )的時候,一樣當 (count == 0) 的時候纔會去申請加鎖。因此 PowerManager.WakeLock 的計數機制並非正真意義上的對每次請求進行申請/釋放每一把鎖,它只是對同一把鎖被申請/釋放的次數進行了統計,而後再去操做。ui
源碼 位置:frameworks/base/core/java/android/os/PowerManager.java
++++++++++++++++++++++++
講述 應用層 申請的鎖 怎麼傳到kernel下面的,來理解
整個wakelock的框架。
好比android跑起來以後 在 /sys/power/wake_lock 下面的PowerManagerService
的生成過程。
1).應用程序申請鎖
Android 提供了現成 android.os.PowerManager 類 , 類中
提供newWakeLock(int flags, String tag)方法 來取得應用層
的鎖, 此函數的定義
frameworks/base/core/java/android/os/PowerManager.java
應用程序 在申請wake_lock時 都會有調用如下 部分。
實例:
PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, 「MyTag」);
wl.acquire();//申請鎖,這裏會調用PowerManagerService裏面acquireWakeLock()
***********************
wl.release(); //釋放鎖,顯示的釋放鎖,若是申請的鎖不在此釋放,系統就不會進入休眠。
======================================
2). frameworks層
/frameworks/base/services/java/com/android/server/PowerManagerService.java
這個類是來管理 全部的應用程序 申請的wakelock。好比音視
、頻播放器、camera等申請的wakelock 都是經過這個類來 管理的。
static final String PARTIAL_NAME ="PowerManagerService"
nativeAcquireWakeLock
(PARTIAL_WAKE_LOCK_ID, PARTIAL_NAME);
上面 這個函數調用Power
類 裏面的 acquireWakeLock(),此時的
PARTIAL_NAME做爲參數傳遞到底層去。
public static native void nativeAcquireWakeLock(int lock, String id);
注:在PowerManagerService
類中沒有實現nativeAcquireWakeLock,其實現體在
frameworks/base/core/jni/android_os_Power.cpp中,所
以nativeAcquireWakeLock()方法時會調用JNI
下的實現方法。
3).JNI層的實現
路徑:frameworks/base/core/jni/android_os_Power.cpp //
static void acquireWakeLock(JNIEnv *env, jobject clazz,
jint lock, jstring idObj)
{
**************
const char *id = env->GetStringUTFChars(idObj, NULL);
acquire_wake_lock(lock, id);
env->ReleaseStringUTFChars(idObj, id);
}
注:在acquireWakeLock()中調用了
路徑下hardware/libhardware_legacy/power/power.c下面
的acquire_wake_lock(lock, id)
4).與kernel層的交互
在power.c下的acquire_wake_lock(lock, id)函數以下:
int acquire_wake_lock(int lock, const char* id)
{
**************
return write(fd, id, strlen(id));
}
注: fd就是文件描述符,在此 表示」/sys/power/wake_lock」
id就是從PowerManagerService類中傳下來的參數即:
PARTIAL_NAME = "PowerManagerService"
到此 就是經過 文件系統 來與kernel層 交互的地方。
+++++++++++++++++++++++++++++++++++++++++++++++++++++spa
PowerManager類被應用程序調用,控制電源設備狀態切換:.net
PowerManager類對外有三個接口函數:code
一、void goToSleep(long time); //強制設備進入Sleep狀態server
Note:在應用層調用該函數, 應用須要 在 源碼下編譯,用系統簽名,不然 調用 此函數 出錯;
二、newWakeLock(int flags, String tag);//取得相應層次的鎖
flags參數說明:
PARTIAL_WAKE_LOCK :保持CPU 運轉,屏幕和鍵盤燈是關閉的。
SCREEN_DIM_WAKE_LOCK :保持CPU 運轉,容許保持屏幕顯示但有多是灰的,關閉鍵盤燈
SCREEN_BRIGHT_WAKE_LOCK :保持CPU 運轉,保持屏幕高亮顯示,關閉鍵盤燈
FULL_WAKE_LOCK :保持CPU 運轉,保持屏幕高亮顯示,鍵盤燈也保持亮度
ACQUIRE_CAUSES_WAKEUP: 一旦有請求鎖時,強制打開Screen和keyboard light
ON_AFTER_RELEASE: 在釋放鎖時reset activity timer
Note:
若是申請了partial wakelock,那麼即便按Power鍵,系統也不會進Sleep,如Music播放時
若是申請了其它的wakelocks,按Power鍵,系統仍是會進Sleep
三、void userActivity(long when, boolean noChangeLights);//User activity事件發生,設備會被切換到Full on的狀態,同時Reset Screen off timer.
PowerManager和WakeLock的操做步驟
- PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);經過
Context.getSystemService()
.方法獲取PowerManager實例。
- 而後經過PowerManager的newWakeLock ((int flags, String tag)來生成WakeLock實例。int Flags指示要獲取哪一種WakeLock,不一樣的Lock對cpu 、屏幕、鍵盤燈有不一樣影響。
- 獲取WakeLock實例後經過acquire()獲取相應的鎖,而後進行其餘操做,最後使用release()釋放(釋放是必須的)。
Note:
1. 在使用以上函數的應用程序中,必須在其Manifest.xml文件中加入下面的權限:
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.DEVICE_POWER" />
2. 全部的鎖必須成對的使用, 若是申請了而沒有及時釋放,會形成系統故障。如申請了partial wakelock,而沒有及時釋放, 那系統就永遠進不了Sleep模式.