Android 10 HAL 层添加HIDL实现过程
Posted fulszcd
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 10 HAL 层添加HIDL实现过程相关的知识,希望对你有一定的参考价值。
本文以跑步机为假想场景介绍如何在android Q(10)上添加HIDL,内容涉及HAL、HIDL进程间通讯、多线程以及串口操作,涵盖了标准的Android硬件服务的主要技术。编写时参考了两篇博客(见参考资料)经调试、扩充、查缺补漏而成。记录此文为后来者避坑,代码在RK3399_Android_10代码上验证通过。
目录
一、Hardware Interface
1.1 编写HAL -- 接口定义
源码目录下新建hardware/interfaces/ledtreadmill/1.0目录,然后创建文件
ILedTreadmill.hal (主接口)
package android.hardware.ledtreadmill@1.0;
import ILedTreadmillCallback;
interface ILedTreadmill
OpenInitSerialPort(string address, int32_t baudrate, int32_t flags);
StartRead();//开始读取
StopRead();//结束读取
RCtlUnlock(int32_t inTime) generates (bool ret);//解锁
RCtlLock() generates (bool ret);
RCtlSetWeight(int32_t inWeight) generates (bool ret);//设置体重 -- 计算卡路里用途 单位0.1千克
RCtlSetResumeType(bool inToMinSpeed) generates (bool ret);
RCtlStart() generates (int32_t ret);//开始
RCtlFastSpeed(int32_t inSpeed) generates (int32_t ret); // 快捷速度 1 - 12 千米每小时
RCtlFastIncline(int32_t inIncline) generates (int32_t ret); // 快捷速度 1 - 12 千米每小时
RCtlIncSpeed() generates (int32_t ret); //速度加
RCtlDecSpeed() generates (int32_t ret); //速度减
RCtlIncIncline() generates (int32_t ret); //坡度加
RCtlDecIncline() generates (int32_t ret); //坡度减
RCtlSetUnit(int32_t inUnit) generates (bool ret); //
RCtlPause() generates (bool ret); //暂停
RCtlResume() generates (bool ret); //继续
RCtlStop() generates (bool ret); //停止
setCallBack(ILedTreadmillCallback callback) generates (bool ret);//回调读取的数据
;
ILedTreadmillCallback.hal (回调接口)
package android.hardware.ledtreadmill@1.0;
interface ILedTreadmillCallback
oneway onKeyDown(int32_t inKeyCode);
oneway onKeyPress(int32_t inKeyCode);
oneway onKeyUp(int32_t inKeyCode);
oneway onFastSpeedKnobScroll(int32_t inKnobSpeed, int32_t inKnobType);//快速速度旋钮按键消息
oneway onStartCountdown(); //倒计时开始
oneway onCountdown(int32_t inCount); //倒计时
oneway onStartRun(); //开始跑步
oneway onStopRun(); //停止跑步
oneway onTargetSpeedChange(int inSpeed); //目标速度变化
oneway onTargetInclineChange(int inIncline); //目标扬升变化
oneway onTargetSpeedStatusChange(int inStatus); //目标速度 显示与隐藏 1 显示 0 隐藏
oneway onTargetInclineStatusChange(int inStatus); //目标扬升 显示与隐藏 1 显示 0 隐藏
;
1.2 使用hidl-gen生成变量
首先确保代码进行过完全编译,然后执行 make hidl-gen -j4
. /opt/openjdk8-env.sh
source build/envsetup.sh
lunch rk3399_Android10-userdebug
make -j8
make hidl-gen -j4
设置临时变量
PACKAGE=android.hardware.ledtreadmill@1.0
LOC=hardware/interfaces/ledtreadmill/1.0/default
使用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
使用update-makefiles.sh生成1.0目录下的Android.bp
./hardware/interfaces/update-makefiles.sh
此时的目录结构为
.
└── 1.0
├── Android.bp
├── default
│ ├── Android.bp
│ ├── LedTreadmillCallback.cpp
│ ├── LedTreadmillCallback.h
│ ├── LedTreadmill.cpp
│ └── LedTreadmill.h
├── ILedTreadmillCallback.hal
└── ILedTreadmill.hal
1.3 实现主程序CPP
LetTreadmill.h 代码由前文生成,手动增加了日志定义
// FIXME: your file license if you have one
#pragma once
#include <android/hardware/ledtreadmill/1.0/ILedTreadmill.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
#include "android/log.h"
static const char *TAG="LedTreadmill";
#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__)
namespace android
namespace hardware
namespace ledtreadmill
namespace V1_0
namespace 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;
struct LedTreadmill : public ILedTreadmill
// Methods from ::android::hardware::ledtreadmill::V1_0::ILedTreadmill follow.
Return<void> OpenInitSerialPort(const hidl_string& address, int32_t baudrate, int32_t flags) override;
Return<void> StartRead() override;
Return<void> StopRead() override;
Return<void> RCtlUnlock(int32_t inTime) override;
Return<void> RCtlLock() override;
Return<void> RCtlSetWeight(int32_t inWeight) override;
Return<void> RCtlSetResumeType(bool inToMinSpeed) override;
Return<void> RCtlStart() override;
Return<void> RCtlFastSpeed(int32_t inSpeed) override;
Return<void> RCtlFastIncline(int32_t inIncline) override;
Return<void> RCtlIncSpeed() override;
Return<void> RCtlDecSpeed() override;
Return<void> RCtlIncIncline() override;
Return<void> RCtlDecIncline() override;
Return<void> RCtlSetUnit(int32_t inUnit) override;
Return<void> RCtlPause() override;
Return<void> RCtlResume() override;
Return<void> RCtlStop() override;
Return<void> setCallBack(const sp<::android::hardware::ledtreadmill::V1_0::ILedTreadmillCallback>& callback) override;
// Methods from ::android::hidl::base::V1_0::IBase follow.
;
// FIXME: most likely delete, this is only for passthrough implementations
// extern "C" ILedTreadmill* HIDL_FETCH_ILedTreadmill(const char* name);
// namespace implementation
// namespace V1_0
// namespace ledtreadmill
// namespace hardware
// namespace android
LetTreadmill.cpp
// FIXME: your file license if you have one
#include <bitset>
#include <cstring>
#include <fcntl.h>
#include <list>
#include <stdio.h>
#include <thread>
#include <termios.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <sstream>
#include <vector>
#include <mutex>
#include "LedTreadmill.h"
using namespace std;
typedef unsigned char UC;
namespace android
namespace hardware
namespace ledtreadmill
namespace V1_0
namespace implementation
#define OUTPUT_HEX_COLS 16
void output_Hex(const unsigned char *ucPtr, int iNumBytes);
int fd = -1;
sp<ILedTreadmillCallback> mCallback = nullptr;
pthread_t mReadThread;//读取数据线程
pthread_t mWriteThread;//写入数据线程
//获取波特率
static int getBaudrate(int baudrate)
switch(baudrate)
case 0: return B0;
case 50: return B50;
case 75: return B75;
case 110: return B110;
case 134: return B134;
case 150: return B150;
case 200: return B200;
case 300: return B300;
case 600: return B600;
case 1200: return B1200;
case 1800: return B1800;
case 2400: return B2400;
case 4800: return B4800;
case 9600: return B9600;
case 19200: return B19200;
case 38400: return B38400;
case 57600: return B57600;
case 115200: return B115200;
case 230400: return B230400;
case 460800: return B460800;
case 500000: return B500000;
case 576000: return B576000;
case 921600: return B921600;
case 1000000: return B1000000;
case 1152000: return B1152000;
case 1500000: return B1500000;
case 2000000: return B2000000;
case 2500000: return B2500000;
case 3000000: return B3000000;
case 3500000: return B3500000;
case 4000000: return B4000000;
default: return -1;
//读取串口数据
int UART_recv(void *buf, int len)
//LOGD("UART_recv");
//定义读事件集合
fd_set fdRead;
int ret;
struct timeval aTime;
FD_ZERO(&fdRead);
FD_SET(fd,&fdRead);
aTime.tv_sec = 0;
aTime.tv_usec = 300000; //300ms
//ret = select(fd + 1, &fdRead, NULL, NULL, &aTime );
ret = select(fd + 1, &fdRead, NULL, NULL, NULL);
if (ret < 0)
//关闭串口
close(fd);
else if (ret > 0)
//判断是否读事件
if (FD_ISSET(fd,&fdRead))
//data available, so get it!
ret = read(fd, buf, len);
// 对接收的数据进行处理,这里为简单的数据回发
return ret;
//读取一位数据
void recvOne(UC receiveBuffer[], int index)
while(!UART_recv(&receiveBuffer[index], 1))
LOGD("recvOne ---1--- recv error");
void *runRead(void* run)
long time = (long)run;
int iLCnt = 0;
LOGD("runRead %lu", time);
UC receiveBuffer[256];
int receiveLength;
while(1) //读取一包数据
receiveLength = 0;
recvOne(receiveBuffer, receiveLength++);//读取第一位
if (receiveBuffer[receiveLength - 1] == 0x10)
for(int i = 0; i < 15; i++)
//LOGD("runRead --- read = %d", receiveBuffer[i]);
recvOne(receiveBuffer, receiveLength++);
output_Hex(receiveBuffer, 16);
if(iLCnt % 30 == 0)
LOGD("NMW runRead while: %d", iLCnt);
if(mCallback != nullptr)
if(iLCnt % 60 == 0)
mCallback->onKeyPress(iLCnt);
else
mCallback->onTargetSpeedChange(iLCnt);
++iLCnt;
usleep(10 * 1000);
// Methods from ::android::hardware::ledtreadmill::V1_0::ILedTreadmill follow.
Return<void> LedTreadmill::OpenInitSerialPort(const hidl_string& address, int32_t baudrate, int32_t flags)
// TODO implement
LOGD("OpenInitSerialPort");
int speed;
speed = getBaudrate(baudrate);
if (speed == -1)
return Void();
char c[20];
strcpy(c, address.c_str());
if (flags == 0)
fd = open(c, O_RDWR|O_NOCTTY);
if(fd < 0)
LOGD("open uart device error\\n");
struct termios cfg;
if (tcgetattr(fd, &cfg) < 0)
close(fd);
return Void();
cfmakeraw(&cfg);
cfsetispeed(&cfg, speed);
cfsetospeed(&cfg, speed);
//修改控制模式,保证程序不会占用串口?
cfg.c_cflag |= CLOCAL;
//printf("c_cflag |= CLOCAL => %x\\r\\n", new_opt.c_cflag);
//修改控制模式,使得能够从串口读取输入数据
cfg.c_cflag |= CREAD;
//printf("c_cflag |= CREAD => %x\\r\\n", new_opt.c_cflag);
if (tcsetattr(fd, TCSANOW, &cfg) < 0)
close(fd);
return Void();
return Void();
Return<void> LedTreadmill::StartRead()
// TODO implement
int read = 1;
LOGD("StartRead");
pthread_create(&mReadThread, nullptr, runRead, &read);
return Void();
Return<void> LedTreadmill::StopRead()
// TODO implement
LOGD("StopRead");
return Void();
Return<bool> LedTreadmill::RCtlUnlock(int32_t inTime)
// TODO implement
LOGD("RCtlUnlock:%d", inTime);
return bool ;
Return<bool> LedTreadmill::RCtlLock()
// TODO implement
LOGD("RCtlLock");
return bool ;
Return<bool> LedTreadmill::RCtlSetWeight(int32_t inWeight)
// TODO implement
LOGD("RCtlSetWeight:%d", inWeight);
return bool ;
Return<bool> LedTreadmill::RCtlSetResumeType(bool inToMinSpeed)
// TODO implement
if(inToMinSpeed)
LOGD("RCtlSetResumeType to MinSpeed");
else
LOGD("RCtlSetResumeType False");
return bool ;
Return<int32_t> LedTreadmill::RCtlStart()
// TODO implement
LOGD("RCtlStart");
return int32_t ;
Return<int32_t> LedTreadmill::RCtlFastSpeed(int32_t inSpeed)
// TODO implement
LOGD("RCtlFastSpeed:%d", inSpeed);
return int32_t ;
Return<int32_t> LedTreadmill::RCtlFastIncline(int32_t inIncline)
// TODO implement
LOGD("RCtlFastIncline:%d", inIncline);
return int32_t ;
Return<int32_t> LedTreadmill::RCtlIncSpeed()
// TODO implement
LOGD("RCtlIncSpeed");
return int32_t ;
Return<int32_t> LedTreadmill::RCtlDecSpeed()
// TODO implement
LOGD("RCtlDecSpeed");
return int32_t ;
Return<int32_t> LedTreadmill::RCtlIncIncline()
// TODO implement
LOGD("RCtlIncIncline");
return int32_t ;
Return<int32_t> LedTreadmill::RCtlDecIncline()
// TODO implement
LOGD("RCtlDecIncline");
return int32_t ;
Return<bool> LedTreadmill::RCtlSetUnit(int32_t inUnit)
// TODO implement
LOGD("RCtlSetUnit:%d", inUnit);
return bool ;
Return<bool> LedTreadmill::RCtlPause()
// TODO implement
LOGD("RCtlPause");
return bool ;
Return<bool> LedTreadmill::RCtlResume()
// TODO implement
LOGD("RCtlResume");
return bool ;
Return<bool> LedTreadmill::RCtlStop()
// TODO implement
LOGD("RCtlStop");
return bool ;
Return<bool> LedTreadmill::setCallBack(const sp<::android::hardware::ledtreadmill::V1_0::ILedTreadmillCallback>& callback)
// TODO implement
LOGD("setCallback");
mCallback = callback;
return bool ;
void output_Hex(const unsigned char *ucPtr, int iNumBytes)
int rowIdx, colIdx;
const unsigned char *iPtr = ucPtr;
char buf[128];
char *ptr = buf;
for (rowIdx = 0;
rowIdx < (iNumBytes + OUTPUT_HEX_COLS - 1) / OUTPUT_HEX_COLS; rowIdx++)
ptr = buf;
sprintf(ptr, "%08XH ", rowIdx * OUTPUT_HEX_COLS);
ptr += 10;
int offset = rowIdx * OUTPUT_HEX_COLS;
/* output hex characters */
for (colIdx = 0; colIdx < OUTPUT_HEX_COLS; colIdx++)
if ((offset + colIdx) >= iNumBytes)
sprintf(ptr, "%s", " ");
ptr += 3;
else
if ((colIdx + 1) == (OUTPUT_HEX_COLS / 2))
sprintf(ptr, "%02X ", (int)(iPtr[offset + colIdx]));
ptr += 5;
else
sprintf(ptr, "%02X ", (int)(iPtr[offset + colIdx]));
ptr += 3;
/* end-for (colIdx) */
sprintf(ptr, "%s", " ");
ptr += 3;
/* output ascii characters (if printable) */
for (colIdx = 0; colIdx < OUTPUT_HEX_COLS; colIdx++)
if ((offset + colIdx) >= iNumBytes)
sprintf(ptr, "%s", " ");
else if ((iPtr[offset + colIdx] >= 33) && (iPtr[offset + colIdx] <= 126))
sprintf(ptr, "%c", (char)(iPtr[offset + colIdx]));
else
sprintf(ptr, "%s", ".");
++ptr;
/* end-for (colIdx) */
LOGI("%s", buf);
/* end-for (rowIdx) */
return;
// Methods from ::android::hidl::base::V1_0::IBase follow.
//ILedTreadmill* HIDL_FETCH_ILedTreadmill(const char* /* name */)
//return new LedTreadmill();
//
//
// namespace implementation
// namespace V1_0
// namespace ledtreadmill
// namespace hardware
// namespace android
添加启动脚本
新建android.hardware.ledtreadmill@1.0-service.rc脚本
service ledtreadmill-hal-1-0 /vendor/bin/hw/android.hardware.ledtreadmill@1.0-service
class hal
user system
group system
新建service.cpp 用来启动并初始化
#define LOG_TAG "ledtreadmill-1.0-service"
#include <android/log.h>
#include <hidl/HidlTransportSupport.h>
#include "LedTreadmill.h"
using android::sp;
using android::status_t;
using android::OK;
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
using android::hardware::ledtreadmill::V1_0::ILedTreadmill;
using android::hardware::ledtreadmill::V1_0::implementation::LedTreadmill;
int main(int /* argc */, char* /* argv */ [])
android::sp<ILedTreadmill> service = new LedTreadmill();
configureRpcThreadpool(4, true /*callerWillJoin*/);
status_t status = service->registerAsService();
if (status == OK)
LOGD("LedTreadmill HAL Ready.");
service->initSerialPort("/dev/ttyS1", 9600, 0);
service->startRead();
joinRpcThreadpool();
LOGD("Cannot register LedTreadmill HAL service");
return 1;
修改Android.bp 注意仔细检查
// FIXME: your file license if you have one
cc_library_shared
// FIXME: this should only be -impl for a passthrough hal.
// In most cases, to convert this to a binderized implementation, you should:
// - change '-impl' to '-service' here and make it a cc_binary instead of a
// cc_library_shared.
// - add a *.rc file for this module.
// - delete HIDL_FETCH_I* functions.
// - call configureRpcThreadpool and registerAsService on the instance.
// You may also want to append '-impl/-service' with a specific identifier like
// '-vendor' or '-<hardware identifier>' etc to distinguish it.
name: "android.hardware.ledtreadmill@1.0-impl",
relative_install_path: "hw",
// FIXME: this should be 'vendor: true' for modules that will eventually be
// on AOSP.
proprietary: true,
srcs: [
"LedTreadmill.cpp",
"LedTreadmillCallback.cpp",
],
shared_libs: [
"libhidlbase",
"libhidltransport",
"libutils",
"android.hardware.ledtreadmill@1.0",
],
cc_binary
name: "android.hardware.ledtreadmill@1.0-service",
relative_install_path: "hw",
defaults: ["hidl_defaults"],
proprietary: true,
init_rc: ["android.hardware.ledtreadmill@1.0-service.rc"],
srcs: [
"LedTreadmill.cpp",
"service.cpp",
],
shared_libs: [
"libbase",
"liblog",
"libdl",
"libutils",
"libhardware",
"libhidlbase",
"libhidltransport",
"android.hardware.ledtreadmill@1.0",
],
调用update-makefiles.sh更新一下
当前目录结构:
.
└── 1.0
├── Android.bp
├── default
│ ├── Android.bp
│ ├── android.hardware.ledtreadmill@1.0-service.rc
│ ├── LedTreadmillCallback.cpp
│ ├── LedTreadmillCallback.h
│ ├── LedTreadmill.cpp
│ ├── LedTreadmill.h
│ └── service.cpp
├── ILedTreadmillCallback.hal
└── ILedTreadmill.hal
单独编译一下,并排错
mm ./hardware/interfaces/ledtreadmill/1.0
1.4 VNDK相关
目录build/target/product/gsi下,current.txt与29.txt按字母顺序添加
VNDK-core: android.hardware.ledtreadmill@1.0.so
二、device部分
我们使用RK3399来做,lunch是rk3399_Android10-userdebug,device/rockchip/rk3399目录下修改device.mk和manifest.xml,这里根据自己的环境变通。如果配置了ab分区manifest.xml可能是manifest_ab.xml
device.mk
# ledtreadmill HAL
PRODUCT_PACKAGES += \\
android.hardware.ledtreadmill@1.0-service \\
android.hardware.ledtreadmill@1.0-impl
manifest.xml
<hal format="hidl">
<name>android.hardware.ledtreadmill</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>ILedTreadmill</name>
<instance>default</instance>
</interface>
</hal>
三、SELinux部分 -- hal service
3.1 vendor目录
file_contexts增加
/(vendor|system/vendor)/bin/hw/android\\.hardware\\.ledtreadmill@1\\.0-service u:object_r:hal_ledtreadmill_default_exec:s0
新建hal_ledtreadmill_default.te
type hal_ledtreadmill_default, domain;
hal_server_domain(hal_ledtreadmill_default, hal_ledtreadmill)
type hal_ledtreadmill_default_exec, exec_type, vendor_file_type, file_type;
init_daemon_domain(hal_ledtreadmill_default)
allow hal_ledtreadmill_default serial_device:chr_file rw_file_perms;
3.2 public目录
attributes添加
hal_attribute(ledtreadmill);
新建hal_ledtreadmill.te
# HwBinder IPC from client to server, and callbacks
binder_call(hal_ledtreadmill_client, hal_ledtreadmill_server)
binder_call(hal_ledtreadmill_server, hal_ledtreadmill_client)
add_hwservice(hal_ledtreadmill_server, hal_ledtreadmill_hwservice)
allow hal_ledtreadmill_client hal_ledtreadmill_hwservice:hwservice_manager find;
然后同步到prebuilts/api/29.0/public
3.3 private目录
hwservice_contexts添加
android.hardware.ledtreadmill::ILedTreadmill u:object_r:hal_ledtreadmill_hwservice:s0
private/compat/28.0/28.0.ignore.cil private/compat/27.0/27.0.ignore.cil
private/compat/26.0/26.0.ignore.cil 三个文件均添加
hal_ledtreadmill_hwservice
然后同步到prebuilts/api/29.0/private
四、framewors层实现
4.1 System Service 实现
4.1.1 Manager
frameworks/base/core/java/android/os下创建ledtreadmill目录,在该目录下新建ILedTreadmillService.aidl与HAL层功能对应
// ILedTreadmillService.aidl
package android.os.ledtreadmill;
import android.os.ledtreadmill.ILedTreadmillListener;
// Declare any non-default types here with import statements
interface ILedTreadmillService
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
//解锁 -- 单位:分钟 超时后跑步机停止运行。
boolean RCtlUnlock(int inTime);
//关闭 -- 主动停止跑步机运行。
boolean RCtlLock();
//设置体重 -- 计算卡路里用途 单位0.1千克
boolean RCtlSetWeight(int inWeight);
//决定暂停后启动是否恢复到最小速度,(默认为true);
boolean RCtlSetResumeType(boolean inToMinSpeed);
//APK按键启动、停止、快捷速度。
int RCtlStart();
int RCtlFastSpeed(int inSpeed); // 快捷速度 1 - 12 千米每小时
int RCtlFastIncline(int inIncline); // 快捷速度 1 - 12 千米每小时
int RCtlIncSpeed(); //速度加
int RCtlDecSpeed(); //速度减
int RCtlIncIncline(); //坡度加
int RCtlDecIncline(); //坡度减
boolean RCtlSetUnit(int inUnit); //单位转换设置 0 为公制,1为英制。
boolean RCtlPause(); //暂停
boolean RCtlResume(); //继续
boolean RCtlStop(); //停止
boolean setLedTreadmillListener(ILedTreadmillListener listener);
创建ILedTreadmillListener.aidl,与回调接口对应
package android.os.ledtreadmill;
interface ILedTreadmillListener
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void onKeyDown(int inKeyCode);//键盘消息
void onKeyPress(int inKeyCode);//键盘消息
void onKeyUp(int inKeyCode);//键盘消息
void onFastSpeedKnobScroll(int inKnobSpeed, int inKnobType);//快速速度旋钮按键消息
void onStartCountdown(); //倒计时开始
void onCountdown(int inCount);//倒计时
void onStartRun(); //开始跑步
void onStopRun(); //停止跑步
void onTargetSpeedChange(int inSpeed); //目标速度变化
void onTargetInclineChange(int inIncline); //目标扬升变化
void onTargetSpeedStatusChange(int inStatus); //目标速度 显示与隐藏 1 显示 0 隐藏
void onTargetInclineStatusChange(int inStatus); //目标扬升 显示与隐藏 1 显示 0 隐藏
创建LedTreadmillListener.java
package android.os.ledtreadmill;
/**
* android.os.ledtreadmill
*/
public abstract class LedTreadmillListener extends ILedTreadmillListener.Stub
创建LedTreadmillManager.java供APP调用
package android.os.ledtreadmill;
import android.os.RemoteException;
import android.os.ledtreadmill.LedTreadmillListener;
import android.util.Log;
import android.os.ledtreadmill.ILedTreadmillService;
public class LedTreadmillManager
public static final String TAG = "LedTreadmillManager";
private ILedTreadmillService mService;
public LedTreadmillManager(ILedTreadmillService service)
mService = service;
public boolean RCtlUnlock(int inTime)
boolean bRet = false;
try
Log.d(TAG, "RCtlUnlock: ");
if(mService != null)
bRet = mService.RCtlUnlock(inTime);
catch (RemoteException e)
e.printStackTrace();
return bRet;
public boolean RCtlLock()
boolean bRet = false;
try
if(mService != null)
bRet = mService.RCtlLock();
catch (RemoteException e)
e.printStackTrace();
return bRet;
public boolean RCtlSetWeight(int inWeight)
boolean bRet = false;
try
Log.d(TAG, "IRCtlSetWeight: " + inWeight);
if(mService != null)
bRet = mService.RCtlSetWeight(inWeight);
catch (RemoteException e)
e.printStackTrace();
return bRet;
public boolean RCtlSetResumeType(boolean inToMinSpeed)
boolean bRet = false;
try
Log.d(TAG, "RCtlSetResumeType: ");
if(mService != null)
bRet = mService.RCtlSetResumeType(inToMinSpeed);
catch (RemoteException e)
e.printStackTrace();
return bRet;
public int RCtlStart()
int iRet = -16;
try
Log.d(TAG, "RCtlStart: ");
if(mService != null)
iRet = mService.RCtlStart();
catch (RemoteException e)
e.printStackTrace();
return iRet;
public int RCtlFastSpeed(int inSpeed)
int iRet = -16;
try
Log.d(TAG, "RCtlFastSpeed: ");
if(mService != null)
iRet = mService.RCtlFastSpeed(inSpeed);
catch (RemoteException e)
e.printStackTrace();
return iRet;
public int RCtlFastIncline(int inIncline)
int iRet = -16;
try
Log.d(TAG, "RCtlFastIncline: ");
if(mService != null)
iRet = mService.RCtlFastIncline(inIncline);
catch (RemoteException e)
e.printStackTrace();
return iRet;
public int RCtlIncSpeed()
int iRet = -16;
try
Log.d(TAG, "RCtlIncSpeed: ");
if(mService != null)
iRet = mService.RCtlIncSpeed();
catch (RemoteException e)
e.printStackTrace();
return iRet;
public int RCtlDecSpeed()
int iRet = -16;
try
Log.d(TAG, "RCtlDecSpeed: ");
if(mService != null)
iRet = mService.RCtlDecSpeed();
catch (RemoteException e)
e.printStackTrace();
return iRet;
public int RCtlIncIncline()
int iRet = -16;
try
Log.d(TAG, "RCtlIncIncline: ");
if(mService != null)
iRet = mService.RCtlIncIncline();
catch (RemoteException e)
e.printStackTrace();
return iRet;
public int RCtlDecIncline()
int iRet = -16;
try
Log.d(TAG, "RCtlDecIncline: ");
if(mService != null)
iRet = mService.RCtlDecIncline();
catch (RemoteException e)
e.printStackTrace();
return iRet;
public boolean RCtlSetUnit(int inUnit)
boolean bRet = false;
try
Log.d(TAG, "RCtlSetUnit: ");
if(mService != null)
bRet = mService.RCtlSetUnit(inUnit);
RCtlSetUnit(inUnit);
catch (RemoteException e)
e.printStackTrace();
return bRet;
public boolean RCtlPause()
boolean bRet = false;
try
Log.d(TAG, "IRCtlPause: ");
if(mService != null)
bRet = mService.RCtlPause();
catch (RemoteException e)
e.printStackTrace();
return bRet;
public boolean RCtlResume()
boolean bRet = false;
try
Log.d(TAG, "IRCtlResume: ");
if(mService != null)
bRet = mService.RCtlResume();
catch (RemoteException e)
e.printStackTrace();
return bRet;
public boolean RCtlStop()
boolean bRet = false;
try
Log.d(TAG, "IRCtlStop: ");
//AIDL传消息过来时的处理必须放异常处理,否则本地APK异常时抛出异常会导致远程AIDL调用发生错误、崩溃。
//代码写这里
if(mService != null)
bRet = mService.RCtlStop();
catch (RemoteException e)
e.printStackTrace();
return bRet;
public boolean setLedTreadmillListener(ILedTreadmillListener listener)
Log.d(TAG, "setLedTreadmillListener: ");
try
if (mService == null)
return false;
return mService.setLedTreadmillListener(listener);
catch (RemoteException e)
e.printStackTrace();
return false;
frameworks\\base\\Android.bp里添加
"core/java/android/os/ledtreadmill/ILedTreadmillListener.aidl",
"core/java/android/os/ledtreadmill/ILedTreadmillService.aidl",
4.1.2 Service端
frameworks/base/services/core/Android.bp添加引用
static_libs: [
......
"android.hardware.ledtreadmill-V1.0-java",
......
],
frameworks\\base\\services\\core\\java\\com\\android\\server下创建ledtreadmill目录,并新建文件 LedTreadmillService.java
package com.android.server.ledtreadmill;
import android.hardware.ledtreadmill.V1_0.ILedTreadmill;
import android.hardware.ledtreadmill.V1_0.ILedTreadmillCallback;
import android.os.RemoteException;
import android.util.Log;
import android.os.ledtreadmill.ILedTreadmillListener;
import android.os.ledtreadmill.ILedTreadmillService;
/**
* com.android.server.ledtreadmill.LedTreadmillService
*
* @author GW00175635
* @date 2019/7/11
*/
public class LedTreadmillService extends ILedTreadmillService.Stub
private String TAG = "LedTreadmillService";
private ILedTreadmill mHalLedService ;
public LedTreadmillService()
try
mHalLedService = ILedTreadmill.getService();//获取service
catch (RemoteException e)
e.printStackTrace();
@Override
public boolean RCtlUnlock(int inTime) throws RemoteException
Log.d(TAG, "RCtlUnlock: ");
mHalLedService.RCtlUnlock(inTime);
return true;
@Override
public boolean RCtlLock() throws RemoteException
Log.d(TAG, "RCtlLock: ");
mHalLedService.RCtlLock();
return true;
@Override
public boolean RCtlSetWeight(int inWeight) throws RemoteException
Log.d(TAG, "RCtlSetWeight: ");
mHalLedService.RCtlSetWeight(inWeight);
return true;
@Override
public boolean RCtlSetResumeType(boolean inToMinSpeed) throws RemoteException
Log.d(TAG, "RCtlSetResumeType: ");
mHalLedService.RCtlSetResumeType(inToMinSpeed);
return true;
@Override
public int RCtlStart() throws RemoteException
Log.d(TAG, "RCtlStart: ");
mHalLedService.RCtlStart();
return 0;
@Override
public int RCtlFastSpeed(int inSpeed) throws RemoteException
Log.d(TAG, "RCtlFastSpeed: ");
mHalLedService.RCtlFastSpeed(inSpeed);
return 0;
@Override
public int RCtlFastIncline(int inIncline) throws RemoteException
Log.d(TAG, "RCtlFastIncline: ");
mHalLedService.RCtlFastIncline(inIncline);
return 0;
@Override
public int RCtlIncSpeed() throws RemoteException
Log.d(TAG, "RCtlIncSpeed: ");
mHalLedService.RCtlIncSpeed();
return 0;
@Override
public int RCtlDecSpeed() throws RemoteException
Log.d(TAG, "RCtlDecSpeed: ");
mHalLedService.RCtlDecSpeed();
return 0;
@Override
public int RCtlIncIncline() throws RemoteException
Log.d(TAG, "RCtlIncIncline: ");
mHalLedService.RCtlIncIncline();
return 0;
@Override
public int RCtlDecIncline() throws RemoteException
Log.d(TAG, "RCtlDecIncline: ");
mHalLedService.RCtlDecIncline();
return 0;
@Override
public boolean RCtlSetUnit(int inUnit) throws RemoteException
Log.d(TAG, "RCtlSetUnit: ");
mHalLedService.RCtlSetUnit(inUnit);
return true;
@Override
public boolean RCtlPause() throws RemoteException
Log.d(TAG, "RCtlPause: ");
mHalLedService.RCtlPause();
return true;
@Override
public boolean RCtlResume() throws RemoteException
Log.d(TAG, "RCtlResume: ");
mHalLedService.RCtlResume();
return true;
@Override
public boolean RCtlStop() throws RemoteException
Log.d(TAG, "RCtlStop: ");
mHalLedService.RCtlStop();
return true;
@Override
public boolean setLedTreadmillListener(ILedTreadmillListener listener) throws RemoteException
Log.d(TAG, "setTestEventListener: ");
LedTreadmillCallback ltCallback = new LedTreadmillCallback(listener);
//return mHalLedService.setCallback(ltCallback);
return false;
class LedTreadmillCallback extends ILedTreadmillCallback.Stub
ILedTreadmillListener mILTListener;
LedTreadmillCallback (ILedTreadmillListener listener)
mILTListener = listener;
@Override
public void onKeyDown(int inKeyCode) throws RemoteException
Log.d(TAG, "onKeyDown: ");
mILTListener.onKeyDown(inKeyCode);
@Override
public void onKeyPress(int inKeyCode) throws RemoteException
Log.d(TAG, "onKeyPress: ");
mILTListener.onKeyPress(inKeyCode);
@Override
public void onKeyUp(int inKeyCode) throws RemoteException
Log.d(TAG, "onKeyUp: ");
mILTListener.onKeyUp(inKeyCode);
@Override
public void onFastSpeedKnobScroll(int inKnobSpeed, int inKnobType) throws RemoteException
Log.d(TAG, "onFastSpeedKnobScroll: ");
mILTListener.onFastSpeedKnobScroll(inKnobSpeed, inKnobType);
@Override
public void onStartCountdown() throws RemoteException
Log.d(TAG, "onStartCountdown: ");
mILTListener.onStartCountdown();
@Override
public void onCountdown(int inCount) throws RemoteException
Log.d(TAG, "onCountdown: ");
mILTListener.onCountdown(inCount);
@Override
public void onStartRun() throws RemoteException
Log.d(TAG, "onStartRun: ");
mILTListener.onStartRun();
@Override
public void onStopRun() throws RemoteException
Log.d(TAG, "onStopRun: ");
mILTListener.onStopRun();
在frameworks\\base\\core\\java\\android\\content\\Context.java里添加
/**
* @link android.os.ledtreadmill.LedTreadmillManager for receiving intents at a
* time of your choosing.
*
* @see #getSystemService(String)
* @see android.os.ledtreadmill.LedTreadmillManager
*/
public static final String LEDTREADMILL_SERVICE = "led_treadmill";
frameworks/base/core/java/android/app/SystemServiceRegistry.java里添加
import android.os.ledtreadmill.LedTreadmillManager;
import android.os.ledtreadmill.ILedTreadmillService;
......
registerService(Context.LEDTREADMILL_SERVICE, LedTreadmillManager.class,
new CachedServiceFetcher<LedTreadmillManager>()
@Override
public LedTreadmillManager createService(ContextImpl ctx)
IBinder iBinder = ServiceManager.getService(Context.LEDTREADMILL_SERVICE);
if (iBinder == null)
Log.d(TAG, "NMW get LedTreadmillManager return null");
return null;
ILedTreadmillService service = ILedTreadmillService.Stub
.asInterface(iBinder);
Log.d(TAG, "NMW get LedTreadmillManager return instance");
return new LedTreadmillManager(service);
);
......
在frameworks\\base\\services/java/com/android/server/SystemServer.java里添加
import com.android.server.ledtreadmill.LedTreadmillService;
......
/**
* Starts a miscellaneous grab bag of stuff that has yet to be refactored and organized.
*/
private void startOtherServices()
......
traceBeginAndSlog("MakeLedTreadmillServiceReady");
try
Slog.i(TAG, "LedTreadmill Service");
ServiceManager.addService(Context.LEDTREADMILL_SERVICE, new LedTreadmillService());
catch (Throwable e)
reportWtf("starting LedTreadmillService", e);
traceEnd();
......
4.1.3 添加Selinux策略
public/service.te添加
type ledtreadmill_service, system_api_service, system_server_service, service_manager_type;
private/service_contexts添加--注意这里的led_treadmill要与前文添加的Context.LEDTREADMILL_SERVICE保持一致
led_treadmill u:object_r:ledtreadmill_service:s0
private/system_server.te添加
hal_client_domain(system_server, hal_ledtreadmill)
private/compat/28.0/28.0.ignore.cil private/compat/27.0/27.0.ignore.cil 以及
private/compat/26.0/26.0.ignore.cil添加
ledtreadmill_service
最后将这些修改同步到prebuilts/api/29.0/就完成了
4.1.4 编译
需要更新下API,然后才能编译通过
#./hardware/interfaces/update-makefiles.sh
make update-api
make -j8
4.2 APP实现调用
编写一个APP来测试验证下,packages/apps目录下新建LedTreadmill目录,内容比较简单--我们将主要文件放上来,缺少的自己补充下。
4.2.1 APP调用主Activity
package com.genlt.ledtreadmill;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ledtreadmill.LedTreadmillManager;
import android.os.ledtreadmill.LedTreadmillListener;
import android.view.View;
import android.widget.Button;
import android.util.Log;
/**
* MainaActivity
*/
public class MainActivity extends Activity implements View.OnClickListener
private final String TAG = "MainActivity";
LedTreadmillManager mLedTreadmillManager;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLedTreadmillManager = (LedTreadmillManager)getSystemService(Context.LEDTREADMILL_SERVICE);
if(mLedTreadmillManager == null)
Log.d("activity", "Get service for mLedTreadmillManager failed." + Context.LEDTREADMILL_SERVICE);
else
Log.d("activity", "Get service for mLedTreadmillManager OK. " + Context.LEDTREADMILL_SERVICE);
Button btn_start, btn_stop, btn_custprogram, btn_pause;
Button btn_SpeedPlus, btn_SpeedDec;
Button btn_InclinePlus, btn_InclineDec;
Button btn_FastSpeedTwo, btn_FastSpeedSix;
Button btn_SetCallback;
btn_start = findViewById(R.id.btn_start);
btn_stop = findViewById(R.id.btn_stop);
btn_pause = findViewById(R.id.btn_pause);
btn_custprogram = findViewById(R.id.btn_custprogram);
btn_SpeedPlus = findViewById(R.id.btn_SpeedPlus);
btn_SpeedDec = findViewById(R.id.btn_SpeedDec);
btn_InclinePlus = findViewById(R.id.btn_InclinePlus);
btn_InclineDec = findViewById(R.id.btn_InclineDec);
btn_FastSpeedTwo = findViewById(R.id.btn_FastSpeedTwo);
btn_FastSpeedSix = findViewById(R.id.btn_FastSpeedSix);
btn_SetCallback = findViewById(R.id.button_setCallback);
btn_start.setOnClickListener(this);
btn_stop.setOnClickListener(this);
btn_pause.setOnClickListener(this);
btn_custprogram.setOnClickListener(this);
btn_SpeedPlus.setOnClickListener(this);
btn_SpeedDec.setOnClickListener(this);
btn_FastSpeedTwo.setOnClickListener(this);
btn_FastSpeedSix.setOnClickListener(this);
btn_InclinePlus.setOnClickListener(this);
btn_InclineDec.setOnClickListener(this);
btn_SetCallback.setOnClickListener(this);
@Override
public void onClick(View view)
Log.d(TAG, "onClick");
// TODO Auto-generated method stub
switch (view.getId())
case R.id.btn_start:
if(mLedTreadmillManager != null)
Log.d(TAG, "btn_start: ");
mLedTreadmillManager.RCtlStart();
else
Log.d(TAG, "mLedTreadmillManager is null: ");
break;
case R.id.btn_stop:
if(mLedTreadmillManager != null)
Log.d(TAG, "btn_stop: ");
mLedTreadmillManager.RCtlStart();
else
Log.d(TAG, "mLedTreadmillManager is null: ");
break;
case R.id.btn_SpeedPlus:
if(mLedTreadmillManager != null)
Log.d(TAG, "btn_SpeedPlus: ");
mLedTreadmillManager.RCtlStart();
else
Log.d(TAG, "mLedTreadmillManager is null: ");
break;
case R.id.btn_SpeedDec:
if(mLedTreadmillManager != null)
Log.d(TAG, "btn_SpeedDec: ");
mLedTreadmillManager.RCtlStart();
else
Log.d(TAG, "mLedTreadmillManager is null: ");
break;
case R.id.btn_FastSpeedTwo:
if(mLedTreadmillManager != null)
Log.d(TAG, "btn_FastSpeedTwo: ");
mLedTreadmillManager.RCtlFastSpeed(20);
else
Log.d(TAG, "mLedTreadmillManager is null: ");
break;
case R.id.btn_FastSpeedSix:
if(mLedTreadmillManager != null)
Log.d(TAG, "btn_FastSpeedSix: ");
mLedTreadmillManager.RCtlFastSpeed(60);
else
Log.d(TAG, "mLedTreadmillManager is null: ");
break;
case R.id.btn_custprogram:
if(mLedTreadmillManager != null)
// Log.d(TAG, "btn_custprogram: ");
// int []Speeds = 12, 15, 8;
// int []Incs = 2, 1, 9;
// int []Durations = 50, 50, 50;
// mLedTreadmillManager.RCtlCustProgram(Speeds, Incs, Durations);
else
Log.d(TAG, "mLedTreadmillManager is null: ");
break;
case R.id.btn_pause:
if(mLedTreadmillManager != null)
Log.d(TAG, "btn_pause: ");
mLedTreadmillManager.RCtlPause();
else
Log.d(TAG, "mLedTreadmillManager is null: ");
break;
case R.id.btn_InclinePlus:
if(mLedTreadmillManager != null)
Log.d(TAG, "btn_InclinePlus: ");
mLedTreadmillManager.RCtlIncIncline();
else
Log.d(TAG, "mLedTreadmillManager is null: ");
break;
case R.id.btn_InclineDec:
if(mLedTreadmillManager != null)
Log.d(TAG, "btn_InclineDec: ");
mLedTreadmillManager.RCtlDecIncline();
else
Log.d(TAG, "mLedTreadmillManager is null: ");
break;
case R.id.button_setCallback:
Log.d(TAG, "button_setCallback");
mLedTreadmillManager.setLedTreadmillListener(new LedTreadmillListener()
@Override
public void onKeyDown(int inKeyCode)
Log.d(TAG, "onKeyDown: " + inKeyCode);
@Override
public void onKeyPress(int inKeyCode)
Log.d(TAG, "onKeyPress: " + inKeyCode);
@Override
public void onKeyUp(int inKeyCode)
Log.d(TAG, "onKeyUp: " + inKeyCode);
@Override
public void onFastSpeedKnobScroll(int inKnobSpeed, int inKnobType)
Log.d(TAG, "onFastSpeedKnobScroll inKnobSpeed: " + inKnobSpeed + " inKnobType:" + inKnobType);
@Override
public void onStartCountdown()
Log.d(TAG, "onStartCountdown: ");
@Override
public void onCountdown(int inCount)
Log.d(TAG, "onCountdown: " + inCount);
@Override
public void onStartRun()
Log.d(TAG, "onStartRun: ");
@Override
public void onStopRun()
Log.d(TAG, "onStopRun: ");
@Override
public void onTargetSpeedChange(int inSpeed)
Log.d(TAG, "onTargetSpeedChange: " + inSpeed);
@Override
public void onTargetInclineChange(int inIncline)
Log.d(TAG, "onTargetInclineChange: " + inIncline);
@Override
public void onTargetSpeedStatusChange(int inStatus)
Log.d(TAG, "onTargetSpeedStatusChange: " + inStatus);
@Override
public void onTargetInclineStatusChange(int inStatus)
Log.d(TAG, "onTargetInclineStatusChange: " + inStatus);
);
break;
default:
break;
4.2.2 Layout文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:orientation="horizontal">
<Button
android:id="@+id/btn_start"
android:layout_width="360dp"
android:layout_height="60dp"
android:gravity="center"
android:textSize="30sp"
android:text="启动 Start" />
<Button
android:id="@+id/btn_stop"
android:layout_width="360dp"
android:layout_height="60dp"
android:gravity="center"
android:textSize="30sp"
android:text="停止 Stop" />
</LinearLayout>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:orientation="horizontal">
<Button
android:id="@+id/btn_SpeedPlus"
android:layout_width="360dp"
android:layout_height="60dp"
android:gravity="center"
android:textSize="30sp"
android:text="加速 Plus" />
<Button
android:id="@+id/btn_SpeedDec"
android:layout_width="360dp"
android:layout_height="60dp"
android:gravity="center"
android:textSize="30sp"
android:text="减速 Dec" />
</LinearLayout>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:orientation="horizontal">
<Button
android:id="@+id/btn_FastSpeedTwo"
android:layout_width="360dp"
android:layout_height="60dp"
android:gravity="center"
android:textSize="30sp"
android:text="速度(Speed) 2 " />
<Button
android:id="@+id/btn_FastSpeedSix"
android:layout_width="360dp"
android:layout_height="60dp"
android:gravity="center"
android:textSize="30sp"
android:text="速度(Speed) 6 " />
</LinearLayout>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:orientation="horizontal">
<Button
android:id="@+id/btn_custprogram"
android:layout_width="360dp"
android:layout_height="60dp"
android:gravity="center"
android:textSize="30sp"
android:visibility="invisible"
android:text="程式 CustProgram" />
<Button
android:id="@+id/btn_pause"
android:layout_width="360dp"
android:layout_height="60dp"
android:gravity="center"
android:textSize="30sp"
android:text="暂停 Pause"
/>
</LinearLayout>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:orientation="horizontal">
<Button
android:id="@+id/btn_InclinePlus"
android:layout_width="360dp"
android:layout_height="60dp"
android:gravity="center"
android:textSize="30sp"
android:text="扬升加 Incline Plus" />
<Button
android:id="@+id/btn_InclineDec"
android:layout_width="360dp"
android:layout_height="60dp"
android:gravity="center"
android:textSize="30sp"
android:text="扬升减 Incline Dec" />
</LinearLayout>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:lAndroid HIDL概述(一)
参考技术A
Android O(8.0) 版本之后,底层实现有了比较大的变化,最显著的一个方面就是 HIDL 机制的全面实施。本文及接下来的几篇博文将从 HIDL的基本概念 、 HIDL服务模拟 、 framework层aidl服务 、 应用层程序 这四个方面来全面的阐述 HIDL 工作全过程,这对于理解系统源码中 Gnss 、 Usb 、 Camera 等模块的工作原理有极大帮助。
在 Android O(8.0) 之前系统的升级牵扯多方协作,极为麻烦, HIDL 机制的推出就是将 framework 与 hal 层分开,使得框架部分可以直接被覆盖、更新,而不需要重新对 HAL 进行编译,这样在系统升级时, OEM 厂商 跳过 SoC 厂商,先对 framework 进行升级。
framework 与 hal 紧紧耦合存在于 system.img 中,因此在版本升级时需要: OEM 厂商适配 framework , SoC厂商 适配 hal , 之后将修改打包到 system.img ,生成 OTA 升级包,推送到手机进行 OTA 升级
framework 与 hal 进行了解耦, framework 存在于 system.img , hal 存在于 vendor.img ,进行版本升级时,分为两次升级:
正如上述所言,旧版的系统架构中, Android Framework 层与 Hal 层是打包成一个 system.img 的,且 Framework 与 hal 层之间是紧密耦合的,通过链接的方式使用相应的硬件 so 库。它们之间的架构一般有如下两种方式:
为了解决两者之间这种紧耦合所带来的弊端,google 引入 HIDL 来定义 Framework 与 HAL 之间的接口,可以用下图来描述:
事实上虽然 google 推出了这种机制,但是很多厂商没有很快的跟上节奏,因此为了向前兼容, google 定义了三种类型:
上述可总结为 :
[ 1 ] hidl
[ 2 ] hidl trebl 演进
以上是关于Android 10 HAL 层添加HIDL实现过程的主要内容,如果未能解决你的问题,请参考以下文章
HIDL(HAL interface definition langguage)