赞
踩
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
总结c++创建服务和HIDL生成的一些步骤,本文未使用指令去生成创建hidl和对应的服务文件。
1.首先,在vendor/mediatek/proprietary/hardware/interfaces中创建文件夹testofhidl/1.0,
在上述的路径中,即…/interfaces,主要是mediatek存放HAL文件的地方,注意,在里面一般也有如下两个文件updat-hash.sh和updat-makefiles.sh,创建完成后,我们有如下路径:
vendor/mediatek/proprietary/hardware/interfaces/testofhidl/1.0
2.在testofhidl/1.0/下创建文件ITestOfHidl.hal和IDataCallback.hal,两者都是Hal文件,IDataCallback.hal是做回调用的,最后创建Android.bp文件,它们都是在…/testofhidl/1.0这个目录下的,它们的分别如下
ITestOfHidl.hal
package vendor.mediatek.hardware.testofhidl@1.0;
import vendor.mediatek.hardware.testofhidl@1.0::IDataCallback;
interface ITestOfHidl {
init();
release();
sendData(vec<uint8_t> data);
setDataCallback(IDataCallback callback) generates (uint32_t channel);
};
IDataCallback.hal
package vendor.mediatek.hardware.testofhidl@1.0;
interface IDataCallback {
onDataReceived(vec<uint8_t> data);
};
Android.bp
// This file is autogenerated by hidl-gen -Landroidbp. hidl_interface { name: "vendor.mediatek.hardware.testofhidl@1.0", root: "vendor.mediatek.hardware", srcs: [ "IDataCallback.hal", "ITestOfHidl.hal", ], interfaces: [ "android.hidl.base@1.0", ], gen_java: true, } subdirs = [ "default", ]
在…/testofhidl文件夹下也创建一个Android.bp文件
// This is an autogenerated file, do not edit.
subdirs = [
"1.0",
]
最后,使用vendor/mediatek/proprietary/hardware/interfaces中的updata-hash.sh增加一下current.txt的哈希值,可以看到current.txt多出这两行
af1b12d5eaba28900257dd15689aca72ee6badef0469fa73cb92893c2a416d80 vendor.mediatek.hardware.testofhidl@1.0::IDataCallback
7b3b7f0d9ba0833e46e368655e7add4a79c23979ae9f57139519e589f8ba4606 vendor.mediatek.hardware.testofhidl@1.0::ITestOfHidl
注意:如果没有updata-hash.sh这个脚本,可以参考https://blog.csdn.net/kehyuanyu/article/details/120904314?spm=1001.2014.3001.5502,里面有教你如何使用hild-gen生成hash的方法。
编译通过,以上就算完成了。
在vendor/mediatek/proprietary/hardware/interfaces/testofhidl/1.0/default/创建如下:
Android.bp
// FIXME: your file license if you have one cc_binary { name: "vendor.mediatek.hardware.testofhidl@1.0-service", relative_install_path: "hw", proprietary: true, vendor: true, defaults: ["hidl_defaults"], init_rc: ["vendor.mediatek.hardware.testofhidl@1.0-service.rc"], srcs: [ "TestOfHidl.cpp", "service.cpp" ], shared_libs: [ "liblog", "libcutils", "libdl", "libbase", "libutils", "libhardware", "libhidlbase", "vendor.mediatek.hardware.testofhidl@1.0", ], }
TestOfHidl.cpp
// FIXME: your file license if you have one #define TAG "testofhidl-1.0-service" #include "TestOfHidl.h" namespace vendor::mediatek::hardware::testofhidl::implementation { // Methods from ::vendor::mediatek::hardware::testofhidl::V1_0::ITestOfHidl follow. Return<void> TestOfHidl::init() { // TODO implement std::thread th(&TestOfHidl::myLoop, this); if(th.joinable()){ th.detach(); } return Void(); } void TestOfHidl::myLoop() { while(true){ if(!deqIn.empty()){ char *p = deqIn.front(); std::vector<uint8_t> out; //对通过client中使用sendData()传进来的byte进行修改 //byte[] p = {}的第二位固定为1 p[1] = 1; covertArray2Vector(p, 6, out); mCallback->onDataReceived(out); deqIn.pop_front(); } } } Return<void> TestOfHidl::release() { // TODO implement return Void(); } void TestOfHidl::covertVector2Array(std::vector<uint8_t> in, char *out) { int size = in.size(); for (int i = 0; i < size; i++) { out[i] = in.at(i); } } void TestOfHidl::covertArray2Vector(const char *in, int len, std::vector<uint8_t> &out) { out.clear(); for (int i = 0; i < len; i++) { out.push_back(in[i]); } } Return<void> TestOfHidl::sendData(const hidl_vec<uint8_t>& data) { // TODO implement char *cstr_data = new char[data.size() + 1]; covertVector2Array(data, cstr_data); deqIn.push_back(cstr_data); return Void(); } TestOfHidl::TestOfHidl(): callback_map({}), mChd(this){} Return<void> TestOfHidl::setDataCallback(const sp<::vendor::mediatek::hardware::testofhidl::V1_0::IDataCallback>& callback) { // TODO implement channel_id++; mCallback = callback; if (mChd != nullptr) { LOGD("linkToDeath\n"); callback->linkToDeath(mChd, channel_id); } else { LOGE("mChd is null\n"); } return channel_id; } void TestOfHidl::serviceDied(uint64_t cookie, const android::wp<::android::hidl::base::V1_0::IBase>& /*who*/) { LOGE("client is crash, channel_id = %lu!!!", cookie); int count = callback_map.erase(cookie); if(count == 1){ callback_interface_usage[cookie] = false; }else if(count > 1){ LOGE("error callback_map, please check callback_map !!!"); } } // Methods from ::android::hidl::base::V1_0::IBase follow. //ITestOfHidl* HIDL_FETCH_ITestOfHidl(const char* /* name */) { //return new TestOfHidl(); //} // } // namespace vendor::mediatek::hardware::testofhidl::implementation
TestOfHidl.h
// FIXME: your file license if you have one #pragma once #include <vendor/mediatek/hardware/testofhidl/1.0/ITestOfHidl.h> #include <hidl/MQDescriptor.h> #include <hidl/Status.h> #include <android/log.h> #include <thread> #include <deque> namespace vendor::mediatek::hardware::testofhidl::implementation { using ::android::hardware::hidl_array; using ::android::hardware::hidl_memory; using ::android::hardware::hidl_string; using ::android::hardware::hidl_vec; using ::android::hardware::Return; using ::android::hardware::Void; using ::android::sp; #define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG, __VA_ARGS__) #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG , TAG, __VA_ARGS__) #define LOGI(...) __android_log_print(ANDROID_LOG_INFO , TAG, __VA_ARGS__) #define LOGW(...) __android_log_print(ANDROID_LOG_WARN , TAG, __VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR , TAG, __VA_ARGS__) struct TestOfHidl : public V1_0::ITestOfHidl, android::hardware::hidl_death_recipient { // Methods from ::vendor::mediatek::hardware::testofhidl::V1_0::ITestOfHidl follow. Return<void> init() override; Return<void> release() override; Return<void> sendData(const hidl_vec<uint8_t>& data) override; Return<uint32_t> setDataCallback(const sp<::vendor::mediatek::hardware::testofhidl::V1_0::IDataCallback>& callback) override; void serviceDied(uint64_t cookie, const android::wp<::android::hidl::base::V1_0::IBase>& who) override; // Methods from ::android::hidl::base::V1_0::IBase follow. private: sp<V1_0::IDataCallback> mCallback = nullptr; ::android::sp<hidl_death_recipient> mChd; uint32_t channel_id = 0; std::deque<char*> deqIn; void myLoop(); void covertArray2Vector(const char *in, int len, std::vector<uint8_t> &out); void covertVector2Array(std::vector<uint8_t> in, char *out); public: TestOfHidl(); }; // FIXME: most likely delete, this is only for passthrough implementations // extern "C" ITestOfHidl* HIDL_FETCH_ITestOfHidl(const char* name); } // namespace vendor::mediatek::hardware::testofhidl::implementation
上述文件,通过hidl-gen生成,然后再自己修改部分内容。
vendor.mediatek.hardware.testofhidl@1.0-service.rc
service testofhidl-hal-1-0 /vendor/bin/hw/vendor.mediatek.hardware.testofhidl@1.0-service
class hal
user root
group system
service.cpp
#define TAG "testofhidl-1.0-service" #include <android/log.h> #include <hidl/HidlTransportSupport.h> #include <vendor/mediatek/hardware/testofhidl/1.0/ITestOfHidl.h> #include <hidl/LegacySupport.h> #include "TestOfHidl.h" using android::sp; using android::status_t; using android::OK; using android::hardware::configureRpcThreadpool; using android::hardware::joinRpcThreadpool; using android::hardware::defaultPassthroughServiceImplementation; using vendor::mediatek::hardware::testofhidl::V1_0::ITestOfHidl; using vendor::mediatek::hardware::testofhidl::implementation::TestOfHidl; int main() { //LOGD("testofhidl server0."); android::sp<ITestOfHidl> service = new TestOfHidl(); //LOGD("testofhidl server1."); configureRpcThreadpool(4, true /*callerWillJoin*/); status_t status = service->registerAsService(); if (status == OK) { //LOGD("testofhidl HAL Ready0."); service->init(); //LOGD("testofhidl HAL Ready1."); joinRpcThreadpool(); //LOGD("testofhidl HAL Ready2."); } LOGD("Cannot register testofhidl HAL service"); return 1; }
device/mediatek/mt_xxxx/device.mk添加如下
...
PRODUCT_PACKAGES += vendor.mediatek.hardware.testofhidl@1.0-service
PRODUCT_PACKAGES += vendor.mediatek.hardware.testofhidl@1.0
...
device/mediatek/mt_xxxx/manifest.xml添加如下
<hal format="hidl">
<name>vendor.mediatek.hardware.testofhidl</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>ITestOfHidl</name>
<instance>default</instance>
</interface>
</hal>
在添加了这一部分内容后,可能会报一个兼容性矩阵相关的错误(FAILED: out/target/product/T9530_Base_TP_VASA/obj/PACKAGING/check_vintf_all_intermediates/check_vintf_compatible_log),官方推荐的解决方法如下:
1. Update deprecated HALs to the latest version.
2. Check for any typos in device manifest or framework compatibility matrices with FCM version >= 5
3. For new platform HALs, add them to any framework compatibility matrix with FCM version >= 5 where applicable.
4. For device-specific HALs, add to DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE or DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE.: Success INCOMPATIBLE
根据官方推荐的解决方法,我们修改如下文件:
在/hardware/interfaces/compatibility_matricescompatibility_matrix.5.xml中添加如下
<hal format="hidl" optional="true">
<name>vendor.mediatek.hardware.testofhidl</name>
<version>1.0</version>
<interface>
<name>ITestOfHidl</name>
<instance>default</instance>
</interface>
</hal>
这部分完成后,也可以成功编译。
在/system/sepolicy/vendor/中新建hal_testofhidl_default.te
type hal_testofhidl_default, domain;
hal_server_domain(hal_testofhidl_default, hal_testofhidl)
type hal_testofhidl_default_exec, exec_type, vendor_file_type, file_type;
init_daemon_domain(hal_testofhidl_default)
在system/sepolicy/vendor/file_contexts中添加如下
/(vendor|system/vendor)/bin/hw/vendor\.mediatek\.hardware\.testofhidl@1\.0-service u:object_r:hal_testofhidl_default_exec:s0
在/system/sepolicy/public/新建hal_testofhidl.te
# HwBinder IPC from client to server, and callbacks
binder_call(hal_testofhidl_client, hal_testofhidl_server)
binder_call(hal_testofhidl_server, hal_testofhidl_client)
add_hwservice(hal_testofhidl_server, hal_testofhidl_hwservice)
allow hal_testofhidl_client hal_testofhidl_hwservice:hwservice_manager find;
在/system/sepolicy/public/hwservice.te添加如下
type hal_testofhidl_hwservice, hwservice_manager_type;
在system/sepolicy/public/attributes添加如下
hal_attribute(testofhidl);
在/system/sepolicy/prebuilts/api/30.0/public/创建hal_testofhidl.te(同步上方public修改)
# HwBinder IPC from client to server, and callbacks
binder_call(hal_testofhidl_client, hal_testofhidl_server)
binder_call(hal_testofhidl_server, hal_testofhidl_client)
add_hwservice(hal_testofhidl_server, hal_testofhidl_hwservice)
allow hal_testofhidl_client hal_testofhidl_hwservice:hwservice_manager find;
在system/sepolicy/prebuilts/api/30.0/public/hwservice.te做如下添加(同步上方public修改)
type hal_testofhidl_hwservice, hwservice_manager_type;
在system/sepolicy/prebuilts/api/30.0/public/attributes做如下添加(同步上方public修改)
hal_attribute(testofhidl);
在system/sepolicy/private/hwservice_contexts做如下添加
vendor.mediatek.hardware.testofhidl::ITestOfHidl u:object_r:hal_testofhidl_hwservice:s0
在system/sepolicy/private/compat/26.0/26.0.ignore.cil和
system/sepolicy/private/compat/27.0/27.0.ignore.cil和
system/sepolicy/private/compat/28.0/28.0.ignore.cil和
system/sepolicy/private/compat/29.0/29.0.ignore.cil做如下添加(这个根据自己实际情况添加)
hal_testofhidl_hwservice
在system/sepolicy/prebuilts/api/30.0/private/hwservice_contexts做如下添加
vendor.mediatek.hardware.testofhidl::ITestOfHidl u:object_r:hal_testofhidl_hwservice:s0
在system/sepolicy/prebuilts/api/30.0/private/compat/26.0/26.0.ignore.cil和
system/sepolicy/prebuilts/api/30.0/private/compat/27.0/27.0.ignore.cil和
system/sepolicy/prebuilts/api/30.0/private/compat/28.0/28.0.ignore.cil和
system/sepolicy/prebuilts/api/30.0/private/compat/29.0/29.0.ignore.cil做如下添加
hal_testofhidl_hwservice
编译后,将固件烧录到板子上,开机后,就可以查看到如下进程了
T9530_Base_TP_VASA:/ $ ps -A | grep testofhidl
system 527 1 10810148 4744 0 0 R vendor.mediatek.hardware.testofhidl@1.0-service
有如下修改
modified: device/mediatek/mt8195/device.mk modified: device/mediatek/mt8195/manifest.xml modified: system/sepolicy/prebuilts/api/30.0/private/compat/26.0/26.0.ignore.cil modified: system/sepolicy/prebuilts/api/30.0/private/compat/27.0/27.0.ignore.cil modified: system/sepolicy/prebuilts/api/30.0/private/compat/28.0/28.0.ignore.cil modified: system/sepolicy/prebuilts/api/30.0/private/compat/29.0/29.0.ignore.cil modified: system/sepolicy/prebuilts/api/30.0/private/hwservice_contexts modified: system/sepolicy/prebuilts/api/30.0/public/attributes modified: system/sepolicy/prebuilts/api/30.0/public/hwservice.te modified: system/sepolicy/private/compat/26.0/26.0.ignore.cil modified: system/sepolicy/private/compat/27.0/27.0.ignore.cil modified: system/sepolicy/private/compat/28.0/28.0.ignore.cil modified: system/sepolicy/private/compat/29.0/29.0.ignore.cil modified: system/sepolicy/private/hwservice_contexts modified: system/sepolicy/public/attributes modified: system/sepolicy/public/hwservice.te modified: system/sepolicy/vendor/file_contexts modified: vendor/mediatek/proprietary/hardware/interfaces/current.txt
有如下创建
system/sepolicy/prebuilts/api/30.0/public/hal_testofhidl.te
system/sepolicy/public/hal_testofhidl.te
system/sepolicy/vendor/hal_testofhidl_default.te
vendor/mediatek/proprietary/hardware/interfaces/testofhidl/
其中vendor/mediatek/proprietary/hardware/interfaces/testofhidl内包含如下添加
/1.0
Android.bp
IDataCallback.hal
ITestOfHidl.hal
/default
Android.bp
service.cpp
TestOfHidl.cpp
TestOfHidl.h
vendor.mediatek.hardware.testofhidl@1.0-service.rc
从/out/soong/.intermediates/vendor/mediatek/proprietary/hardware/interfaces/testofhidl/1.0/vendor.mediatek.hardware.testofhidl-V1.0-java/android_common/combined中获取如下包:
vendor.mediatek.hardware.testofhidl-V1.0-java.jar
使用Android Studio,将这个jar包放入app/libs中,右击这个包,点击add as library,build.gradle(Module)的dependencies会自动生成如下:
dependencies {
...
implementation files('libs\\vendor.mediatek.hardware.testofhidl-V1.0-java.jar')
...
}
从Android的原生代码里,prebuilt/sdk/30/system/获取android.jar,将获取到的jar包,替换掉D:\software\androidSDK\platforms\android-30的jar包,然后修改build.gradle(Module),compileSdk、minSdk、targetSdk全部改成30,如下
android {
compileSdk 30
defaultConfig {
applicationId "com.zzh.zzh.myapplication"
minSdk 30
targetSdk 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
...
}
在创建Client应用前,将这个Client应用设置为系统级应用,放置系统签名文件在Client项目的目录下,同时在build.gradle(Module)下增加如下:
android {
...
signingConfigs {
debug {
storeFile file("../keystore/platform_ok.jks")
storePassword = "xxxxxxxxxx"
keyAlias = "platform"
keyPassword = "xxxxxxxxxxx"
}
}
...
}
如何生成keystore文件,可以自行百度,
同时对AndroidManifest.xml增加android:sharedUserId=“android.uid.system”,表示该应用一定要和系统平台签名一致要不然应用无法被解析安装:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.zzh.zzh.myapplication"
android:sharedUserId="android.uid.system">
最后,其java代码如下:
package com.zzh.kk.myapplication; import androidx.appcompat.app.AppCompatActivity; import android.content.Intent; import android.os.Bundle; import android.os.RemoteException; import android.util.Log; import java.util.ArrayList; import java.util.Vector; import vendor.mediatek.hardware.touchserver.V1_0.IDataCallback; import vendor.mediatek.hardware.touchserver.V1_0.ITestOfHidl; public class MainActivity extends AppCompatActivity { private static final String TAG = "ApiImpl"; private ITestOfHidl mTestOfHidl; private int channel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); try { mTestOfHidl = ITestOfHidl.getService(); if (mTestOfHidl != null) { ArrayList<Byte> list = new ArrayList<Byte>(); byte[] data = {0x01, 0x00, 0x00, 0x01, 0x00, 0x01};; for (byte datum : data) { list.add(datum); } mTestOfHidl.sendData(list); channel= mTestOfHidl.setDataCallback(new IDataCallback.Stub() { @Override public void onDataReceived(ArrayList<Byte> data) throws RemoteException { if ( data != null) { byte[] result = new byte[data.size()]; Vector v1 = new Vector(data.size()); for (int i = 0; i < data.size(); i++) { result[i] = data.get(i); int k = result[i]&0xff; v1.add(i,Integer.toHexString(k)); Log.d(TAG, "v1 = " + v1.get(i)); } } } }); } mTestOfHidl.asBinder().linkToDeath(mDeathProxy, channel); } catch (RemoteException e) { e.printStackTrace(); } } private IHwBinder.DeathRecipient mDeathProxy = new IHwBinder.DeathRecipient() { @Override public void serviceDied(long cookie) { Log.d(TAG, "mService serviceDied++ channel id = " + cookie); //延时3s,等待服务启动 SystemClock.sleep(3000); //重连 try { mTestOfHidl = ITestOfHidl.getService(); if(mTestOfHidl != null){ channel = mTestOfHidl.setDataCallback(new IDataCallback.Stub(){...}); mTestOfHidl.asBinder().linkToDeath(mDeathProxy, channel); Log.d(TAG,"channel = " + channel); } } catch (RemoteException e) { e.printStackTrace(); } Log.d(TAG, "mService serviceDied--"); } }; }
AS中TAG为ApiImpl的logcat可以看到如下:
https://blog.csdn.net/u013357557/article/details/84561652
https://blog.csdn.net/kehyuanyu/article/details/120904314?spm=1001.2014.3001.5502
https://www.codeleading.com/article/68254488842/#%E4%B8%89%E3%80%81SELinux%E9%83%A8%E5%88%86%E2%80%94%E2%80%94hal%20service
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。