HIDL背景
Treble 是 Google Android 團(tuán)隊(duì)的一項(xiàng)重大項(xiàng)目,意在 Android 操作系統(tǒng)框架在架構(gòu)方面的一項(xiàng)重大改變碍遍,旨在讓制造商以更低的成本更輕松、更快速地將設(shè)備更新到新版 Android 系統(tǒng)。Android 7.x 及更早版本中沒有正式的供應(yīng)商接口脆丁,因此設(shè)備制造商必須更新大量 Android 代碼才能將設(shè)備更新到新版 Android 系統(tǒng)奢讨。
Android O以后稚叹,Treble 提供了一個穩(wěn)定的新供應(yīng)商接口,供設(shè)備制造商訪問 Android 代碼中特定于硬件的部分拿诸,這樣一來扒袖,設(shè)備制造商只需更新 Android 操作系統(tǒng)框架,即可跳過芯片制造商直接提供新的 Android 版本亩码。
HIDL簡介
HIDL 是用于指定 HAL 與其用戶之間接口的一個接口描述語言(Interface Description Language)季率,它允許將指定的類型與函數(shù)調(diào)用收集到接口(Interface)和包(Package)中。更廣泛地說描沟,HIDL 是一個可以讓那些獨(dú)立編譯的代碼庫(Libraries)之間進(jìn)行通信的系統(tǒng)飒泻。 HIDL 實(shí)際上是用于進(jìn)行進(jìn)程間通信(Inter-process Communication,IPC)的啊掏。進(jìn)程間的通信可以稱為 Binder 化(Binderized)蠢络。對于必須連接到進(jìn)程的庫,也可以使用 passthough 模式(但在Java中不支持)迟蜜。 HIDL 將指定的數(shù)據(jù)結(jié)構(gòu)與方法簽名組織到接口中刹孔,這些接口又會被收集到包中以供使用。它的語法與 C++娜睛、JAVA 是類似的髓霞,不過關(guān)鍵字集合不盡相同。其注釋風(fēng)格與 JAVA 是一致的畦戒。
HIDL設(shè)計
設(shè)計 HIDL 這個機(jī)制的目的方库,主要是想把框架(framework)與 HAL 進(jìn)行隔離,使得框架部分可以直接被覆蓋障斋、更新纵潦,而不需要重新對 HAL 進(jìn)行編譯徐鹤。HAL 的部分將會放在設(shè)備的 /vendor 分區(qū)中,并且是由設(shè)備供應(yīng)商(vendors)或 SOC 制造商來構(gòu)建邀层。這使得框架部分可以通過 OTA 方式更新返敬,同時不需要重新編譯 HAL。
直通式HAL( Passthrough 模式)和 綁定式 HAL (Binderized模式)
為了將以往設(shè)備的 Android 版本更新到 Android O寥院,開發(fā)者需要將傳統(tǒng)的 HAL 封裝到新的 HIDL 接口中劲赠,這個接口為 HAL 提供了 Binder 化以及 Passthrough 模式。這個封裝過程對 HAL 以及 Android Framework 都是透明的秸谢。
Passthrough 模式僅對 C++ 客戶端與實(shí)現(xiàn)適用凛澎,以往的 Android 版本設(shè)備中,HAL 不會采用 JAVA 語言來寫估蹄,所以 JAVA HAL 必然是 Binder 化的塑煎。
綁定式 HAL。以 HAL 接口定義語言 (HIDL) 表示的 HAL臭蚁。這些 HAL 取代了早期 Android 版本中使用的傳統(tǒng) HAL 和舊版 HAL轧叽。在綁定式 HAL 中,Android 框架和 HAL 之間通過 Binder 進(jìn)程間通信 (IPC) 調(diào)用進(jìn)行通信刊棕。所有在推出時即搭載了 Android 8.0 或后續(xù)版本的設(shè)備都必須只支持綁定式 HAL炭晒。
下面介紹HIDL的實(shí)現(xiàn)流程:
一、編譯環(huán)境
1. 下載AOSP源碼
android 8.1.0_r52 OPM7.181205.001
2. 編譯代碼:
source build/envset.sh
lunch
甥角,選擇一個對應(yīng)手機(jī)的編譯項(xiàng)
make
3网严、hidl-gen工具已經(jīng)安裝,安裝命令
make hidl-gen
4嗤无、調(diào)試平臺
Nexus 5X手機(jī)
二绽昼、設(shè)計實(shí)現(xiàn)
NFC POS實(shí)現(xiàn)設(shè)計在HAL層坦报,隔離framework框架砖织,HAL層實(shí)現(xiàn)EMV Level one和EMV Level two瑟捣。本文實(shí)現(xiàn)EMV Level 2為例:
1、創(chuàng)建接口文件
在hardware/interfaces/目錄下新建nfcEMV/1.0目錄嚎卫,并在1.0目錄中創(chuàng)建接口INfcEMV.hal嘉栓。
mkdir -p hardware/interfaces/nfcEMV/1.0
vim hardware/interfaces/nfcEMV/1.0/INfcEMV.hal
vim hardware/interfaces/nfcEMV/1.0/INfcNotify.hal
vim hardware/interfaces/nfcEMV/1.0/types.hal
目錄結(jié)構(gòu)如下:
eric@ubuntu:~/android-8.1.0_r52/hardware/interfaces/nfcEMV$ tree
.
└── 1.0
├── INfcEMV.hal
├── INfcNotify.hal
└── types.hal
INfcEMV.hal文件里面有一個接口INfcEMV和一個方法transceive(string command),文件實(shí)現(xiàn)如下:
package android.hardware.nfcEMV@1.0;
interface INfcEMV{
init();
release();
transceive(string command) generates (string response);
setCallback(INfcNotify callback);
};
其中transceive為收發(fā)命令接口拓诸。
setCallback:讓client端設(shè)置一個callback方法到server端
下面來看看這個callback里面都定義了些啥侵佃,我們要為這個callback實(shí)現(xiàn)一個接口INfcNotify.hal
package android.hardware.nfcEMV@1.0;
?interface INfcNotify{
oneway onNotify(HalEvent event);
};
回調(diào)函數(shù)里面有一個回調(diào)方法,可以讓server傳一個HalEvent的結(jié)構(gòu)體到client端奠支,這個結(jié)構(gòu)體也是自定義的馋辈,在types.hal,可以定義自己喜歡的類型倍谜,這里是一個簡單的int成員變量
package android.hardware.nfcEMV@1.0;
?struct HalEvent {
int32_t id;
int32_t value;
};
2迈螟、hidl-gen命令產(chǎn)生接口實(shí)現(xiàn)文件
Google為我們提供了一些工具來生成HAL層相關(guān)的代碼框架和代碼實(shí)例叉抡,這樣子我們只需要關(guān)心實(shí)現(xiàn)部分,而不需要寫一堆代碼答毫。
創(chuàng)建腳本nfcEMV.sh
vim nfcEMV.sh
chmod 777 nfcEMV.sh
腳本會使用hidl-gen工具卜壕,自動生成對應(yīng)的c++文件和Android.bp文件,實(shí)現(xiàn)如下:
PACKAGE=android.hardware.nfcEMV@1.0
LOC=hardware/interfaces/nfcEMV/1.0/default/
# make hidl-gen -j64
#使用hidl-gen生成default目錄里的C++文件
hidl-gen -o $LOC -Lc++-impl -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport $PACKAGE
#使用hidl-gen生成default目錄 里的Android.bp文件
hidl-gen -o $LOC -Landroidbp-impl -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport $PACKAGE
現(xiàn)在的目錄如下:
eric@ubuntu:~/android-8.1.0_r52/hardware/interfaces/nfcEMV$ tree
.
└── 1.0
├── default
│ ├── Android.bp**
│ ├── NfcEMV.cpp**
│ ├── NfcEMV.h**
│ ├── NfcNotify.cpp**
│ └── NfcNotify.h**
├── INfcEMV.hal
├── INfcNotify.hal
└── types.hal
其中有一個代碼是用不到的烙常,NfcNotify.h和NfcNotify.cpp,刪掉這兩個文件鹤盒。
default 是新生成的目錄蚕脏,打開NfcEMV.h文件,去掉下面的注釋
// extern "C" INfcEMV* HIDL_FETCH_INfcEMV(const char* name);
HIDL的實(shí)現(xiàn)有兩種方式侦锯,一種是Binderized模式驼鞭,另一種是Passthrough模式,我們使用直通式HAL(Passthrough 模式)來通信尺碰。
NfcEMV.cpp文件也要進(jìn)行對應(yīng)的修改挣棕, 去掉如下的注釋:
//INfcEMV* HIDL_FETCH_INfcEMV(const char* /* name */) {
// return new NfcEMV();
//}
整個文件代碼如下:
vim hardware/interfaces/nfcEMV/1.0/default/NfcEMV.cpp
#define LOG_TAG "NfcEMV"
#include "NfcEMV.h"
#include <log/log.h>
namespace android {
namespace hardware {
namespace nfcEMV {
namespace V1_0 {
namespace implementation {
//eric: server callback handler
sp<INfcNotify> NfcEMV::mCallback = nullptr;
// Methods from INfcEMV follow.
Return<void> NfcEMV::init() {
// TODO implement
mExit = false;
run("NfcEMV");
return Void();
}
Return<void> NfcEMV::release() {
// TODO implement
mExit = true;
return Void();
}
Return<void> NfcEMV::transceive(const hidl_string& command, transceive_cb _hidl_cb) {
// TODO implement
//Eric: here print the command input from client
char buf[100];
::memset(buf, 0x00, 100);
::snprintf(buf, 100, "___EricLog:transceive Command:, %s", command.c_str());
hidl_string response(buf);
_hidl_cb(response);
return Void();
return Void();
}
Return<void> NfcEMV::setCallback(const sp<INfcNotify>& callback) {
// TODO implement
mCallback = callback;
if(mCallback != nullptr) {
ALOGD("setCallback: done");
}
return Void();
}
bool NfcEMV::threadLoop()
{
static int32_t count = 0;
HalEvent event;
while(!mExit) {
::sleep(2);
event.value = count ++;
if(mCallback != nullptr) {
mCallback->onNotify(event);
}
}//end while
ALOGD("threadLoop: exit");
return false;
}
// Methods from ::android::hidl::base::V1_0::IBase follow.
INfcEMV* HIDL_FETCH_INfcEMV(const char* /* name */) {
return new NfcEMV();
}
} // namespace implementation
} // namespace V1_0
} // namespace nfcEMV
} // namespace hardware
} // namespace android
3. 然后使用腳本update-makefiles.sh來更新Makefile
自動在hardware/interfaces/nfcEMV/1.0目錄生成Android.mk和 Android.bp,hardware/interfaces/nfcEMV目錄生成Android.bp亲桥。命令如下
./hardware/interfaces/update-makefiles.sh
再來添加兩個空文件:
touch hardware/interfaces/nfcEMV/1.0/default/android.hardware.nfcEMV@1.0-service.rc
touch hardware/interfaces/nfcEMV/1.0/default/service.cpp
目錄結(jié)構(gòu)如下:
eric@ubuntu:~/android-8.1.0_r52/hardware/interfaces/nfcEMV$ tree
.
├── 1.0
│ ├── Android.bp
│ ├── Android.mk
│ ├── default
│ │ ├── Android.bp
│ │ ├── android.hardware.nfcEMV@1.0-service.rc**
│ │ ├── NfcEMV.cpp
│ │ ├── NfcEMV.h
│ │ ├── NfcNotify.cpp
│ │ ├── NfcNotify.h
│ │ └── service.cpp**
│ ├── INfcEMV.hal
│ ├── INfcNotify.hal
│ └── types.hal
└── Android.bp
其中android.hardware.nfcEMV@1.0-service.rc是程序的入口函數(shù)洛心,實(shí)現(xiàn)如下:
vim hardware/interfaces/nfcEMV/1.0/default/android.hardware.nfcEMV@1.0-service.rc
service nfcEMV_hal_service /vendor/bin/hw/android.hardware.nfcEMV@1.0-service
class hal
user system
group system
很簡單,就是在設(shè)備啟動的時候執(zhí)行/vendor/bin/hw/android.hardware.nfcEMV@1.0-service程序:
vim hardware/interfaces/nfcEMV/1.0/default/service.cpp
# define LOG_TAG "android.hardware.nfcEMV@1.0-service"
# include <android/hardware/nfcEMV/1.0/INfcEMV.h>
# include <hidl/LegacySupport.h>
using android::hardware::nfcEMV::V1_0::INfcEMV;
using android::hardware::defaultPassthroughServiceImplementation;
int main() {
return defaultPassthroughServiceImplementation<INfcEMV>();
}
這個service是注冊了INfcEMV接口文件里面的接口题篷,作為binder server端词身,很簡單就一句話,因?yàn)槲覀兪褂昧藀assthrough的模式番枚,Android幫我們封裝了這個函數(shù)法严,不需要我們自己去addService
打開hardware/interfaces/nfcEMV/1.0/default目錄下的Android.bp,添加編譯service.cpp成為可執(zhí)行文件的代碼葫笼。具體添加內(nèi)容如下:
vim hardware/interfaces/nfcEMV/1.0/default/Android.bp
cc_binary {
name: "android.hardware.nfcEMV@1.0-service",
defaults: ["hidl_defaults"],
proprietary: true,
relative_install_path: "hw",
srcs: ["service.cpp"],
init_rc: ["android.hardware.nfcEMV@1.0-service.rc"],
shared_libs: [
"libhidlbase",
"libhidltransport",
"libutils",
"liblog",
"android.hardware.nfcEMV@1.0",
"android.hardware.nfcEMV@1.0-impl",
],
}
然后編譯:
mmm hardware/interfaces/nfcEMV/1.0/default/
編譯后可以在, vendor/bin/hw/下找到對應(yīng)的文件android.hardware.nfcEMV@1.0-service*深啤。
ll out/target/product/bullhead/vendor/bin/hw/
生成的HAL server端的程序列表:
- out/target/product/bullhead/vendor/lib64/hw/android.hardware.nfcEMV@1.0-impl.so*
- out/target/product/bullhead/system/lib64/android.hardware.nfcEMV@1.0.so*
- out/target/product/bullhead/vendor/bin/hw/android.hardware.nfcEMV@1.0-service*
目前,我們server端的進(jìn)程和實(shí)現(xiàn)端共享庫已經(jīng)完成了路星。
在manifest文件里添加vendor接口的定義, 編輯device/lge/bullhead/manifest.xml文件(拿Nexus5x手機(jī)舉例)溯街,添加android.hardware.nfcEMV的聲明,不然在client端是沒法拿到service的洋丐。如下:
vim device/lge/bullhead/manifest.xml
<manifest version="1.0" type="device">
<hal format="hidl">
<name>android.hardware.graphics.allocator</name>
<transport>hwbinder</transport>
<version>2.0</version>
<interface>
<name>IAllocator</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<name>android.hardware.wifi</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>IWifi</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<name>android.hardware.wifi.supplicant</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>ISupplicant</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<name>android.hardware.nfcEMV</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>INfcEMV</name>
<instance>default</instance>
</interface>
</hal>
</manifest>
4. 客戶端的實(shí)現(xiàn)
4.1 使用C++實(shí)現(xiàn)客戶端調(diào)用
在hardware/interfaces/nfcEMV/1.0目錄下新建test目錄苫幢,并且在test目錄下新建Android.bp跟nfcEMVTest.cpp文件,這兩個文件的內(nèi)容如下:
vim hardware/interfaces/nfcEMV/1.0/test/nfcEMVTest.cpp
#define LOG_TAG "nfcEMV_Test"
#include <log/log.h>
#include <android/hardware/nfcEMV/1.0/INfcEMV.h>
#include <android/hardware/nfcEMV/1.0/types.h>
#include <android/hardware/nfcEMV/1.0/INfcNotify.h>
#include <hidl/Status.h>
#include <hidl/HidlSupport.h>
using android::sp;
using android::hardware::Return;
using android::hardware::Void;
using android::hardware::nfcEMV::V1_0::INfcEMV;
using android::hardware::nfcEMV::V1_0::HalEvent
using android::hardware::nfcEMV::V1_0::INfcNotify
class nfcEMVCallback: public INfcNotify {
public:
nfcEMVCallback() {}
~nfcEMVCallback() {}
Return<void> onNotify(const HalEvent& event) {
ALOGD("onNotify: id = %d, value = %d", event.id, event.value);
return Void();
}
};
int main(void)
{
sp<INfcEMV> service = INfcEMV::getService();
if(service == nullptr) {
ALOGE("main: failed to get nfcEMV service");
return -1;
}
sp<nfcEMVCallback> callback = new nfcEMVCallback();
service->setCallback(callback);
service->init();
::sleep(20);
service->release();
return 0;
}
vim -p hardware/interfaces/nfcEMV/1.0/test/Android.bp
cc_binary {
relative_install_path: "hw",
defaults: ["hidl_defaults"],
name: "nfcEMV_client",
proprietary: true,
srcs: ["nfcEMVTest.cpp"],
shared_libs: [
"liblog",
"libhardware",
"libhidlbase",
"libhidltransport",
"libutils",
"android.hardware.nfcEMV@1.0",
],
}
執(zhí)行以下命令:
./hardware/interfaces/update-makefiles.sh
mmm hardware/interfaces/nfcEMV/1.0/
執(zhí)行第一條命令是為了更新hardware/interfaces/nfcEMV/目錄下的Android.bp文件垫挨,如下:
vim hardware/interfaces/nfcEMV/Android.bp
// This is an autogenerated file, do not edit.
subdirs = [
"1.0",
"1.0/default",
"1.0/test",
]
執(zhí)行第二條命令會生成可執(zhí)行文件:
out/target/product/bullhead/vendor/bin/hw/nfcEMV_client
調(diào)試HIDL
建立腳本nfcEMV_adb_push.sh韩肝,把生成的service復(fù)制到手機(jī)的目錄。
vim nfcEMV_adb_push.sh
adb push out/target/product/bullhead/vendor/lib64/hw/android.hardware.nfcEMV@1.0-impl.so /vendor/lib64/hw/
adb push out/target/product/bullhead/system/lib64/android.hardware.nfcEMV@1.0.so /system/lib64/
adb push out/target/product/bullhead/vendor/bin/hw/android.hardware.nfcEMV@1.0-service* /vendor/bin/hw/
adb push out/target/product/bullhead/vendor/etc/init/android.hardware.nfcEMV@1.0-service.rc /vendor/etc/init/
adb push out/target/product/bullhead/vendor/bin/hw/nfcEMV_client /vendor/bin/hw/
adb push device/lge/bullhead/manifest.xml /vendor/
然后進(jìn)入手機(jī)adb device檢查手機(jī)是否連接九榔,adb shell進(jìn)入命令行哀峻。
adb shell
cd /vendor/bin/hw/
./nfcEMV_client
4.2 java層實(shí)現(xiàn)客戶端的HIDL調(diào)用
為了方便eclipse或者Android Studio調(diào)用接口函數(shù)涡相,需要編譯出classes.jar包。但是jack編譯出來的文件是classes.jack剩蟀。
檢查目錄
eric@ubuntu:~/android-8.1.0_r52/out/target/common/obj/JAVA_LIBRARIES/android.hardware.nfcEMV-V1.0-java_intermediates$ tree
.
|-- anno
|-- classes
|-- classes-desugar.jar
|-- classes-full-debug.jar
|-- classes.dex
|-- classes.jack
|-- classes.jar(需要這個文件)
|-- desugar_dumped_classes
|-- jack-rsc
|-- jack-rsc.java-source-list
|-- jack_res_jar_flags
|-- javalib.jar
|-- link_type
為了編譯出classes.jar催蝗,需要打開hardware/interfaces/nfcEMV/1.0目錄的Android.mk,在include $(CLEAR_VARS)下面添加ANDROID_COMPILE_WITH_JACK := false育特。這樣編譯的時候就不走jack編譯了
vim hardware/interfaces/nfcEMV/1.0/Android.mk
# This file is autogenerated by hidl-gen. Do not edit manually.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
#LOCAL_JACK_ENABLED := disabled
ANDROID_COMPILE_WITH_JACK := false
LOCAL_MODULE := android.hardware.nfcEMV-V1.0-java
LOCAL_MODULE_CLASS := JAVA_LIBRARIES
執(zhí)行下面命令
mmm hardware/interfaces/nfcEMV/1.0/
執(zhí)行完后生成classes.jar.
新建Android項(xiàng)目HIDLdemo丙号,將classes.jar導(dǎo)入項(xiàng)目,MainActivity代碼實(shí)現(xiàn)如下:
vim packages/apps/HIDLdemo/src/com/example/eric/hidldemo/MainActivity.java
package com.example.eric.hidldemo;
import android.hardware.nfcEMV.V1_0.INfcEMV;
import android.os.Bundle;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
INfcEMV iNfcEMVService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hidl);
try {
iNfcEMVService = INfcEMV.getService();
} catch (RemoteException e) {
e.printStackTrace();
}
}
public void hidlTest(View view){
if (iNfcEMVService != null){
Log.d("NfcEMV", "service is connect.");
String s = null;
try {
s = iNfcEMVService.transceive("NfcEMV");
} catch (RemoteException e) {
e.printStackTrace();
}
Log.d("nfcEMV", s);
Toast.makeText(this, s, Toast.LENGTH_LONG).show();
}
}
}
添加Android.mk文件缰冤,然后將項(xiàng)目放到packages/apps/進(jìn)行編譯犬缨。Android.mk文件內(nèi)容如下:
vim packages/apps/HIDLdemo/Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_PACKAGE_NAME := HIDLdemo
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_MODULE_TAGS :=optional
LOCAL_DEX_PREOPT := false
LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4
LOCAL_STATIC_JAVA_LIBRARIES += android-support-v7-appcompat
LOCAL_STATIC_JAVA_LIBRARIES += android-support-v7-gridlayout
#LOCAL_STATIC_JAVA_LIBRARIES += android-support-v13
LOCAL_STATIC_JAVA_LIBRARIES += android.hardware.nfcEMV-V1.0-java-static
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_RESOURCE_DIR += prebuilts/sdk/current/support/v7/appcompat/res
LOCAL_RESOURCE_DIR += prebuilts/sdk/current/support/v7/gridlayout/res
LOCAL_CERTIFICATE := platform
#LOCAL_PRIVILEGED_MODULE := true
LOCAL_AAPT_FLAGS := --auto-add-overlay
LOCAL_AAPT_FLAGS += --extra-packages android.support.v7.appcompat:android.support.v7.gridlayout
#LOCAL_STATIC_JAVA_LIBRARIES += android.hardware.fingerprint-V1.0-java-static
#LOCAL_SRC_FILES := $(call all-subdir-java-files)
include $(BUILD_PACKAGE)
執(zhí)行命令
mmm packages/apps/HIDLdemo
會生成out/target/product/bullhead/system/app/HIDLdemo/HIDLdemo.apk
push到手機(jī):
adb install -r out/target/product/bullhead/system/app/HIDLdemo/HIDLdemo.apk
問題:這個時候會出現(xiàn)base.apk code is missing的error 信息,
adb: failed to install out/target/product/bullhead/system/app/HIDLdemo/HIDLdemo.apk: Failure [INSTALL_FAILED_INVALID_APK: Package couldn't be installed in /data/app/com.example.eric.hidldemo-3AZN-XemgZKqyJPiOwx0Jg==: Package /data/app/com.example.eric.hidldemo-3AZN-XemgZKqyJPiOwx0Jg==/base.apk code is missing]
解決方案:在Android.mk中增加LOCAL_DEX_PREOPT := false
Android客戶端執(zhí)行
先啟動./android.hardware.nfcEMV@1.0-service服務(wù)棉浸,然后通過命令拉起MainActivity界面
adb shell am start -n com.example.eric.hidldemo/.MainActivity
執(zhí)行時會出現(xiàn)SELinux : avc: denied的error信息怀薛;添加HIDL的SELinux步驟:
vim device/lge/bullhead/sepolicy/service.te
type per_mgr_service, service_manager_type;
type atfwd_service, service_manager_type;
type cne_service, service_manager_type;
type nfcEMV_hal_service, service_manager_type;
vim device/lge/bullhead/sepolicy/service_contexts
android.hardware.nfcEMV::INfcEMV u:object_r:nfcEMV_hal_service:s0
android.hardware.nfcEMV::NfcEMVEvent u:object_r:nfcEMV_hal_service:s0
android.hardware.nfcEMV::INfcEMVClientCallback u:object_r:nfcEMV_hal_service:s0
vim device/lge/bullhead/sepolicy/file_contexts
添加:
/vendor/bin/hw/android\.hardware\.nfcEMV@1\.0-service u:object_r:nfcEMV_hal_service:s0
android 8.0之后在只能在device/xxx/sepoilcy中添加avc權(quán)限,/sysetm/sepolicy/Android.mk 編譯的out生成路徑在 out/target/product/xxx/vendor/etc/selinux/
下面提供不用修改devices/設(shè)備名稱/sepolicy/ *.te 的方法
直接修改 :android-8.1.0_r15/system/sepolicy/private/service_contexts
window u:object_r:window_service:s0
gesture u:object_r:window_service:s0
* u:object_r:default_android_service:s0
gesture 就是Context定義的service name
修改之后需要在源碼目錄下面make selinux_policy -j11
會生成out/target/product/marlin/system/etc/selinux/plat_service_contexts
把這個文件adb root && adb remount && adb push plat_service_contexts /system/etc/selinux/ 重啟手機(jī)
或者make systemimage 然后使用fastboot flash system system.img 就可以了