前面介绍了很多Android Automotive框架内的技术,最后分享一些自己使用方法。
硬件抽象层
首先在types.hal中定义新的车辆属性
代码路径:hardware\interfaces\automotive\vehicle\2.0\type.hal
/**
* NEW_VENDOR_PROPERTY
*
* @change_mode VehiclePropertyChangeMode:ONCHANGE
* @access VehiclePropertyAccess:READ_WRITE
*/
NEW_VENDOR_PROPERTY = (
0xAAAA
| VehiclePropertyGroup:VENDOR
| VehiclePropertyType:INT32
| VehicleArea:SEAT),
在types.hal中添加数据结构
enum NewVendorPropertyMenu : int32_t {
ENUM_1 = 0x1,
ENUM_2 = 0x2
};
代码路径:hardware\interfaces\automotive\vehicle\2.0\default\impl\vhal_v2_0\DefaultConfig.h
添加作用域配置。
constexpr int NEW_VENDOR_PROPERTY_AREA_1 = (int)VehicleAreaSeat::ROW_1_LEFT;
constexpr int NEW_VENDOR_PROPERTY_AREA_2 = (int)VehicleAreaSeat::ROW_1_RIGHT;
添加车辆属性配置
{.config =
{
.prop = toInt(VehicleProperty::NEW_VENDOR_PROPERTY),
.access = VehiclePropertyAccess::READ_WRITE,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
.areaConfigs = {
VehicleAreaConfig{.areaId = (int)(VehicleAreaSeat::ROW_1_LEFT), .minInt32Value = 0, .maxInt32Value = 5},
VehicleAreaConfig{.areaId = (int)(VehicleAreaSeat::ROW_1_RIGHT), .minInt32Value = 0, .maxInt32Value = 5}
},
},
.initialAreaValues = {
{(int)(VehicleAreaSeat::ROW_1_LEFT), {.int32Values = {toInt(NewVendorPropertyMenu::ENUM_1)} } },
{(int)(VehicleAreaSeat::ROW_1_RIGHT), {.int32Values = {toInt(NewVendorPropertyMenu::ENUM_2)} } },
}
},
添加车辆属性初始值
.initialAreaValues = {
{(int)(VehicleAreaSeat::ROW_1_LEFT), {.int32Values = {toInt(NewVendorPropertyMenu::ENUM_1)} } },
{(int)(VehicleAreaSeat::ROW_1_RIGHT), {.int32Values = {toInt(NewVendorPropertyMenu::ENUM_2)} } },
}
在EmulatedVehicleHal.cpp中测试加一个假回调
路径
hardware\interfaces\automotive\vehicle\2.0\default\impl\vhal_v2_0\EmulatedVehicleHal.cpp
StatusCode EmulatedVehicleHal::set(const VehiclePropValue& propValue) { ······ //mock hal callback event ALOGI("%s propId: 0x%x, areaId: 0x%x", __func__, propValue.prop, propValue.areaId); doHalEvent(getValuePool()->obtain(propValue)); //mock hal callback event ······ getEmulatorOrDie()->doSetValueFromClient(propValue); return StatusCode::OK; }
增加自定义类型
代码路径:hardware\interfaces\automotive\vehicle\2.0\Android.bp
types: [
"NewVendorPropertyMenu",
]
Android P版本之后不再使用
系统框架层 Car-lib
代码路径:packages\services\Car\car-lib\src\android\car\VehiclePropertyIds.java
public static final int NEW_VENDOR_PROPERTY = 624994986;/* (0xAAAA | VehiclePropertyGroup:VENDOR | VehiclePropertyType:INT32 | VehicleArea:SEAT) */
public static String toString(int o) {
if (o == NEW_VENDOR_PROPERTY) {
return "NEW_VENDOR_PROPERTY";
}
}
将carlib的修改加到这里
代码路径:packages\services\Car\car-lib\api\system-current.txt
field public static final int NEW_VENDOR_PROPERTY = 624994986; // 0x2540AAAA
系统框架层 CarService
代码路径:packages\services\Car\service\src\com\android\car\hal\PropertyHalServiceIds.java
将权限和property
对应放入map
里
mProps.put(VehicleProperty.NEW_VENDOR_PROPERTY, new Pair<>(
Car.PERMISSION_NEW_VENDOR_PROPERTY,
Car.PERMISSION_NEW_VENDOR_PROPERTY));
在AndroidManifest里加入权限。
代码路径: packages\services\Car\service\AndroidManifest.xml
<permission
android:name="android.car.permission.NEW_VENDOR_PROPERTY"
android:protectionLevel="system|signature"
android:label="@string/car_permission_vendor_property"
android:description="@string/car_permission_desc_vendor_property"
/>
private CarPropertyManager mCarPropertyManager;
private CarPropertyManager.CarPropertyEventCallback mCallback = new CarPropertyManager.CarPropertyEventCallback() {
@Override
public void onChangeEvent(CarPropertyValue carPropertyValue) {
//数据发生变化
switch (carPropertyValue.getPropertyId()) {
case VehiclePropertyIds.PERF_VEHICLE_SPEED:
//数据发生变化
float value = (float) carPropertyValue.getValue();
break;
default:
}
}
@Override
public void onErrorEvent(int i, int i1) {
//发生错误
}
};
private void init() {
//创建Car实例
car = Car.createCar(mContext, new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//和服务绑定成功
//获取CarPropertyManager实例
mCarPropertyManager = (CarPropertyManager) car.getCarManager(Car.PROPERTY_SERVICE);
//订阅一个属性,变化时获取通知
mCarPropertyManager.registerCallback(mCallback, VehiclePropertyIds.PERF_VEHICLE_SPEED, CarPropertyManager.SENSOR_RATE_NORMAL);
//获取一个属性值
mCarPropertyManager.getIntProperty(VehiclePropertyIds.PERF_VEHICLE_SPEED, 0);
//设置一个属性值
mCarPropertyManager.setIntProperty(VehiclePropertyIds.HVAC_FAN_SPEED, VehicleAreaSeat.SEAT_ROW_1_LEFT, 0);
}
@Override
public void onServiceDisconnected(ComponentName name) {
//和服务断开连接
}
});
//请求和服务绑定
car.connect();
}
import android.hardware.automotive.vehicle.V2_0.IVehicle;
import android.hardware.automotive.vehicle.V2_0.IVehicleCallback;
import android.hardware.automotive.vehicle.V2_0.SubscribeOptions;
private IVehicle mVehicle;
private final VehicleDeathRecipient mVehicleDeathRecipient = new VehicleDeathRecipient();
rivate static class VehicleCallback extends IVehicleCallback.Stub {
private Handler mHandler;
VehicleCallback(Handler handler) {
mHandler = handler;
}
@Override
public void onPropertyEvent(ArrayList<VehiclePropValue> propValues) {
mHandler.sendMessage(Message.obtain(
mHandler, CallbackHandler.MSG_ON_PROPERTY_EVENT, propValues));
}
@Override
public void onPropertySet(VehiclePropValue propValue) {
mHandler.sendMessage(Message.obtain(
mHandler, CallbackHandler.MSG_ON_PROPERTY_SET, propValue));
}
@Override
public void onPropertySetError(int errorCode, int propId, int areaId) {
mHandler.sendMessage(Message.obtain(
mHandler, CallbackHandler.MSG_ON_SET_ERROR,
new PropertySetError(errorCode, propId, areaId)));
}
}
private final IVehicleCallback mInternalCallback;
private void init(){
try {
mVehicle = android.hardware.automotive.vehicle.V2_0.IVehicle.getService();
} catch (RemoteException e) {
Log.e(CarLog.TAG_SERVICE, "Failed to get IVehicle service", e);
} catch (NoSuchElementException e) {
Log.e(CarLog.TAG_SERVICE, "IVehicle service not registered yet");
}
try {
mVehicle.linkToDeath(mVehicleDeathRecipient, 0);
} catch (RemoteException e) {
throw new IllegalStateException("Failed to linkToDeath Vehicle HAL");
}
mInternalCallback = new VehicleCallback(handler);
//SubscribeOptions opts = new SubscribeOptions();
SubscribeOptions opts = new SubscribeOptions();
opts.propId = property;
opts.sampleRate = samplingRateHz;
opts.flags = flags;
subscribe(opts);
}
public void subscribe(SubscribeOptions... options) throws RemoteException {
mVehicle.subscribe(mInternalCallback, new ArrayList<>(Arrays.asList(options)));
}
头文件
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::hidl_vec;
using ::android::hardware::hidl_handle;
using ::android::hardware::hidl_death_recipient;
using ::android::sp;
using namespace ::android::hardware::automotive::vehicle::V2_0;
namespace com{
namespace vhal{
namespace helper {
class VhalHelper : public IVehicleCallback
{
/*Overrides*/
Return onPropertyEvent(const hidl_vec& propValues) override;
Return onPropertySet(const VehiclePropValue& propValue) override;
Return onPropertySetError(StatusCode errorCode, int32_t propId, int32_t areaId) override;
void handleVehicleHalDeath();
class VehicleHalDeathRecipient : public hidl_death_recipient
{
public:
VehicleHalDeathRecipient(const sp faceIdVhalHelper) :
mFaceIdVhalHelper(faceIdVhalHelper) {}
virtual void serviceDied(uint64_t cookie,
const android::wp& who);
private:
sp mFaceIdVhalHelper;
};
public:
VhalHelper();
virtual ~VhalHelper();
android::status_t initVehicle();
private:
sp mVehicle;
sp mVehicleHalDeathRecipient;
};
cpp文件
#define LOG_TAG "VhalHelper"
#define LOG_NDEBUG 0
#define LOG_NDDEBUG 0
#include
#include
#include
#include "android-base/macros.h"
#define VEHICLE_SPEED (toInt(VehicleProperty::VEHICLE_SPEED))
#define MAX_RETRY_TIME 100
#define VEHICLE_INIT_SLEEP_WAIT 100 /* 100 ms */
static SubscribeOptions reqVehicleProperties[] = {
{
.propId = VEHICLE_SPEED,
.flags = SubscribeFlags::EVENTS_FROM_CAR
},
};
namespace com{
namespace vhal{
namespace helper {
VhalHelper::VhalHelper() {
}
VhalHelper::~VhalHelper() {
}
android::status_t VhalHelper::initVehicle()
{ ALOGE("VhalHelper initVehicle");
StatusCode status;
hidl_vec options;
if (mVehicle == 0) {
mVehicle = IVehicle::getService();
if (mVehicle != 0) {
mVehicle->linkToDeath(mVehicleHalDeathRecipient, 0 /*cookie*/);
} else {
return android::FAILED_TRANSACTION;
}
options.setToExternal(reqVehicleProperties, arraysize(reqVehicleProperties));
status = mVehicle->subscribe(new FaceIdVhalHelper(), options);
if (status != StatusCode::OK) {
return android::FAILED_TRANSACTION;
}
}
return android::OK;
}
Return VhalHelper::onPropertyEvent(const hidl_vec & propValues) {
int32_t rxProprtyCount = propValues.size();
for(int i = 0; i < rxProprtyCount; i++) {
ALOGD("VhalHelper. Val:%f , Time:%u ", propValues[i].value.floatValues[0], (unsigned int)(propValues[i].timestamp/1000000));
}
return Return();
}
Return VhalHelper::onPropertySet(const VehiclePropValue & propValue) {
return Return();
}
Return VhalHelper::onPropertySetError(StatusCode errorCode,
int32_t propId,
int32_t areaId) {
return Return();
}
void VhalHelper::handleVehicleHalDeath()
{
mVehicle->unlinkToDeath(mVehicleHalDeathRecipient);
mVehicle = NULL;
int retryCount = 0;
do {
if (initVehicle() == android::OK) {
break;
} else {
if (++retryCount <= MAX_RETRY_TIME) {
usleep(VEHICLE_INIT_SLEEP_WAIT*1000);
} else {
break;
}
}
} while (1);
}
void FaceIdVhalHelper::VehicleHalDeathRecipient::serviceDied(uint64_t cookie __unused,
const android::wp& who __unused) {
mFaceIdVhalHelper->handleVehicleHalDeath();
}
}
}
}
修改bp文件
cc_library_shared {
name: "libvhalplugin",
owner: "ts",
srcs: [
"VhalHelper.cpp",
],
// add cflags.
cflags: [
"-Wall",
"-Wextra",
"-Werror",
],
clang_cflags: ["-Wno-error=unused-lambda-capture"],
shared_libs: [
"liblog",
"libutils",
"libbinder",
"libhwbinder",
"libhidlbase",
"libhidltransport",
"[email protected]",
"[email protected]",
],
vendor: true,
}