Android系統“資源調度框架”
一、一些問題的思考
“資源”是什么
計算機基礎中提到,一套完整的計算機系統有三部分組成:應用程序、操作系統(OS)和計算機的硬件。
其中硬件又可分五大組成:控制器(CU)、運算器(ALU)、存儲器(Memory)、輸入設備(Input)和輸出設備(Output)。
本文提到的“資源”指硬件的性能資源,所闡述的問題就是程序運行時分配到的硬件資源。
比如cpu的大小核心及數量,比如cpu、gpu、ddr、flash的運行頻率。
“資源”和性能有什么關系
簡單理解以cpu為例。程序的執行最終反映為cpu運行機器碼,cpu時鍾頻率越高,相同時間內執行的語句就越多,自然程序運行越快。
如此就讓人感覺到“性能”更強。
為什么需要資源調度
下面是兩個生活化場景,可以思考一下。
1、同樣一款游戲,同樣的畫質幀率設置下為啥有的機器卡卡的,有的比較流暢。
2、同樣的一款游戲,為啥換什么配置的機器都感覺一個樣。一樣卡或者一樣流暢。
開發者(系統廠商和應用開發者)有一致的目標:讓應用程序流暢運行。但是應用直接操作控制cpu、gpu等硬件是不被允許的。
aosp中,cpu、gpu的資源調度默認還是內核在控制,系統框架間接控制。默認的策略考慮的是通用性,安全性。
但是現實針對具體的性能場景,往往需要更加精細的資源調度,這樣在同樣的硬件基礎上能更充分的利用硬件資源提升用戶體驗。而不是“一核有難多核圍觀”

誰(進程)涉及到調度資源?
考慮以下典型場景
1、輸入交互場景:cpu提頻保證輸入交互流暢
2、應用/游戲啟動場景:cpu提頻甚至綁定大核心,分配更多算力加速啟動
3、下載時文件讀寫場景:提升flash頻率,加速IO
4、游戲關鍵時刻:cpu、gpu提頻,重點分配游戲進程
5、系統資源不夠了:app得知資源不夠主動裁減某些任務負載(比如降低畫質),來保證自己的重要任務流暢
1和2平台系統側來觸發資源調度是比較合理的,但是3、4、5場景顯然app才好知道,自己什么時候讀寫文件,什么時候游戲爆發團戰,什么時候自己太猛讓cpu、gpu快撐不住了,比如主動降低自己的畫質保證流暢度。
從這兩種角度來看,我們可以得知,資源調度、性能調優需要系統和應用的共同努力。系統和應用均需要獲得資源調度接口。
現狀是?
- AOSP
aosp在性能優化上不斷進步,但是目前為止還是沒有一套硬件的資源調度框架供給fwk與app,了解到的只有Framework中Powermanager#powerHint接口。
- 芯片廠商
芯片廠商在自己的平台上提供了基礎的資源調度框架,像高通的perfLock,MTK的PerfService,提供了基礎的cpu、gpu資源調度入口。
但這僅針對他們自己的芯片硬件如cpu、gpu。不包含其他廠商的硬件資源例如存儲flash,並且是系統級別的接口,是給手機廠商用的,沒有針對第三方應用提供一套SDK方案。
並且芯片平台之間這些框架是不通用的哈哈哈。
-
結論
aosp和芯片廠商release出的代碼,目前沒有現成的一套體系,讓系統框架或app來控制底層硬件運行性能,包括不限於cpu,gpu,內存,io,網絡。
手機廠商實現一套自己的資源調度框架是必選項。
我們的需求
從上面的問題以及思考、討論中,使得我們的需求,訴求輪廓逐漸清晰:直接控制系統資源,直接獲取系統運行狀態。
我們要控制cpu的頻率及運行的核心
我們要控制gpu的頻率
我們要控制ddr、Flash的頻率
我們要得知當前系統的壓力
構思一下軟件架構
系統進程和app進程都要用,java和native都要用。
那么要給app提供sdk,比如ndk、java lib的編譯依賴
要給系統框架提供系統服務接口,java系統服務和native系統服務。
由於本架構是用於溝通硬件的,所以fwk里僅做鑒權和請求簡單分解,真正的實現最好放到native或者更進一步放到內核里,避免java層native層多份實現
為了時效性可以整到單獨的進程里,而不是放在system_server中。
下圖是個示意圖

圖:資源調度軟件架構示意圖
有了這套資源調度框架,就能直接控制cpu等系統資源和接收系統狀態了。
需要考慮接口的可移植性,不同芯片平台之間、不同android版本之間。除了目前常用的,還要對其他未來可能的硬件資源創造方便的增刪接口。
還需要考慮到鑒權和策略控制,誰可以用和什么情況下允許用、時長頻次等兜底策略。
二、目前國內手機廠商的做法調查
當前時間:2021-07
你抄我呀,我抄你,友商之間甜蜜蜜。
ov米差不多,華為只提供c的api。
然后ov米的接口風格是做的更少,直接把提頻綁核放權給應用。而華為選擇做的更多,給應用的是設置幀率、設置場景這種概念性接口,真正分配多少硬件資源由系統決定。
下面一起來瞅一瞅。
華為-計算加速服務-性能加速庫
官網鏈接:華為計算加速服務
華為計算加速服務(HUAWEI Accelerate Kit,簡稱Acc Kit)支持多線程庫和性能加速庫,可實現高效的多線程加速能力和性能加速能力。
性能加速庫是Acc Kit中的性能加速模塊,它為您提供了設置顯示幀率、設置關鍵線程、監聽系統狀態等硬件能力相關的接口。性能加速庫允許您深度參與華為硬件平台的性能調度,使您能夠更有效地利用華為平台的硬件能力。通過性能加速庫自主控制性能參數,可使硬件響應更及時、更准確,能有效解決應用在部分場景的卡頓、掉幀等問題,同時又避免了低負載場景的性能過剩,最大程度提升整機能效比。
場景介紹
| 典型場景 | 策略描述 |
|---|---|
| 高負載場景 | 游戲渲染場景下,通過設置關鍵線程保證用戶線程的資源調度優先級,使得用戶添加的線程優先被系統調用。 |
| 負載突變場景 | 通過系統性能監控接口,您更容易預知負載變化,及時通知硬件提高刷新率,使應用啟動更快,游戲運行更流暢。 |
| 低刷新率場景 | 導航場景,通知硬件降低刷新率,切換到導航內動畫時及時提高刷新率,在不影響用戶體驗情況下維持較低功耗。 |
| 混合場景 | 普通應用內視頻播放場景中降低刷新率,滑動時提高刷新率,獲取最佳效果和能效比。 |
PerfGeniusApi
Public Constructor Summary
Public Destructor Summary
Public Method Summary
PerfGeniusApi
~ PerfGeniusApi
Init
GetApiVersion
SetFrameRate
ResetFrameRate
GetCurrentFrameRate
GetSupportedFrameRate
SetScene
GetPerformanceLevel
AddKeyThreads
RemoveKeyThreads
RegisterSystemEventCallback
UnRegisterSystemEventCallback
RegisterPerformanceTracer
UnRegisterPerformanceTracer
GetPerfGeniusApiHandle
DeletePerfGeniusApiHandle
小米-應用加速器(MiBridge)
官網鏈接:應用加速器(MiBridge)介紹
框架

MiBridge是提供給應用接入到系統的一個接口
• 輕量級,JAR包,大小只有幾kb。
• 低成本,與系統間連接采用Binder通信機制
API
boolean checkDebugPermission(Context context, String pkg, int uid, String auth_key)
boolean checkPermission(String pkg, int uid)
int requestCpuHighFreq(int uid, int level, int timeoutms)
int cancelCpuHighFreq(int uid)
int requestThreadPriority(int uid , int req_tid, int timeoutms)
int cancelThreadPriority (int uid , int req_tid)
requestGpuHighFreq,requestIOHighFreq,requestMemory,requestNetwork等
OPPO-HyperBoost
官網鏈接:HyperBoost介紹
應用場景
1)系統資源調度:關鍵使用場景下通知系統及時分配合理資源,保證應用流暢運行。
2)4D振感:支持多種精細的線性馬達波形振感,開發者可以通過傳入波形序號直接調用振動,帶來更精彩的應用體驗。
3)智能幀率(敬請期待):根據應用場景智能調節幀率,動態調整幀率策略,預防卡頓。
工作原理框架

通用接口說明
| API原型 | API說明 |
|---|---|
| public HyperBoostUnitClient getHyperBoostClient(Context context) | 功能:初始化SDK,過程中完成鑒權和回執 參數:context:傳入Activity上下文 |
| public int getVersion() | 功能:獲取SDK版本號,如1.0.1 sdk的版本號為100001 |
| public boolean registerClient() | 功能:初始化HyperBoost引擎,需要在鑒權成功回調中使用 |
| public boolean registerNotifier(HyperBoostCallback callback) | 功能:注冊溫控警報回調 參數:callback:用於溫控回調的標准接口類實現 |
| public boolean specificAction(String info) | 功能:針對應用特調優化場景預留接口,適用於商務對接過的三方應用,雙方協定優化方案和通信協議,調用此接口通知服務端 參數:info:用於雙方特調優化的通信的協議內容 |
普通應用接口說明
| API原型 | API說明 |
|---|---|
| public boolean appBootCompleted() | 功能:應用冷啟動時手機系統默認會有一段時間的加速,APP啟動邏輯完成時若調用該接口通知系統,手機系統恢復一般狀態,可以減少系統功耗。 |
| public boolean appActionLoading(int loadTime, int level) | 功能:在應用加載等重負載場景下,調用此接口可以將系統性能在一定時間內拉高,為應用分配更大的系統資源,減少用戶等待。為防止濫用造成功耗問題,單次調用最長加速時長為10秒,調用間隔最短為30秒。 參數: loadTime:CPU提頻時長,單位ms,最大有效值10000 level:提頻等級,分為三級,提頻力度依次遞增,應用按需調用。 可傳入參數: HyperBoostCommonUtil.CPU_BOOST_LEVEL_COMMON; HyperBoostCommonUtil.CPU_BOOST_LEVEL_HIGH; HyperBoostCommonUtil.CPU_BOOST_LEVEL_STRONG; |
| public boolean appActionBurst(int burstTime, int level) | 功能:對於短時間內負載較大的操作,可調用此接口,短時間內將CPU性能拉高。防止濫用造成功耗問題,單次調用最長加速時長為1秒,調用間隔最短為3秒。 參數: burstTime:CPU提頻時長,單位ms,最大有效值1000 level:同appActionLoading方法 |
| public boolean appActionDdr(int burstTime, int level) | 功能:短時間內提高內存讀寫速度和傳輸效率。防止濫用造成功耗問題,單次調用最長加速時長為1秒,調用間隔最短為3秒。 參數:burstTime:DDR提頻時長,單位ms,最大有效值1000 level:暫不生效,可默認傳HyperBoostCommonUtil.DDR_BOOST_LEVEL_COMMON; |
| public boolean appActionGpu(int burstTime, int level) | 功能:短時間內拉高GPU工作頻率,適用於應用畫面渲染、頁面切換等場景。防止濫用造成功耗問題,單次調用最長加速時長為1秒,調用間隔最短為3秒。 參數: burstTime:GPU提頻時長,單位ms,最大有效值1000 level:暫不生效,可默認傳HyperBoostCommonUtil.GPU_BOOST_LEVEL_COMMON; |
| public boolean appActionEnd() | 功能:標識應用重負載場景結束,暫時不需要性能提升,系統將恢復正常狀態,降低功耗。 |
| public boolean appActionBind(int tid, boolean isBind) | 功能:傳入線程id,系統將保障該線程運行在大核或超大核上。適用於應用負載較重,耗時較長的線程場景,如音視頻類應用的視頻編解碼線程。 參數: tid: 需要綁定大核的線程id,需傳入android系統級線程id isBind:傳入HyperBoostCommonUtil.BIND_GOLD_CORE表示綁定大核,傳入HyperBoostCommonUtil.UNBIND_GOLD_CORE表示解綁大核; |
游戲應用接口說明
| API原型 | API說明 |
|---|---|
| public boolean gameBootCompleted() | 功能:游戲冷啟動時手機系統默認會有一段時間的加速,游戲啟動邏輯完成時若調用該接口通知系統,手機系統恢復一般狀態,可以減少系統功耗。 |
| public boolean gameSceneStart() | 功能:標識游戲開始。為了保持游戲期間性能穩定,通過調用該接口通知手機系統已正式開始打游戲,這時手機系統會開啟觸摸屏靈敏度優化、自動追幀等優化策略,從而使游戲性能更加穩定 |
| public boolean gameSceneEnd() | 功能:標識游戲結束。在游戲結束或者回到游戲大廳時調用該接口,這時手機系統會關閉上述的觸摸屏優化等優化策略,從而減少不必要的功耗,提升手機續航。 |
| public boolean gameActionLoading(int loadTime, int level) | 功能:在游戲地圖加載等重負載場景下,調用此接口可以將系統性能在一定時間內拉高,為應用分配更大的系統資源,減少用戶等待。為防止濫用造成功耗問題,單次調用最長加速時長為30秒,調用間隔最短為60秒。 參數: loadTime:CPU提頻時長,單位ms,最大有效值30000 level:提頻等級,分為三級,提頻力度依次遞增,應用按需調用。 可傳入參數: HyperBoostCommonUtil.CPU_BOOST_LEVEL_COMMON; HyperBoostCommonUtil.CPU_BOOST_LEVEL_HIGH; HyperBoostCommonUtil.CPU_BOOST_LEVEL_STRONG; |
| public boolean gameActionBurst(int burstTime, int level) | 功能:對於短時間內負載較大的操作,可調用此接口,短時間內將CPU性能拉高。防止濫用造成功耗問題,單次調用最長加速時長為1秒,調用間隔最短為3秒。 參數: burstTime:CPU提頻時長,單位ms,最大有效值1000 level:同appActionLoading方法 |
| public boolean gameActionDdr(int burstTime, int level) | 功能:短時間內提高內存讀寫速度和傳輸效率。防止濫用造成功耗問題,單次調用最長加速時長為1秒,調用間隔最短為3秒。 參數: burstTime:DDR提頻時長,單位ms,最大有效值1000 level:暫不生效,可默認傳HyperBoostCommonUtil.DDR_BOOST_LEVEL_COMMON; |
| public boolean gameActionGpu(int burstTime, int level) | 功能:短時間內拉高GPU工作頻率,適用於游戲畫面渲染、頁面切換等場景。防止濫用造成功耗問題,單次調用最長加速時長為1秒,調用間隔最短為3秒。 參數: burstTime:GPU提頻時長,單位ms,最大有效值1000 level:暫不生效,可默認傳HyperBoostCommonUtil.GPU_BOOST_LEVEL_COMMON; |
| public boolean gameActionEnd() | 功能:標識游戲重負載場景結束,暫時不需要性能提升,系統將恢復正常狀態,降低功耗。 |
| public boolean gameActionBind(int tid, boolean isBind) | 功能:傳入線程id,系統將保障該線程運行在大核或超大核上。適用於游戲負載較重,耗時較長的線程場景,比如在地圖資源加載的時候,配合提頻一起使用。 參數: tid: 需要綁定大核的線程id,需傳入android系統級線程id isBind:傳入HyperBoostCommonUtil.BIND_GOLD_CORE表示綁定大核,傳入HyperBoostCommonUtil.UNBIND_GOLD_CORE表示解綁大核; |
VIVO-Multi-turbo
官網鏈接:Multi-turbo SDK介紹
1、Multi-turbo SDK介紹
Multi-turbo SDK支持游戲應用和普通應用,普通應用在某些關鍵場景下可通過Multi-turbo SDK提供的接口,通知手機系統及時分配合理的系統資源,保障應用的流暢運行。游戲應用可以給系統提供精准的場景、設置等信息,系統可給游戲應用反饋系統狀態等,利用這些信息雙方可以更好的協作,更進一步改善玩家的游戲體驗。
2、工作原理
開發者在需要的場景下,調用合適的Multi-turbo SDK提供的接口,手機系統層接受到相應需求,快速分配合理的系統資源,從而使應用運行更流暢;同時應用可注冊對應系統狀態回調,系統可以為注冊系統回調的應用反饋對應系統狀態信息,應用也可根據系統狀態信息做一些相應調整,從而達到更好的效果。

API
public boolean checkPermission(String code)
public void appShortTurbo(int duration, int level)
public void appLongTurbo(int duration, int level)
public void appTurboEnd()
public void gameLongTurbo(int duration)
public void gameShortTurbo(int duration)
public void gameTurboEnd()
public void gameSceneStart()
public void gameSceneEnd()
public void updateGameInfo(String infoJson)
public String getPhoneInfo(int type)
public void registerCallBack(CallBack callBack, int flags)
三、最后
第一章的現狀有提到,實現一套自己的資源調度框架是手機廠商的必經之路。
技術架構和核心方法上難點不大,只是copy一套系統服務和封裝內核接口。
重點還是這些接口使用,因為涉及到全局的性能,所以完善的測試是必要的。
