1. 程式人生 > >(原創)android PowerManager分析(十分詳細)

(原創)android PowerManager分析(十分詳細)

http://www.myexception.cn/android/2076061.html

(原創)android PowerManager分析(非常詳細)

概述

一直以來,電源管理是電子產品設計中非常重要的環節,也是任何電子裝置中最為重要的系統模組之一,優秀的電源管理方案,能夠提供持久的續航能力,良好的使用者體驗,更能提升電子產品的競爭力。

移動裝置的電量主要由兩種元件消耗:CPU和顯示屏,因此設法降低這兩種元件的耗電量就是電源管理的關鍵,為移動裝置設計的CPU大多有兩種工作頻率,為了省電,大部分時間內cpu都工作在降低頻率下,只有進行密集計算時,如視訊解碼才會切換到高頻狀態,而顯示屏省電的方法是儘量減少亮屏時間,但是顯示屏的開關和應用有很大的關係,因此係統中需要有一套機制來控制顯示屏的開關和亮度,這也是電源管理的主要工作。

電源管理架構

Android的電源管理主要是通過wakelock機制管理系統的狀態,整個android電源管理,可以分為四個層次:應用介面層(PowerManager.java),Framework層(PowerManagerService.java),HAL層(Power.c),和核心層(kernel/Power)。

應用介面層:PowerManager中開放給應用一系列介面,應用可以呼叫PM的介面申請wakelock,喚醒系統,使系統進入睡眠等操作;

Framework層:應用呼叫PowerManager開放的介面,來對系統進行一些列的操作是在PowerManagerService中完成的,PowerManagerService計算系統中和Power相關的計算,是整個電源管理的決策系統。同時協調Power如何與系統其它模組的互動,比如亮屏,暗屏,系統睡眠,喚醒等等。

HAL層:該層只有一個power.c檔案,該檔案通過上層傳下來的引數,向/sys/power/wake_lock或者/sys/power/wake_unlock檔案節點寫資料來與kernel進行通訊,主要功能是申請/釋放鎖,維持螢幕亮滅

Kernel層:核心層實現電源管理的方案主要包含三個部分:

1、Kernel/power/:實現了系統電源管理框架機制。

2、Arch/arm(ormips or powerpc)/mach-XXX/pm.c:實現對特定板的處理器電源管理。

3、drivers/power:是裝置電源管理的基礎框架,為驅動提供了電源管理介面。

Android電源管理框架如下圖

電源管理服務——PowerManagerService

PowerManagerServcie是android系統電源管理的核心服務,它在Framework層建立起一個策略控制方案,向下決策HAL層以及kernel層來控制裝置待機狀態,控制顯示屏,背光燈,距離感測器,光線感測器等硬體裝置的狀態。向上提供給應用程式相應的操作介面,比如聽音樂時持續保持系統喚醒,應用通知來臨喚醒手機螢幕等場景

啟動過程

SystemServer在系統啟動的時候會啟動三類服務:引導關鍵服務,核心服務,其他服務;PowerManagerService是在SystemServer中建立的,並將其作為一個系統服務加入到ServiceManager中:

mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);

在啟動引導關鍵服務呼叫startBootstrapServices(),其中各種服務都是通過SystemServiceManager中的startService()函式來啟動:

public <T extends SystemService> T startService(Class<T> serviceClass) {

final String name = serviceClass.getName();

final T service;

            Constructor<T> constructor = serviceClass.getConstructor(Context.class);

            service = constructor.newInstance(mContext);

mServices.add(service);//註冊服務到服務列表中去

service.onStart();//啟動服務

}

在啟動PowerManagerService時,傳入的引數類是PowerManagerService,在startService()中首先呼叫PowerManagerService的建構函式,然後呼叫其onStart()函式

PowerManagerServcie的建構函式:

mHandler = new PowerManagerHandler(mHandlerThread.getLooper());synchronized (mLock) {mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks");mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display");mDisplaySuspendBlocker.acquire();

mWakefulness = WAKEFULNESS_AWAKE;

nativeInit(); 

建立一個處理訊息和傳送訊息的執行緒mHandler,並且兩種標誌flag的wakelock鎖PowerManagerService.WakeLocksPowerManagerService.Display,前者是傳入到底層是控制cpu喚醒狀態,後者則是控制螢幕亮滅。在建構函式最後呼叫nativeInit();在native層初始化相關資源。將mWakefulness 置成WAKEFULNESS_AWAKE狀態,mWakefulness 標識系統當前狀態共有四種定義:

WAKEFULNESS_ASLEEP:表示系統當前處於休眠狀態,只能被wakeUp()呼叫喚醒。

WAKEFULNESS_AWAKE:表示系統目前處於正常執行狀態。

WAKEFULNESS_DREAMING:表示系統當前正處於屏保的狀態。

WAKEFULNESS_DOZING:表示系統正處於“doze”狀態。這種狀態下只有低耗電的“屏保”可以執行,其他應用程序都被掛起。

在SystemServer中startService中呼叫到PowerManagerService建構函式做完初始化操作之後便會呼叫PowerManagerService的onStart()函式:

publishBinderService(Context.POWER_SERVICE, new BinderService());

publishLocalService(PowerManagerInternal.classnew LocalService());

        Watchdog.getInstance().addMonitor(this);

        Watchdog.getInstance().addThread(mHandler);

Onstart完成的工作就是將POWER_SERVICE作為Binder的服務端,註冊到SystemService中去;將PowerManagerInternal註冊到本地服務中,將自己加到watchdog的監控佇列中去;將之前在建構函式中建立的mHandler物件加入到watchdog的中,用於監視mHandler的looper是否空閒;

系統準備工作

SystemServer在呼叫PowerManagerService之後還會呼叫其SystemReady相當於在系統準備就緒後對PowerManagerService再進行一些初始化工作。SystemReady()方法程式碼如下:

mAppOps = appOps;

mDreamManager = getLocalService(DreamManagerInternal.class);

mDisplayManagerInternal = getLocalService(DisplayManagerInternal.class);

mPolicy = getLocalService(WindowManagerPolicy.class);

mBatteryManagerInternal = getLocalService(BatteryManagerInternal.class);

PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);

mScreenBrightnessSettingMinimum = pm.getMinimumScreenBrightnessSetting();

mScreenBrightnessSettingMaximum = pm.getMaximumScreenBrightnessSetting();

mScreenBrightnessSettingDefault = pm.getDefaultScreenBrightnessSetting();

獲取與PowerManager相關的本地服務,比如屏保(mDreamManager),螢幕顯示(mDisplayManagerInternal),視窗策略(mPolicy),電池電量(mBatteryManagerInternal)等服務,然後初始化螢幕最大亮度,最小亮度,和預設亮度;

SensorManager sensorManager = new SystemSensorManager(mContextmHandler.getLooper());

mBatteryStats = BatteryStatsService.getService();

mNotifier new Notifier(Looper.getMainLooper(), mContextmBatteryStats,mAppOps, createSuspendBlockerLocked("PowerManagerService.Broadcasts"),mPolicy);

mWirelessChargerDetector new WirelessChargerDetector(sensorManager,        createSuspendBlockerLocked("PowerManagerService.WirelessChargerDetector"), mHandler);

mSettingsObserver new SettingsObserver(mHandler);

mLightsManager = getLocalService(LightsManager.class);

mAttentionLight mLightsManager.getLight(LightsManager.LIGHT_ID_ATTENTION);

建立sensorManager 物件,用於與sensor互動,比如距離感測器,光線感測器,加速度感測器(doze上使用)。獲取電池狀態服務,和背光服務;

建立mNotifier 物件,在通過mNotifier 傳送通知時候,會傳入底層申請PowerManagerService.Broadcasts的wakelock鎖。

建立mSettingsObserver 監聽系統設定變化,比如亮屏時間,自動背光,螢幕亮度,屏保,低電模式等等

總而言之在SystemReady方法中完成的主要工作如下:

獲取與PowerManagerServcie相關的系統服務以及本地服務;

獲取螢幕最大,最小以及預設亮度值;

建立SensorManager 物件,用於和SensorService互動;

建立Notifier物件,用於通知系統中電源狀態的改變;

建立WirelessChargerDetector物件,用於檢測無線充電的感測器(市面上支援的手機較少)

呼叫DisplayManagerService的initPowerManagement()方法來初始化Power顯示模組。

註冊SettingsObserver監聽系統設定的變化

PowerManagerServcie的啟動初始化過程如下:

相關介面

PowerManager嚮應用提供了相應的介面,以供應用程式呼叫,來改變系統待機狀態,螢幕狀態,螢幕亮度等,PowerManager是PowerManagerService的代理類,PowerManager向上層應用提供互動的介面,具體的處理工作在PowerManagerService中完成。下面介紹PowerManager中提供的相應介面作用:

Wakeup():強制系統從睡眠狀態喚醒,此介面對應用是不開放的,應用想喚醒系統必須通過設定亮屏標誌(後面即將講到);

gotoSleep():強制系統進入到睡眠狀態,此介面也是應用不開放。

userActivity():向PowerManagerService報告影響系統休眠的使用者活動,重計算滅屏時間,背光亮度等,例如觸屏,劃屏,power鍵等使用者活動;

Wakelock:wakelock是PowerManager的一個內部類,提供了相關的介面來操作wakelock鎖,比如newWakeLock()方法來建立wakelock鎖,acquire()和release()方法來申請和釋放鎖。

isDeviceIdleMode():返回裝置當前的狀態,如果處於Idle狀態,則返回true,Idle狀態是在手機長時間沒有被使用以及沒有運動的情況下,手機進入到一種Doze低功耗的模式下,這種狀態下手機可能會關掉網路資料訪問,可以通過監視DEVICE_IDLE_MODE_CHANGED這個廣播資訊,來監控手機狀態的改變

喚醒——wakeup

PowerManager的wakeup介面屬性是@hide的,所以對於上層應用是不可見的,上層應用要喚醒系統大都依靠兩種方式:1.在應用啟動Activity時候設定相應的window的flags,通過WMS來喚醒系統;2.在應用申請wakelock鎖時附帶ACQUIRE_CAUSES_WAKEUP標誌;

Wakeup流程如下圖所示

PowerManager的wakeup介面,可供應用程式呼叫,來強制喚醒系統,如果該裝置處於睡眠狀態,呼叫該介面會立即喚醒系統,比如按Power鍵,來電,鬧鐘等場景都會呼叫該介面。喚醒系統需要android.Manifest.permission#DEVICE_POWER的許可權;

我們來看看PowerManagerServcie中wakeup介面的程式碼:

mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWERnull);

相關推薦

原創android PowerManager分析十分詳細

http://www.myexception.cn/android/2076061.html (原創)android PowerManager分析(非常詳細) 概述 一直以來,電源管理是電子產品設計中非常重要的環節,也是任何電子裝置中最為重要的系統模

android aidl 分析PowerManager

1: 每個aidl檔案都會有一個對應的java檔案(自動生成) 2:實現了PowerManager.Stub具體介面的IBinder服務    PowerManagerService.java中IBinder服務      private

Android多媒體分析MediaScanner

Android平臺上的媒體檔案管理和桌面系統不同。在桌面系統上,不同目錄下的媒體檔案呈樹狀結構顯示給使用者,使用者需要進入不同目錄尋找該目錄下的檔案。而在Android平臺上,不同目錄下的媒體檔案

Android ApiDemo分析--Graphics

這個Demo演示了對圖片的一些操作以及基本的繪圖方式; 相關內容: 在Android要繪製一個東西,需要四個部分:一個Bitmap用於儲存畫素值,一個Canvas用於定義繪圖操作,一個Paint定義繪圖使用的顏色,畫筆,畫刷等屬性,最後一個是要繪製的圖形本身(如矩形,線段等)。 1、Bitmap - 稱作點陣

原創】docker原始碼分析2---docker server

上一節,分析了Engine和job。那這一節就開始講下docker server。 1、docker server 1.1 主體流程 我們從main函式開始,看看docker server

Android Scroll分析滑動效果產生分析

滑動一個View,本質上來說就是移動一個View。改變其當前所處的位置,它的原理與動畫效果的實現非常相似,都是通過不斷地改變View的座標來實現這一效果。所以,要實現View的滑動,就必須監聽使用者觸控的事件,並根據事件傳入的座標,動態且不斷地改變View的座標

Android多媒體分析MediaStore

1 publicclass MainActivity extends Activity { 2 private ImageView image; 3 private Button btn; 4 privateint index; 5 privateint totalCount; 6 private

Android Scroll分析

1.滑動一個view,實質上就是移動一個view,改變其所處的位置,原理與動畫效果的實現非常相似,都是通過不斷的改變view的座標來實現這一效果。所以要實現view的滑動,就必須監聽使用者的觸控事件,並且根據事件傳入的座標,動態且不斷的改變view的座標,從而實

android fsck_msdos 分析:目錄項

其實寫完前面的關於FAT檔案系統的簇檢查那一部分之後,我一直沒準備寫第二部分關於檔案目錄項處理這一部分,因為這部分都是按照FAT規範來處理的。 handleDirTree(int dosfs, struct bootblock *boot, struct fatEnt

原創】docker原始碼分析1---框架與engine

原始碼為docker 1.6.2版本 為啥要用1.6.2版本,這是因為我買了一本書《Docker容器與容器雲》,這本書裡面也是用的1.6.2版本。 一邊可以學習這本書,一邊研究原始碼,事半功

Android Camera Subsystem 架構Binder機制及顯示分析3

Camera Display 對於AP層使用者,通過Camera介面, 以最直觀的方式能夠從Camera顯示視窗中看到的Camera Display主要包括三部分。各部分的具體細節如下所示。 (1)Camera Preview Display 對於Camera Pre

Android核心分析28-----Android GDI之Surface&Canvas

Surface&Canvas     Canvas為在畫布的意思。Android上層的作圖幾乎都通過Canvas例項來完成,其實Canvas更多是一種介面的包裝。drawPaints ,drawPoints,drawRect,drawBitmap ... 1

HTTP的請求方法一共有9種,有OPTIONS, HEAD, GET, POST等等消息頭有圖,十分清楚

ram () 哪些 ive 十分 enc set utf-8 cat 請求方法:指定了客戶端想對指定的資源/服務器作何種操作 下面我們介紹HTTP/1.1中可用的請求方法: 【GET:獲取資源】 GET方法用來請求已被URI識別的資源。指定的資源經服務器端解析後返

Fidder詳解-抓取HTTPS清求Web/App抓包分析靠譜篇

可能 clas 請求 設置代理 cer port 關閉 lan str 為什麽要學Fidder抓包? 學習接口,必須要學http協議,不要求您對協議的掌握有多深。只是希望你能夠了解什麽是協議、協議的報文、狀態碼等等!本文通過抓包工具Fidder帶你進入接口的大門。我們通過

高精度六軸平臺Hexapod platform逆運動學分析部分運動模擬

import numpy as np import matplotlib.pyplot as plt plt.figure(1) plt.ion() # Input the desired position and rotation of he platform p = np.array

高精度六軸平臺Hexapod platform逆運動學分析簡介

一、簡介: Hexapod robot代指一種蜘蛛型機器人,Hexapod platform代指有六個移動關節(Prismatic joint)的高精度平臺,這裡我們研究的是後者。 Hexapod platform的概念最初由D.stewart 在其1965年的論文《A platform

吳恩達機器學習十二主成分分析降維、PCA

目錄 0. 前言 學習完吳恩達老師機器學習課程的降維,簡單的做個筆記。文中部分描述屬於個人消化後的理解,僅供參考。 如果這篇文章對你有一點小小的幫助,請給個關注喔~我會非常開心的~ 0. 前言 資料的特徵數量,又稱作向量的維度。降維(dimens

sdk manager閃退因為在Android Studio中更新sdk後

網上的find_java.bat等懷疑JAVA路徑,測試後發現自己的路徑沒有問題。 原因:AndroidStudio中操作sdk manager,對SDK資料夾中的tools檔案進行了重新的整理分化,導致tools資料夾中的檔案不完整導致。 解決方案: 找到以

QT 貪吃蛇簡單程式碼實現原創用於理解原理,請勿隨意傳播

main.cpp  #include "mainwindow.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); M

資料結構與演算法——複雜度分析

資料結構與演算法(一)—— 複雜度分析(上) 基礎知識就像是一座大樓的地基,只有打好基礎,才能造成萬丈高樓。資料結構與演算法是一個程式設計師的內功,只有基礎足夠紮實,才能有效提高自己的技術能力,寫出更高效、擴充套件性更好的優秀程式碼。寫這個系列記錄一下自己學習的