編輯:關於Android編程
PowerManagerService負責Android系統中電源管理方面的工作,為了簡便我們在下文中將其簡稱為PMS。
我們先大致了解一下PMS在Android中的整體結構:

如上圖所示,可以看出PMS的對外接口是PowerManager,其通過Binder通信來調用PMS中定義的BinderService的接口。
BinderService與PowerManger之間的通信接口由IPowerManager.aidl來進行約束。
PMS由SystemServer來啟動,我們看看SystemServer.java中相關的代碼:
private void startBootstrapServices() {
..........
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
..........
}
private void startOtherServices() {
........
try {
mPowerManagerService.systemReady(mActivityManagerService.getAppOpsService());
.........
} catch (Throwable e) {
.........
}
........
}
SystemServer.java中PMS涉及的地方主要有兩處:
1、利用startService啟動PMS。
之前分析PKMS時我們已經提過,startService主要通過反射調用服務的構造函數,然後再調用服務的onStart函數。
2、調用PMS的systemReady方法。
接下來我們就分三部分,分別看看PMS的構造函數、onStart函數及systemReady函數涉及到的流程。
一、構造函數
PowerManagerService的構造函數如下所示:
public PowerManagerService(Context context) {
............
//ServiceThread繼承自HandlerThread,專門針對系統服務定義的,應該是優先級更高吧
mHandlerThread = new ServiceThread(TAG,
Process.THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
mHandlerThread.start();
mHandler = new PowerManagerHandler(mHandlerThread.getLooper());
synchronized (mLock) {
//創建一些鎖對象,同構acquire和release修改引用數
mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks");
mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display");
mDisplaySuspendBlocker.acquire();
mHoldingDisplaySuspendBlocker = true;
mHalAutoSuspendModeEnabled = false;
mHalInteractiveModeEnabled = true;
mWakefulness = WAKEFULNESS_AWAKE;
nativeInit();
nativeSetAutoSuspend(false);
nativeSetInteractive(true);
nativeSetFeature(POWER_FEATURE_DOUBLE_TAP_TO_WAKE, 0);
}
}
容易看出PMS的構造函數較為簡單,僅需要進一步分析其native函數的作用。
在com_android_server_power_PowerManagerService.cpp中:
static void nativeInit(JNIEnv* env, jobject obj) {
//創建一個全局引用對象,引用PMS
gPowerManagerServiceObj = env->NewGlobalRef(obj);
//利用hw_get_module加載底層動態庫,具體實現還是依賴與dlsym函數
status_t err = hw_get_module(POWER_HARDWARE_MODULE_ID,
(hw_module_t const**)&gPowerModule);
if (!err) {
//調用底層動態庫的init函數
gPowerModule->init(gPowerModule);
} else {
ALOGE("Couldn't load %s module (%s)", POWER_HARDWARE_MODULE_ID, strerror(-err));
}
}
static void nativeSetAutoSuspend(JNIEnv* /* env */, jclass /* clazz */, jboolean enable) {
if (enable) {
ALOGD_IF_SLOW(100, "Excessive delay in autosuspend_enable() while turning screen off");
autosuspend_enable();
} else {
ALOGD_IF_SLOW(100, "Excessive delay in autosuspend_disable() while turning screen on");
//初始時調用autosuspend_disable函數,定義於system/core/libsuspend/autosuspend.c中
//最終將調用到autosuspend_earlysuspend_disable函數,就是將底層的置為pwr_state_on的狀態
autosuspend_disable();
}
}
static void nativeSetInteractive(JNIEnv* /* env */, jclass /* clazz */, jboolean enable) {
if (gPowerModule) {
if (enable) {
ALOGD_IF_SLOW(20, "Excessive delay in setInteractive(true) while turning screen on");
//初始時,調用動態庫的setInteractive函數,目前還不確定這個函數調用後的效果
gPowerModule->setInteractive(gPowerModule, true);
} else {
ALOGD_IF_SLOW(20, "Excessive delay in setInteractive(false) while turning screen off");
gPowerModule->setInteractive(gPowerModule, false);
}
}
}
static void nativeSetFeature(JNIEnv *env, jclass clazz, jint featureId, jint data) {
int data_param = data;
if (gPowerModule && gPowerModule->setFeature) {
//初始時,調用動態庫的setFeature函數,將POWER_FEATURE_DOUBLE_TAP_TO_WAKE置為0
gPowerModule->setFeature(gPowerModule, (feature_t)featureId, data_param);
}
}
從上面的代碼可以看出,PMS的構造函數還是比較簡單的,就是創建一些基本的成員,然後利用native函數加載底層的動態庫,並設置一些狀態和標志位。
二、onStart
接下來我們看看PMS的onStart函數:
public void onStart() {
publishBinderService(Context.POWER_SERVICE, new BinderService());
publishLocalService(PowerManagerInternal.class, new LocalService());
Watchdog.getInstance().addMonitor(this);
Watchdog.getInstance().addThread(mHandler);
}
從代碼來看,onStart內容可以分成3類,即發布BinderService、發布LocalService和完成watchdog相關的工作。
我們分別看看這3類工作具體的流程。
1、publishBinderService
publishBinderService定義在PMS的父類SystemService中:
//PMS中的BinderService繼承自IPowerManager.Stub,實現了IBinder接口
//name為PMS的名稱,power
protected final void publishBinderService(String name, IBinder service) {
publishBinderService(name, service, false);
}
protected final void publishBinderService(String name, IBinder service,
boolean allowIsolated) {
//調用ServiceManger的接口,實際上利用Binder通信向Service Manger進程注冊服務
ServiceManager.addService(name, service, allowIsolated);
}
通過上述代碼,PMS就將內部定義的BinderService注冊到Service Manager進程,對應的名稱為”power”。
2、publishLocalService
publishLocalService同樣定義在PMS的父類SystemService中:
//參數中的LocalService繼承自PowerManagerInternal類 protected finalvoid publishLocalService(Class type, T service) { LocalServices.addService(type, service); }
我們來看看LocalServices類的addService函數:
/** * Adds a service instance of the specified interface to the global registry of local services. */ public staticvoid addService(Class type, T service) { synchronized (sLocalServiceObjects) { if (sLocalServiceObjects.containsKey(type)) { throw new IllegalStateException("Overriding service registration"); } sLocalServiceObjects.put(type, service); } }
從代碼來看,LocalServices的作用與單例模式有些相似,不過更為嚴格。
單例模式用於保證某個類只能創建出一個對象; LocalServices管理對象時,確保繼承某個類或接口的對象只有一個。
目前,還看不出PMS利用LocalServices管理其內部的LocalService的理由,先在此留個懸念。
3、watchdog相關工作
在之前的博客中,分析過Android 6.0中watchdog流程。
對於watchdog而言,Android 7.0與Android 6.0基本類似,這裡僅再簡單介紹一下涉及到的流程。
//PMS實現了Watchdog.Monitor接口,下面的代碼將PMS加入到watchdog的mMonitorChecker中 Watchdog.getInstance().addMonitor(this); //將PMS的ServiceThread對對應的handler傳入watchdog中,watchdog將利用該handler構造一個HandlerChecker Watchdog.getInstance().addThread(mHandler);
3.1 addThread
當PMS調用addThread時,watchDog利用mHandler構造一個HandlerChecker,然後周期性地調用HandlerChecker的scheduleCheckLocked方法:
public void scheduleCheckLocked() {
//PMS對應的HandlerChecker沒有monitor,因此mMonitors.size()恆等於0
//調用MessageQueue的isPolling函數,判斷是否處於polling狀態;
//當MessageQueue native層的looper處於等待狀態,即沒有事件需要處理時,isPolling返回true
if (mMonitors.size() == 0 && mHandler.getLooper().getQueue().isPolling()) {
mCompleted = true;
return;
}
if (!mCompleted) {
// we already have a check in flight, so no need
return;
}
mCompleted = false;
mCurrentMonitor = null;
mStartTime = SystemClock.uptimeMillis();
//HandlerChecker繼承runnable,這裡的意思是向PMS的handler發送一個HandlerChecker類型的runnable事件
mHandler.postAtFrontOfQueue(this);
}
public void run() {
final int size = mMonitors.size();
//PMS對應的HandlerChecker的mMonitors.size為0,跳過
for (int i = 0 ; i < size ; i++) {
synchronized (Watchdog.this) {
mCurrentMonitor = mMonitors.get(i);
}
mCurrentMonitor.monitor();
}
//只要PMS的mHandler在規定事件內,執行了上文傳入的runnable事件,就說明沒有阻塞,PMS是正常的
synchronized (Watchdog.this) {
mCompleted = true;
mCurrentMonitor = null;
}
}
3.2 addMonitor
當PMS調用watchDog的addMonitor函數後,watchDog就會周期性地調用PMS的monitor接口:
public void monitor() {
// Grab and release lock for watchdog monitor to detect deadlocks.
synchronized (mLock) {
}
}
PMS只要能在規定時間內獲得mLock鎖,watchDog就能確認PMS沒有死鎖,狀態正常。
以上只是簡略介紹了一下watchDog相關的內容,詳情可以參考下面的博客。
Android6.0 watchdog
三、systemReady
接下來我們看一下PMS的systemReady函數:
public void systemReady(IAppOpsService appOps) {
//這裡持鎖,意味者內部所有函數必須在規定事件內執行完畢
//否則watchDog將會檢測到錯誤
synchronized (mLock) {
mSystemReady = true;
mAppOps = appOps;
//注意下面的對象都是從LocalServices取出的,從之前PMS加入LocalServices的流程來看
//下面取出的實際上應該是繼承抽象類的實際子類
//因此大概可以理解LocalServices的作用了,以抽象類名為key,保存實際的子類
//以key取出子類對象時,子類退化為抽象類,於是得到了實際對象,但僅能利用父類的接口
//整個設計演變為面向接口的編程
//從注釋來看,與doze有關
mDreamManager = getLocalService(DreamManagerInternal.class);
//顯示管理相關
mDisplayManagerInternal = getLocalService(DisplayManagerInternal.class);
//Window管理相關
mPolicy = getLocalService(WindowManagerPolicy.class);
//電源管理相關
mBatteryManagerInternal = getLocalService(BatteryManagerInternal.class);
//這裡獲取PowerManager就是為了方便獲取下面三個系統屬性
PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mScreenBrightnessSettingMinimum = pm.getMinimumScreenBrightnessSetting();
mScreenBrightnessSettingMaximum = pm.getMaximumScreenBrightnessSetting();
mScreenBrightnessSettingDefault = pm.getDefaultScreenBrightnessSetting();
//Sensor相關
SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper());
//系統電量統計有關
mBatteryStats = BatteryStatsService.getService();
// The notifier runs on the system server's main looper so as not to interfere
// with the animations and other critical functions of the power manager.
mNotifier = new Notifier(Looper.getMainLooper(), mContext, mBatteryStats,
mAppOps, createSuspendBlockerLocked("PowerManagerService.Broadcasts"),
mPolicy);
//無線充電檢測相關
mWirelessChargerDetector = new WirelessChargerDetector(sensorManager,
createSuspendBlockerLocked("PowerManagerService.WirelessChargerDetector"),
mHandler);
mSettingsObserver = new SettingsObserver(mHandler);
//lightService相關
mLightsManager = getLocalService(LightsManager.class);
mAttentionLight = mLightsManager.getLight(LightsManager.LIGHT_ID_ATTENTION);
// Initialize display power management.
//調用DisplayManagerService內部的LocalService的函數
//創建出DisplayBlanker和DisplayPowerController
mDisplayManagerInternal.initPowerManagement(
mDisplayPowerCallbacks, mHandler, sensorManager);
//定義一堆BroadcastReceiver
..................
//利用mSettingsObserver監聽一堆數據庫字段的變化
..................
//VR相關
IVrManager vrManager =
(IVrManager) getBinderService(VrManagerService.VR_MANAGER_BINDER_SERVICE);
try {
vrManager.registerListener(mVrStateCallbacks);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to register VR mode state listener: " + e);
}
//從資源文件中讀取大量配置信息
readConfigurationLocked();
//讀取數據庫字段,保存到本地變量中
//必要時會進行一些實際的操作,例如設置feature到native層的動態庫
updateSettingsLocked();
mDirty |= DIRTY_BATTERY_STATE;
//更新全局的電源狀態
updatePowerStateLocked();
}
}
從代碼來看,PMS在systemReady中主要是獲得一些成員變量,注冊一些廣播接收對象、讀取一些配置參數等。雖然PMS會與多個服務打交道,使得systemReady內容較為龐雜,但整個過程比較簡單。
在systemReady函數的最後,調用了一個比較重要的函數updatePowerStateLocked。當PMS監控到終端發生重大變化時,將利用該函數集中更新所有相關的狀態。updatePowerStateLocked涉及的內容較多,等對PMS整體有了初步的了解後,再來分析這個函數。
總結
本篇博客側重於介紹PMS的啟動過程,同時對PMS需要打交道的服務建立一個基本的認識。
Android 有效的解決內存洩漏的問題實例詳解
Android 有效的解決內存洩漏的問題Android內存洩漏,我想做Android 應用的時候遇到的話很是頭疼,這裡是我在網上找的不錯的資料,實例詳解這個問題的解決方案
Android版九連環NingRings
喜歡九連環以及想玩九連環的小伙伴們,送福利了,Android版本的九連環小游戲上線了!!!快來嘗鮮吧,如果覺得好玩,請幫忙轉發。游戲演示及下載地址http://onest
Android自定義View——可拖拽的ListView
有時時候需要對ListView的Item進行手動拖拽排序,如安桌系統中的對通知欄的開關排序,因此需要自定義一個可拖拽的ListView,效果如下:可見,該ListView
了解Activity
依照郭霖老師的《第一行代碼Android》,今天我要來學習Activity,首先來初步了解Activity,基本上就是照葫蘆畫瓢的模式,有點回到當初敲java的hello