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 -- 接口定义

1.2 使用hidl-gen生成变量

1.3 实现主程序CPP

1.4 VNDK相关

二、device部分

三、SELinux部分 -- hal service

3.1 vendor目录

3.2 public目录

3.3 private目录

四、framewors层实现

4.1 System Service 实现

4.1.1 Manager

4.1.2 Service端

4.1.3  添加Selinux策略

4.1.4  编译

4.2 APP实现调用

4.2.1 APP调用主Activity

4.2.2 Layout文件

4.2.2 Makefile文件Android.mk

参考资料


一、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:l

Android 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)

android treble项目&&HIDL学习总结

安卓HAL开发指南

Android P HIDL demo代码编写

Android Automotive VehicleService

Android HIDL 详解