Android Automotive(十)增加一个车辆属性

Android Automotive(十)增加一个车辆属性

前面介绍了很多Android Automotive框架内的技术,最后分享一些自己使用方法。

增加一个车辆属性

硬件抽象层


修改types.hal

首先在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
}

修改DefaultConfig.h

代码路径: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;
}

修改Android.bp

增加自定义类型

代码路径:hardware\interfaces\automotive\vehicle\2.0\Android.bp

types: [
	"NewVendorPropertyMenu", 
]

Android P版本之后不再使用


系统框架层 Car-lib


修改VehiclePropertyIds.java

代码路径: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";
    }
}

修改system-current.txt

将carlib的修改加到这里

代码路径:packages\services\Car\car-lib\api\system-current.txt

field public static final int NEW_VENDOR_PROPERTY = 624994986; // 0x2540AAAA

系统框架层 CarService


修改PropertyHalServiceIds.java

代码路径: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.xml

在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"
/>

调用系统接口

系统框架层调用car-lib

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();
}

系统框架层调用HIDL

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)));
}

硬件抽象层调用HIDL

头文件

#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,
}

你可能感兴趣的:(Android,Automotive,android,automotive)