精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Android Q打通應用層到HAL層(HIDL服務實現)

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

AndroidQ 打通應用層到HAL層—(HAL模塊實現)這篇文章中我們已經實現了自己的HAL,本篇我們實現一個HIDL服務,通過這個服務來調用HAL模塊的函數

什么是HIDL

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

HIDL和應用層AIDL差不多,AIDL常用于連接App和Framework,HIDL則是用來連接Framework和HAL,AIDL使用Binder通信,HIDL則使用HwBinder通信,他們都是通過Binder驅動完成通信,只不過兩個Binder域不一樣

為什么需要HIDL

目前Android系統生態是幾乎每年google都會出一個Android大版本,而普通手機用戶一部手機一般要用兩三年,所以你會發現盡管Android系統已經升級到了10,馬上11出來了,然后還是有很多用戶依然使用的是Android 5,6,7等版本。

對普通用戶來說如果不更換手機就很難跟上Android版本,這是因為OEM廠商在同一設備上進行系統升級需要花費時間金錢成本很高,導致他們不愿意升級,成本高的原因是Android O之前Android Framework的升級需要OEM將HAL也進行對應升級,Framework和HAL是一起被編譯成system.img,它們存在高耦合。

針對這種情況google在Android O中引入了Treble計劃,Treble的目的就是解耦Framework和HAL,就是通過HIDL來實現,Framework不再直接調用HAL,而是通過HIDL來間接使用HAL模塊,每個HAL模塊都可以對應一個HIDL服務,Framework層通過HwBinder創建HIDL服務。

通過HIDL服務來獲取HAL相關模塊繼而打開HAL下的設備,而最終HAL也從system.img中分離,被編進一個單獨的分區vendor.img,從而簡化了Android系統升級的影響與難度。

HIDL的使用

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

并在此目錄下創建一個IHello.hal文件:

packageandroid.hardware.hello_hidl@1.0;

interfaceIHello{

addition_hidl(uint32_ta,uint32_tb)generates(uint32_ttotal);

};

這個文件定義了一個addition_hidl函數,這個函數用來調用HAL的加法函數

然后就可以使用Android提供的工具hidl-gen來生成HIDL框架,執行如下命令:

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

執行命令成功之后我們會發現hardware/interfaces/hello_hidl/1.0下多了一個default目錄,進入default目錄,里面有三個文件Android.bp,Hello.cpp,Hello.h

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

最后目錄結構為:

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

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

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

intmain(){
returndefaultPassthroughServiceImplementation();
}

defaultPassthroughServiceImplementation函數最終會向HwServiceManager注冊HIDL服務

接著我們來看看之前生成的文件,首先看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

系統自動生成了Hello結構體(當然也可以自己改為class),繼承IHello接口,addition_hidl函數就需要在Hello.cpp中去實現了,因為我們采用直通式HIDL,所以需要將// 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函數的注釋,采用直通式HIDL時,通過前面service.cpp中的defaultPassthroughServiceImplementation函數注冊HIDL服務時,內部原理就是通過“HIDL_FETCH_”字串拼接defaultPassthroughServiceImplementation傳遞的IHello,找到HIDL_FETCH_IHello函數并獲取IHello對象,我們可以看到HIDL_FETCH_IHello初始代碼就是創建了一個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",
],
}

這個Android.bp會將Hello這個HIDL服務編譯成一個android.hardware.hello_hidl@1.0-impl.so,它還依賴一個android.hardware.hello_hidl@1.0.so,這個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,
}

這個Android.bp會將hardware/interfaces/hello_hidl/1.0這個HIDL編譯成一個android.hardware.hello_hidl@1.0.so,到這里我們發現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編譯成一個二進制可執行文件android.hardware.hello_hidl@1.0-service.so,用來啟動HIDL服務,好了,最終我們這個HIDL會編譯出來如下三個so:
android.hardware.hello_hidl@1.0-impl.so
android.hardware.hello_hidl@1.0.so
android.hardware.hello_hidl@1.0-service.so

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


android.hardware.hello_hidl
hwbinder
1.0

IHello
default

@1.0::IHello/default

然后在Hello.cpp中添加一行log,之后進行編譯

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

ALOGE("hello_hidlserviceisinitsuccess....");

returnnewHello();
}

執行mmm hardware/interfaces/hello_hidl/1.0/

d6674dae-b06c-11ed-bfe3-dac502259ad0.png在這里插入圖片描述
編譯成功后我們將生成的三個so分別push到手機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/

接著我們到手機vendor/bin/hw/目錄下去執行android.hardware.hello_hidl@1.0-service這個二進制可執行文件,這個文件就會執行service.cpp的代碼,調用defaultPassthroughServiceImplementation注冊我們的HIDL服務

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

再看看log輸出:

d6b2d814-b06c-11ed-bfe3-dac502259ad0.png在這里插入圖片描述
在執行android.hardware.hello_hidl@1.0-service時就會輸入這句log,代表我們這個HIDL服務已經實現,其實通常的HIDL服務都是通過rc文件來開機啟動的,我這里為了方便演示就沒有寫

再執行adb shell ps -A|grep -i --color "hello_hidl"命令看下這個服務狀態
我們發現HIDL服務啟動之后就會一直在后臺,這個其實和AMS,WMS這種服務是類似的,啟動之后在后臺會等待client端訪問

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

HIDL這個服務已經能夠正常啟動了,接著寫一個測試程序看能否獲取這個服務,并且調用該服務的函數,我在Hello.cpp的addition_hidl函數中添加了一句log:

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

測試程序寫在hardware/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的服務,然后調用addition_hidl函數

看一下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",
],
}

我們再編譯這個測試程序,它會被編譯成一個可執行二進制文件Hello_hidl_test
編譯命令:
mmm hardware/interfaces/hello_hidl/1.0/default/test/

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

在執行Hello_hidl_test之前別忘了把HIDL服務啟動起來

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

到這里HIDL服務已經成功實現并且能夠正常使用,HIDL這個框架用起來還是比較簡單的,大部分代碼都是通過工具生成的。

審核編輯:湯梓紅

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • Android
    +關注

    關注

    12

    文章

    3923

    瀏覽量

    127133
  • 函數
    +關注

    關注

    3

    文章

    4304

    瀏覽量

    62429
  • C++
    C++
    +關注

    關注

    22

    文章

    2104

    瀏覽量

    73489
  • 應用層
    +關注

    關注

    0

    文章

    46

    瀏覽量

    11493
  • HAL
    HAL
    +關注

    關注

    2

    文章

    70

    瀏覽量

    12593

原文標題:Android Q打通應用層到HAL層(HIDL服務實現)

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

收藏 人收藏

    評論

    相關推薦

    關于應用層協議定義

    運輸給應用進程提供了端端的通信服務,但不同的網絡進程之間,還需要有不同的通信規則,因此運輸之上還需要有應用層。
    發表于 08-25 10:49 ?1568次閱讀

    PCM2707C是否支持Android系統?PCM2707C Android應用層怎么寫?

    有如下兩個問題,幫忙看看,謝謝! 1,PCM2707C是否支持Android系統 2,PCM2707C Android應用層怎么寫?如何獲取USB上的音頻數據。
    發表于 10-30 07:46

    鴻蒙Hi3516 純手工打造從應用層驅動示例

    本帖最后由 PCB00023915 于 2020-11-6 09:56 編輯 鴻蒙Hi3516 純手工打造從應用層驅動示例鴻蒙的應用和驅動構建涉及的文件較多,能夠重新編譯的
    發表于 11-06 09:56

    請問如何從Android應用層APP對u盤進行讀寫操作?

    開發板:i.MX6Q系統:Android6.0Linux4.1.15從Android應用層APP對u盤進行讀寫操作,沒有權限。怎么解決。。。求教。。。
    發表于 01-11 06:06

    RK3326 Android系統Hal是怎樣去添加服務

    RK3326 Android系統Hal是怎樣去添加服務的?有哪些流程?
    發表于 02-17 06:31

    RK3288 android7.1.2 HAL添加I2C Service怎么實現?

    RK3288 android7.1.2 HAL添加I2CService怎么實現
    發表于 03-02 09:11

    【學習打卡】OpenHarmony的應用層說明

    通過應用層實現控制與其他設備的通信。它是一種抽象服務,并且它將應用程序的其余部分與傳輸過程相屏蔽。應用層位于所有
    發表于 07-14 08:44

    計算機網絡應用層

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

    Zigbee應用層規范

    本內容介紹了Zigbee應用層規范
    發表于 05-24 11:37 ?85次下載
    Zigbee<b class='flag-5'>應用層</b>規范

    局域網通信原理傳輸應用層

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

    認知無線電MAC應用層仿真軟件

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

    Android硬件通訊之HIDL介紹

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

    應用層知多少?(總結在末尾)

    為什么需要應用層運輸給應用進程提供了端端的通信服務,但不同的網絡進程之間,還需要有不同的通信規則,因此運輸之上還需要有
    的頭像 發表于 08-26 11:16 ?1327次閱讀
    <b class='flag-5'>應用層</b>知多少?(總結在末尾)

    物聯網的技術架構及應用層是什么?

    物聯網的技術架構包括感知、網絡、平臺應用層。應用層是物聯網的頂層,它的主要功能是將感知
    的頭像 發表于 07-15 08:56 ?3603次閱讀

    Linux應用層控制外設的兩種不同的方式

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