0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Android Q打通應(yīng)用層到HAL層(HIDL服務(wù)實(shí)現(xiàn))

哆啦安全 ? 來源:CSDN-DJLZPP ? 2023-02-21 10:28 ? 次閱讀

AndroidQ 打通應(yīng)用層到HAL層—(HAL模塊實(shí)現(xiàn))這篇文章中我們已經(jīng)實(shí)現(xiàn)了自己的HAL,本篇我們實(shí)現(xiàn)一個(gè)HIDL服務(wù),通過這個(gè)服務(wù)來調(diào)用HAL模塊的函數(shù)

什么是HIDL

HIDL 全稱為HAL interface definition language(發(fā)音為“hide-l”)是用于指定 HAL 和其用戶之間的接口的一種接口描述語言 (IDL),Android O開始引入了HIDL這個(gè)概念。

HIDL和應(yīng)用層AIDL差不多,AIDL常用于連接App和Framework,HIDL則是用來連接Framework和HAL,AIDL使用Binder通信,HIDL則使用HwBinder通信,他們都是通過Binder驅(qū)動(dòng)完成通信,只不過兩個(gè)Binder域不一樣

為什么需要HIDL

目前Android系統(tǒng)生態(tài)是幾乎每年google都會(huì)出一個(gè)Android大版本,而普通手機(jī)用戶一部手機(jī)一般要用兩三年,所以你會(huì)發(fā)現(xiàn)盡管Android系統(tǒng)已經(jīng)升級到了10,馬上11出來了,然后還是有很多用戶依然使用的是Android 5,6,7等版本。

對普通用戶來說如果不更換手機(jī)就很難跟上Android版本,這是因?yàn)镺EM廠商在同一設(shè)備上進(jìn)行系統(tǒng)升級需要花費(fèi)時(shí)間金錢成本很高,導(dǎo)致他們不愿意升級,成本高的原因是Android O之前Android Framework的升級需要OEM將HAL也進(jìn)行對應(yīng)升級,F(xiàn)ramework和HAL是一起被編譯成system.img,它們存在高耦合。

針對這種情況google在Android O中引入了Treble計(jì)劃,Treble的目的就是解耦Framework和HAL,就是通過HIDL來實(shí)現(xiàn),F(xiàn)ramework不再直接調(diào)用HAL,而是通過HIDL來間接使用HAL模塊,每個(gè)HAL模塊都可以對應(yīng)一個(gè)HIDL服務(wù),F(xiàn)ramework層通過HwBinder創(chuàng)建HIDL服務(wù)。

通過HIDL服務(wù)來獲取HAL相關(guān)模塊繼而打開HAL下的設(shè)備,而最終HAL也從system.img中分離,被編進(jìn)一個(gè)單獨(dú)的分區(qū)vendor.img,從而簡化了Android系統(tǒng)升級的影響與難度。

HIDL的使用

HIDL可以分為:HIDL C++(C++實(shí)現(xiàn))、HIDL Java(Java 實(shí)現(xiàn)),并且還主要分為直通式和綁定式,本篇文章使用的C++和直通式的HIDL,HIDL用起來非常簡單,AOSP的hardware/interfaces/目錄下有很多的HIDL,我們仿照其他HIDL創(chuàng)建自己的HIDL目錄:hardware/interfaces/hello_hidl/1.0

并在此目錄下創(chuàng)建一個(gè)IHello.hal文件:

packageandroid.hardware.hello_hidl@1.0;

interfaceIHello{

addition_hidl(uint32_ta,uint32_tb)generates(uint32_ttotal);

};

這個(gè)文件定義了一個(gè)addition_hidl函數(shù),這個(gè)函數(shù)用來調(diào)用HAL的加法函數(shù)

然后就可以使用Android提供的工具h(yuǎn)idl-gen來生成HIDL框架,執(zhí)行如下命令:

PACKAGE=android.hardware.hello_hidl@1.0
LOC=hardware/interfaces/hello_hidl/1.0/default/
hidl-gen-o$LOC-Lc++-impl-randroid.hardware:hardware/interfaces-randroid.hidl:system/libhidl/transport$PACKAGE
hidl-gen-o$LOC-Landroidbp-impl-randroid.hardware:hardware/interfaces-randroid.hidl:system/libhidl/transport$PACKAGE

執(zhí)行命令成功之后我們會(huì)發(fā)現(xiàn)hardware/interfaces/hello_hidl/1.0下多了一個(gè)default目錄,進(jìn)入default目錄,里面有三個(gè)文件Android.bp,Hello.cpp,Hello.h

d6405992-b06c-11ed-bfe3-dac502259ad0.png在這里插入圖片描述
之后再在執(zhí)行./hardware/interfaces/update-makefiles.sh這個(gè)命令,update-makefiles.sh這個(gè)腳本目的是為HIDL生成對應(yīng)Android.bp文件

最后目錄結(jié)構(gòu)為:

d64e1ec4-b06c-11ed-bfe3-dac502259ad0.png在這里插入圖片描述

接著我們還需要在default目錄下增加一個(gè)空文件service.cpp,用作注冊HIDL服務(wù),我們采用直通式的HIDL,所以service.cpp的內(nèi)容為:

#include
#include
//GeneratedHIDLfiles
usingandroid::IHello;
usingandroid::defaultPassthroughServiceImplementation;

intmain(){
returndefaultPassthroughServiceImplementation();
}

defaultPassthroughServiceImplementation函數(shù)最終會(huì)向HwServiceManager注冊HIDL服務(wù)

接著我們來看看之前生成的文件,首先看Hello.h

//FIXME:yourfilelicenseifyouhaveone

#pragmaonce

#include
#include
#include

namespaceandroid{
namespacehardware{
namespacehello_hidl{
namespaceV1_0{
namespaceimplementation{
using::hidl_array;
using::hidl_memory;
using::hidl_string;
using::hidl_vec;
using::Return;
using::Void;
using::sp;

structHello:publicIHello{
//Methodsfrom::IHellofollow.
Returnaddition_hidl(uint32_ta,uint32_tb)override;

//Methodsfrom::IBasefollow.

};

//FIXME:mostlikelydelete,thisisonlyforpassthroughimplementations
//去掉注釋
extern"C"IHello*HIDL_FETCH_IHello(constchar*name);

}//namespaceimplementation
}//namespaceV1_0
}//namespacehello_hidl
}//namespacehardware
}//namespaceandroid

系統(tǒng)自動(dòng)生成了Hello結(jié)構(gòu)體(當(dāng)然也可以自己改為class),繼承IHello接口,addition_hidl函數(shù)就需要在Hello.cpp中去實(shí)現(xiàn)了,因?yàn)槲覀儾捎弥蓖ㄊ紿IDL,所以需要將// extern “C” IHello* HIDL_FETCH_IHello(const char* name);的注釋去掉

接著來看看Hello.cpp:

//FIXME:yourfilelicenseifyouhaveone

#include"Hello.h"
#include
namespaceandroid{
namespacehardware{
namespacehello_hidl{
namespaceV1_0{
namespaceimplementation{

//Methodsfrom::IHellofollow.
ReturnHello::addition_hidl(uint32_ta,uint32_tb){
//TODOimplement
ALOGE("hello_hidlserviceisinitsuccess....a:%d,b:%d",a,b);
returnuint32_t{};
}
//Methodsfrom::IBasefollow.

IHello*HIDL_FETCH_IHello(constchar*/*name*/){
returnnewHello();
}
}//namespaceimplementation
}//namespaceV1_0
}//namespacehello_hidl
}//namespacehardware
}//namespaceandroid

同樣需要去掉HIDL_FETCH_IHello函數(shù)的注釋,采用直通式HIDL時(shí),通過前面service.cpp中的defaultPassthroughServiceImplementation函數(shù)注冊HIDL服務(wù)時(shí),內(nèi)部原理就是通過“HIDL_FETCH_”字串拼接defaultPassthroughServiceImplementation傳遞的IHello,找到HIDL_FETCH_IHello函數(shù)并獲取IHello對象,我們可以看到HIDL_FETCH_IHello初始代碼就是創(chuàng)建了一個(gè)Hello對象

在接著看default目錄下的Android.bp:

cc_library_shared{
name:"android.hardware.hello_hidl@1.0-impl",
relative_install_path:"hw",
proprietary:true,
srcs:[
"Hello.cpp",
],
shared_libs:[
"libhidlbase",
"libhidltransport",
"libutils",
"android.hardware.hello_hidl@1.0",
"liblog",
"libutils",
],
}

這個(gè)Android.bp會(huì)將Hello這個(gè)HIDL服務(wù)編譯成一個(gè)android.hardware.hello_hidl@1.0-impl.so,它還依賴一個(gè)android.hardware.hello_hidl@1.0.so,這個(gè)so哪來的呢?

再接著看1.0目錄下的Android.bp:

//Thisfileisautogeneratedbyhidl-gen-Landroidbp.
hidl_interface{
name:"android.hardware.hello_hidl@1.0",
root:"android.hardware",
vndk:{
enabled:true,
},
srcs:[
"IHello.hal",
],
interfaces:[
"android.hidl.base@1.0",
],
gen_java:true,
}

這個(gè)Android.bp會(huì)將hardware/interfaces/hello_hidl/1.0這個(gè)HIDL編譯成一個(gè)android.hardware.hello_hidl@1.0.so,到這里我們發(fā)現(xiàn)service.cpp沒有用到,所以我們還需要修改default目錄下的Android.bp:

//FIXME:yourfilelicenseifyouhaveone

cc_library_shared{
name:"android.hardware.hello_hidl@1.0-impl",
relative_install_path:"hw",
proprietary:true,
srcs:[
"Hello.cpp",
],
shared_libs:[
"libhidlbase",
"libhidltransport",
"libutils",
"liblog",
"libhardware",
"android.hardware.hello_hidl@1.0",
"liblog",
"libutils",
],
}
cc_binary{
name:"android.hardware.hello_hidl@1.0-service",
defaults:["hidl_defaults"],
relative_install_path:"hw",
vendor:true,
srcs:["service.cpp"],
shared_libs:[
"android.hardware.hello_hidl@1.0",
"libhardware",
"libhidlbase",
"libhidltransport",
"libutils",
"liblog",
],

}

新增加對service.cpp的編譯,我們將service.cpp編譯成一個(gè)二進(jìn)制可執(zhí)行文件android.hardware.hello_hidl@1.0-service.so,用來啟動(dòng)HIDL服務(wù),好了,最終我們這個(gè)HIDL會(huì)編譯出來如下三個(gè)so:
android.hardware.hello_hidl@1.0-impl.so
android.hardware.hello_hidl@1.0.so
android.hardware.hello_hidl@1.0-service.so

還有一點(diǎn)需要注意的是,這個(gè)HIDL想要被Framework獲取使用還需要在manifest.xml中注冊,
manifest.xml在手機(jī)vendor/etc/vintf/manifest.xml下,我們將這個(gè)文件pull出來然后添加如下代碼:


android.hardware.hello_hidl
hwbinder
1.0

IHello
default

@1.0::IHello/default

然后在Hello.cpp中添加一行l(wèi)og,之后進(jìn)行編譯

IHello*HIDL_FETCH_IHello(constchar*/*name*/){

ALOGE("hello_hidlserviceisinitsuccess....");

returnnewHello();
}

執(zhí)行mmm hardware/interfaces/hello_hidl/1.0/

d6674dae-b06c-11ed-bfe3-dac502259ad0.png在這里插入圖片描述
編譯成功后我們將生成的三個(gè)so分別push到手機(jī)vendor/lib64/hw/,vendor/lib64/,vendor/bin/hw/目錄下

adb push vendor/lib64/hw/android.hardware.hello_hidl@1.0-impl.so vendor/lib64/hw/

adb push system/lib64/android.hardware.hello_hidl@1.0.so vendor/lib64/

adb push vendor/bin/hw/android.hardware.hello_hidl@1.0-service vendor/bin/hw/

接著我們到手機(jī)vendor/bin/hw/目錄下去執(zhí)行android.hardware.hello_hidl@1.0-service這個(gè)二進(jìn)制可執(zhí)行文件,這個(gè)文件就會(huì)執(zhí)行service.cpp的代碼,調(diào)用defaultPassthroughServiceImplementation注冊我們的HIDL服務(wù)

d697d01e-b06c-11ed-bfe3-dac502259ad0.png在這里插入圖片描述

再看看log輸出:

d6b2d814-b06c-11ed-bfe3-dac502259ad0.png在這里插入圖片描述
在執(zhí)行android.hardware.hello_hidl@1.0-service時(shí)就會(huì)輸入這句log,代表我們這個(gè)HIDL服務(wù)已經(jīng)實(shí)現(xiàn),其實(shí)通常的HIDL服務(wù)都是通過rc文件來開機(jī)啟動(dòng)的,我這里為了方便演示就沒有寫

再執(zhí)行adb shell ps -A|grep -i --color "hello_hidl"命令看下這個(gè)服務(wù)狀態(tài)
我們發(fā)現(xiàn)HIDL服務(wù)啟動(dòng)之后就會(huì)一直在后臺,這個(gè)其實(shí)和AMS,WMS這種服務(wù)是類似的,啟動(dòng)之后在后臺會(huì)等待client端訪問

d6c5c294-b06c-11ed-bfe3-dac502259ad0.png在這里插入圖片描述

HIDL這個(gè)服務(wù)已經(jīng)能夠正常啟動(dòng)了,接著寫一個(gè)測試程序看能否獲取這個(gè)服務(wù),并且調(diào)用該服務(wù)的函數(shù),我在Hello.cpp的addition_hidl函數(shù)中添加了一句log:

ReturnHello::addition_hidl(uint32_ta,uint32_tb){
//TODOimplement
ALOGD("dongjiao...Hello::addition_hidla=%d,b=%d",a,b);
returnuint32_t{};
}

測試程序?qū)懺趆ardware/interfaces/hello_hidl/1.0/default目錄下:

d6e1b706-b06c-11ed-bfe3-dac502259ad0.png在這里插入圖片描述
Hello_hidl_test.cpp:

#include
#include
#include

usingandroid::sp;
usingandroid::IHello;
usingandroid::Return;
intmain(){
android::sphw_device=IHello::getService();
if(hw_device==nullptr){
ALOGD("dongjiao...failedtogethello-hidl");
return-1;
}
ALOGD("dongjiao...successtogethello-hidl....");
Returntotal=hw_device->addition_hidl(3,4);
return0;
}

測試程序代碼也比較簡單,獲取IHello的服務(wù),然后調(diào)用addition_hidl函數(shù)

看一下Android.bp:

cc_binary{
name:"Hello_hidl_test",
srcs:["Hello_hidl_test.cpp"],
shared_libs:[
"liblog",
"android.hardware.hello_hidl@1.0",
"libhidlbase",
"libhidltransport",
"libhwbinder",
"libutils",
],
}

我們再編譯這個(gè)測試程序,它會(huì)被編譯成一個(gè)可執(zhí)行二進(jìn)制文件Hello_hidl_test
編譯命令:
mmm hardware/interfaces/hello_hidl/1.0/default/test/

d708152c-b06c-11ed-bfe3-dac502259ad0.png在這里插入圖片描述
編譯成功了,將這個(gè)可執(zhí)行文件push到手機(jī)/system/bin/目錄下

在執(zhí)行Hello_hidl_test之前別忘了把HIDL服務(wù)啟動(dòng)起來

d74177ae-b06c-11ed-bfe3-dac502259ad0.png在這里插入圖片描述
接著執(zhí)行Hello_hidl_test
d75700f6-b06c-11ed-bfe3-dac502259ad0.png在這里插入圖片描述
然后看log輸出
d7747096-b06c-11ed-bfe3-dac502259ad0.png在這里插入圖片描述
可以看到成功了,成功獲取到了HIDL服務(wù)并且調(diào)用了該服務(wù)的addition_hidl函數(shù),將我們的參數(shù)傳遞了過去,實(shí)際開發(fā)中就可以在獲取HIDL服務(wù)時(shí)打開HAL模塊,然后可以直接調(diào)用HAL的函數(shù)。 上一篇文章其實(shí)也寫了測試程序測自定義的HAL模塊,我們只需要將上一篇文章中的測試程序中的代碼copy到HIDL初始化代碼中就能夠調(diào)用HAL的那個(gè)加法函數(shù)了,具體就不測試了。

到這里HIDL服務(wù)已經(jīng)成功實(shí)現(xiàn)并且能夠正常使用,HIDL這個(gè)框架用起來還是比較簡單的,大部分代碼都是通過工具生成的。

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • Android
    +關(guān)注

    關(guān)注

    12

    文章

    3917

    瀏覽量

    127037
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4284

    瀏覽量

    62325
  • C++
    C++
    +關(guān)注

    關(guān)注

    21

    文章

    2102

    瀏覽量

    73453
  • 應(yīng)用層
    +關(guān)注

    關(guān)注

    0

    文章

    46

    瀏覽量

    11487
  • HAL
    HAL
    +關(guān)注

    關(guān)注

    2

    文章

    69

    瀏覽量

    12576

原文標(biāo)題:Android Q打通應(yīng)用層到HAL層(HIDL服務(wù)實(shí)現(xiàn))

文章出處:【微信號:哆啦安全,微信公眾號:哆啦安全】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    關(guān)于應(yīng)用層協(xié)議定義

    運(yùn)輸給應(yīng)用進(jìn)程提供了端端的通信服務(wù),但不同的網(wǎng)絡(luò)進(jìn)程之間,還需要有不同的通信規(guī)則,因此運(yùn)輸之上還需要有應(yīng)用層。
    發(fā)表于 08-25 10:49 ?1559次閱讀

    PCM2707C是否支持Android系統(tǒng)?PCM2707C Android應(yīng)用層怎么寫?

    有如下兩個(gè)問題,幫忙看看,謝謝! 1,PCM2707C是否支持Android系統(tǒng) 2,PCM2707C Android應(yīng)用層怎么寫?如何獲取USB上的音頻數(shù)據(jù)。
    發(fā)表于 10-30 07:46

    鴻蒙Hi3516 純手工打造從應(yīng)用層驅(qū)動(dòng)示例

    本帖最后由 PCB00023915 于 2020-11-6 09:56 編輯 鴻蒙Hi3516 純手工打造從應(yīng)用層驅(qū)動(dòng)示例鴻蒙的應(yīng)用和驅(qū)動(dòng)構(gòu)建涉及的文件較多,能夠重新編譯的
    發(fā)表于 11-06 09:56

    請問如何從Android應(yīng)用層APP對u盤進(jìn)行讀寫操作?

    開發(fā)板:i.MX6Q系統(tǒng):Android6.0Linux4.1.15從Android應(yīng)用層APP對u盤進(jìn)行讀寫操作,沒有權(quán)限。怎么解決。。。求教。。。
    發(fā)表于 01-11 06:06

    RK3326 Android系統(tǒng)Hal是怎樣去添加服務(wù)

    RK3326 Android系統(tǒng)Hal是怎樣去添加服務(wù)的?有哪些流程?
    發(fā)表于 02-17 06:31

    RK3288 android7.1.2 HAL添加I2C Service怎么實(shí)現(xiàn)

    RK3288 android7.1.2 HAL添加I2CService怎么實(shí)現(xiàn)?
    發(fā)表于 03-02 09:11

    【學(xué)習(xí)打卡】OpenHarmony的應(yīng)用層說明

    通過應(yīng)用層實(shí)現(xiàn)控制與其他設(shè)備的通信。它是一種抽象服務(wù),并且它將應(yīng)用程序的其余部分與傳輸過程相屏蔽。應(yīng)用層位于所有
    發(fā)表于 07-14 08:44

    計(jì)算機(jī)網(wǎng)絡(luò)應(yīng)用層

    掌握TCP/IP 的應(yīng)用層的主要應(yīng)用及工作原理,包括DNS 服務(wù)、 HTTP 服務(wù)、 FTP 服務(wù)和E-mail 服務(wù);理解OSI
    發(fā)表于 08-05 17:46 ?292次下載

    Zigbee應(yīng)用層規(guī)范

    本內(nèi)容介紹了Zigbee應(yīng)用層規(guī)范
    發(fā)表于 05-24 11:37 ?85次下載
    Zigbee<b class='flag-5'>應(yīng)用層</b>規(guī)范

    局域網(wǎng)通信原理傳輸應(yīng)用層

    局域網(wǎng)通信原理傳輸應(yīng)用層(烽火通信網(wǎng)絡(luò)機(jī)頂盒hg680-j刷機(jī))-該文檔為局域網(wǎng)通信原理傳輸應(yīng)用層講解資料,講解的還不錯(cuò),感興趣的可以下載看看…………………………
    發(fā)表于 07-30 08:29 ?15次下載
    局域網(wǎng)通信原理傳輸<b class='flag-5'>層</b>和<b class='flag-5'>應(yīng)用層</b>

    認(rèn)知無線電MAC應(yīng)用層仿真軟件

    認(rèn)知無線電MAC應(yīng)用層仿真軟件(澳萊特電源技術(shù)有限公司)-該文檔為認(rèn)知無線電MAC應(yīng)用層仿真軟件總結(jié)文檔,是一份很不錯(cuò)的參考資料,具有較高參考價(jià)值,感興趣的可以下載看看…………
    發(fā)表于 09-15 11:40 ?11次下載
    認(rèn)知無線電MAC<b class='flag-5'>層</b>與<b class='flag-5'>應(yīng)用層</b>仿真軟件

    Android硬件通訊之HIDL介紹

    HIDL的全稱是HAL interface definition language(硬件抽象接口定義語言),是AndroidFramework 與
    的頭像 發(fā)表于 03-08 15:52 ?5051次閱讀

    應(yīng)用層知多少?(總結(jié)在末尾)

    為什么需要應(yīng)用層運(yùn)輸給應(yīng)用進(jìn)程提供了端端的通信服務(wù),但不同的網(wǎng)絡(luò)進(jìn)程之間,還需要有不同的通信規(guī)則,因此運(yùn)輸之上還需要有
    的頭像 發(fā)表于 08-26 11:16 ?1300次閱讀
    <b class='flag-5'>應(yīng)用層</b>知多少?(總結(jié)在末尾)

    物聯(lián)網(wǎng)的技術(shù)架構(gòu)及應(yīng)用層是什么?

    物聯(lián)網(wǎng)的技術(shù)架構(gòu)包括感知、網(wǎng)絡(luò)、平臺應(yīng)用層。應(yīng)用層是物聯(lián)網(wǎng)的頂層,它的主要功能是將感知
    的頭像 發(fā)表于 07-15 08:56 ?3540次閱讀

    Linux應(yīng)用層控制外設(shè)的兩種不同的方式

    眾所周知,linux下一切皆文件,那么應(yīng)用層如何控制硬件,同樣是通過 文件I/O的方式來實(shí)現(xiàn)的,那么應(yīng)用層控制硬件通常有兩種方式。
    的頭像 發(fā)表于 10-05 19:03 ?219次閱讀
    Linux<b class='flag-5'>應(yīng)用層</b>控制外設(shè)的兩種不同的方式