Android Vehicle

一、Vehicle相关类

Vehicle HAL :汽车的硬件抽象层描述,定义 OEM 可以实现的车辆属性的接口,Vehicle HAL通过RPC通信接收MCU和QNX发送的消息,然后保存在本地,并同步信息给上层。

1、Framework层

HalClient

HalClient是车辆 HAL 客户端,直接与车辆 HAL 接口 IVehicle} 交互。包含一些可重试属性的逻辑,将车辆通知重定向到给定的循环线程。

HalClient代码位于:

packages/services/Car/service/src/com/android/car/hal/HalClient.java

HalClient的定义:

class  HalClient {}

VehicleHal

VehicleHal是车辆 HAL的抽象。此类处理与本机 HAL 的接口,并对接收的数据进行基本解析。然后将每个事件发送到相应的HalClient实现。

VehicleHal代码位于:

packages/services/Car/service/src/com/android/car/hal/VehicleHal.java

VehicleHal的定义:

public class VehicleHal implements HalClientCallback {}

HalClientCallback

HalClientCallback 是 HalClient 支持的回调函数,VehicleHal实现了HalClientCallback接口。

HalClient代码位于:

packages/services/Car/service/src/com/android/car/hal/HalClientCallback.java

HalClient的定义:

public interface HalClientCallback {}

HalServiceBase

HalServiceBase是一个抽象类,它定义了HalService的架构,它的具体实现类包括ClusterHalService、DiagnosticHalService、EvsHalService、InputHalService、PowerHalService、PropertyHalService、TimeHalService、UserHalService、VmsHalService。

HalServiceBase代码位于:

packages/services/Car/service/src/com/android/car/hal/HalServiceBase.java

HalServiceBase的定义:

public abstract class HalServiceBase {}

HalPropValue

HalPropValue 表示车辆属性值,它可用于在车辆HAL中使用的AIDL或HIDL VehiclePropValue之间进行转换,并在CarPropertyManager中使用。

HalPropValue代码位于:

packages/services/Car/service/src/com/android/car/hal/HalPropValue .java

HalPropValue的定义:

public abstract class HalPropValue {}

VehicleStub

VehicleStub 表示 AIDL 或传统 HIDL 版本中的 IVehicle 服务接口。它公开了通用接口,因此客户端无需关心底层 IVehicle 服务所在的版本。

VehicleStub 代码位于:

packages/services/Car/service/src/com/android/car/VehicleStub.java

VehicleStub 的定义:

public abstract class VehicleStub {}

AidlVehicleStub

AidlVehicleStub是AIDL的VehicleHAL的接口,它继承于VehicleStub。

AidlVehicleStub代码位于:

packages/services/Car/service/src/com/android/car/AidlVehicleStub.java

AidlVehicleStub的定义:

final class AidlVehicleStub extends VehicleStub {}

HidlVehicleStub

HidlVehicleStub是HIDL的VehicleHAL的接口,它继承于VehicleStub,Android 10开始HIDL已经废弃。

HidlVehicleStub代码位于:

packages/services/Car/service/src/com/android/car/HidlVehicleStub.java

HidlVehicleStub的定义:

final class HidlVehicleStub extends VehicleStub {}

IVehicle

IVehicle是VehicleHal的aidl接口,Framework通过IVehicle向VehicleHal发送消息。

IVehicle接口方法如下:

  • void getValues(android.hardware.automotive.vehicle.IVehicleCallback callback, in android.hardware.automotive.vehicle.GetValueRequests requests);

  • void setValues(android.hardware.automotive.vehicle.IVehicleCallback callback, in android.hardware.automotive.vehicle.SetValueRequests requests);

  • void subscribe(in android.hardware.automotive.vehicle.IVehicleCallback callback, in android.hardware.automotive.vehicle.SubscribeOptions[] options, int maxSharedMemoryFileCount);

  • void unsubscribe(in android.hardware.automotive.vehicle.IVehicleCallback callback, in int[] propIds);

IVehicle代码位于:

hardware/interfaces/automotive/vehicle/aidl/android/hardware/automotive/vehicle/IVehicle.aidl

IVehicle的定义:

interface IVehicle {}

IVehicleCallback

IVehicleCallback是VehicleHal的aidl接口,VehicleHal通过IVehicleCallback调用Framework回调。

IVehicleCallback接口方法如下:

  • void onGetValues(in android.hardware.automotive.vehicle.GetValueResults responses);

  • void onSetValues(in android.hardware.automotive.vehicle.SetValueResults responses);

  • void onPropertyEvent(in android.hardware.automotive.vehicle.VehiclePropValues propValues, int sharedMemoryFileCount);

  • void onPropertySetError(in android.hardware.automotive.vehicle.VehiclePropErrors errors);

IVehicleCallback代码位于:

hardware/interfaces/automotive/vehicle/aidl/android/hardware/automotive/vehicle/IVehicleCallback .aidl

IVehicleCallback的定义:

interface IVehicleCallback {}

VehicleProperty

VehicleProperty是AIDL接口文件,它定义了VehicleProperty的枚举类型。

VehicleProperty代码位于:

hardware/interfaces/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleProperty.aidl

VehicleProperty的定义:

enum VehicleProperty {}

2、HAL层

IVhalClient

IVhalClient代码位于:

packages/services/Car/cpp/vhal/client/src/IVhalClient.cpp

packages/services/Car/cpp/vhal/client/include/IVhalClient.h

IVhalClient的定义:

class IVhalClient {}
class ISubscriptionClient {}
class ISubscriptionCallback {}

AidlVhalClient

AidlVhalClient代码位于:

packages/services/Car/cpp/vhal/client/src/AidlVhalClient.cpp

packages/services/Car/cpp/vhal/client/include/AidlVhalClient.h

AidlVhalClient的定义:

class AidlVhalClient final : public IVhalClient {}
class GetSetValueClient final : public aidl::android::hardware::automotive::vehicle::BnVehicleCallback {}
class SubscriptionVehicleCallback final : public aidl::android::hardware::automotive::vehicle::BnVehicleCallback {}
class AidlSubscriptionClient final : public ISubscriptionClient {}

DefaultVehicleHal

DefaultVehicleHal代码位于:

hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp

hardware/interfaces/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h

DefaultVehicleHal的定义:

class DefaultVehicleHal final : public aidl::android::hardware::automotive::vehicle::BnVehicle {}

ConnectedClient

ConnectedClient代码位于:

hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp

hardware/interfaces/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h

ConnectedClient的定义:

class ConnectedClient {}
class GetSetValuesClient final : public ConnectedClient {}
class SubscriptionClient final : public ConnectedClient {}

SubscriptionManager

SubscriptionManager代码位于:

hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/SubscriptionManager.cpp

hardware/interfaces/automotive/vehicle/aidl/impl/vhal/include/SubscriptionManager.h

SubscriptionManager的定义:

class ContSubConfigs final {}
class SubscriptionManager final {}

IVehicleHardware

IVehicleHardware代码位于:

hardware/interfaces/automotive/vehicle/aidl/impl/hardware/include/IVehicleHardware.h

IVehicleHardware的定义:

class IVehicleHardware {}

FakeVehicleHardware

FakeVehicleHardware 代码位于:

hardware/interfaces/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp

hardware/interfaces/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h

FakeVehicleHardware 的定义:

class FakeVehicleHardware : public IVehicleHardware {}

二、Vehicle流程分析

1、VehicleHAL初始化

VehicleHAL的main函数在VehicleService.cpp中,代码如下:

//hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/VehicleService.cpp
int main(int /* argc */, char* /* argv */[]) {
    std::unique_ptr<FakeVehicleHardware> hardware = std::make_unique<FakeVehicleHardware>(); //创建FakeVehicleHardware对象,用于与RPC通信
    std::shared_ptr<DefaultVehicleHal> vhal =
            ::ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware)); //创建DefaultVehicleHal对象,用户VehicleHal处理


    ALOGI("Registering as service...");
    binder_exception_t err = AServiceManager_addService(
            vhal->asBinder().get(), "android.hardware.automotive.vehicle.IVehicle/default");
    if (err != EX_NONE) {
        ALOGE("failed to register android.hardware.automotive.vehicle service, exception: %d", err);
        return 1;
    }


    if (!ABinderProcess_setThreadPoolMaxThreadCount(4)) {
        ALOGE("%s", "failed to set thread pool max thread count");
        return 1;
    }
    ABinderProcess_startThreadPool();


    ALOGI("Vehicle Service Ready");


    ABinderProcess_joinThreadPool();


    ALOGI("Vehicle Service Exiting");


    return 0;
}

2、Vehicle事件分发流程

我们首先看DefaultVehicleHal的构造函数:

//hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
class DefaultVehicleHal final : public aidl::android::hardware::automotive::vehicle::BnVehicle {
DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> hardware)
    : mVehicleHardware(std::move(hardware)),
      mPendingRequestPool(std::make_shared<PendingRequestPool>(TIMEOUT_IN_NANO)) {
    auto configs = mVehicleHardware->getAllPropertyConfigs();
    for (auto& config : configs) {
        mConfigsByPropId[config.prop] = config;
    }
    VehiclePropConfigs vehiclePropConfigs;
    vehiclePropConfigs.payloads = std::move(configs);
    auto result = LargeParcelableBase::parcelableToStableLargeParcelable(vehiclePropConfigs);
    if (!result.ok()) {
        ALOGE("failed to convert configs to shared memory file, error: %s, code: %d",
              result.error().message().c_str(), static_cast<int>(result.error().code()));
        return;
    }


    if (result.value() != nullptr) {
        mConfigFile = std::move(result.value());
    }


    mSubscriptionClients = std::make_shared<SubscriptionClients>(mPendingRequestPool);
    mSubscriptionClients = std::make_shared<SubscriptionClients>(mPendingRequestPool);


    auto subscribeIdByClient = std::make_shared<SubscribeIdByClient>();
    IVehicleHardware* hardwarePtr = mVehicleHardware.get();
    mSubscriptionManager = std::make_shared<SubscriptionManager>(hardwarePtr);


    std::weak_ptr<SubscriptionManager> subscriptionManagerCopy = mSubscriptionManager;
    mVehicleHardware->registerOnPropertyChangeEvent(
            std::make_unique<IVehicleHardware::PropertyChangeCallback>(
                    [subscriptionManagerCopy](std::vector<VehiclePropValue> updatedValues) {
                        onPropertyChangeEvent(subscriptionManagerCopy, updatedValues);
                    }));


    // Register heartbeat event.
    mRecurrentAction =
            std::make_shared<std::function<void()>>([hardwarePtr, subscriptionManagerCopy]() {
                checkHealth(hardwarePtr, subscriptionManagerCopy); 
            });
    mRecurrentTimer.registerTimerCallback(HEART_BEAT_INTERVAL_IN_NANO, mRecurrentAction);


    mBinderImpl = std::make_unique<AIBinderImpl>();
    mOnBinderDiedUnlinkedHandlerThread = std::thread([this] { onBinderDiedUnlinkedHandler(); });
    mDeathRecipient = ScopedAIBinder_DeathRecipient(
            AIBinder_DeathRecipient_new(&DefaultVehicleHal::onBinderDied));
    AIBinder_DeathRecipient_setOnUnlinked(mDeathRecipient.get(),
                                          &DefaultVehicleHal::onBinderUnlinked);
}
}

在DefaultVehicleHal的构造中进行了如下处理:

通过std::make_shared创建SubscriptionClients对象mSubscriptionClients,函数中调用了2次,不知道啥原因。

通过std::make_shared创建SubscribeIdByClient对象subscribeIdByClient。subscribeIdByClient是一个线程安全类,用于维护每个订阅客户端的请求 ID 不断增加。此类可以安全地传递给异步回调。

通过std::make_shared创建SubscriptionManager对象mSubscriptionManager。

调用mVehicleHardware->registerOnPropertyChangeEvent注册一个回调,当车辆发生属性更改事件时将调用该回调,回调函数为onPropertyChangeEvent。

调用mRecurrentTimer.registerTimerCallback注册心跳事件。

当车辆发生属性更改事件时会调用DefaultVehicleHal的onPropertyChangeEvent方法:

//hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
void DefaultVehicleHal::onPropertyChangeEvent(
        std::weak_ptr<SubscriptionManager> subscriptionManager,
        const std::vector<VehiclePropValue>& updatedValues) {
    auto manager = subscriptionManager.lock();
    if (manager == nullptr) {
        ALOGW("the SubscriptionManager is destroyed, DefaultVehicleHal is ending");
        return;
    }
    auto updatedValuesByClients = manager->getSubscribedClients(updatedValues);
    for (const auto& [callback, valuePtrs] : updatedValuesByClients) {
        std::vector<VehiclePropValue> values;
        for (const VehiclePropValue* valuePtr : valuePtrs) {
            values.push_back(*valuePtr);
        }
        SubscriptionClient::sendUpdatedValues(callback, std::move(values));
    }
}

在DefaultVehicleHal的onPropertyChangeEvent中调用SubscriptionClient的sendUpdatedValues函数:

//hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp
void SubscriptionClient::sendUpdatedValues(std::shared_ptr<IVehicleCallback> callback,
                                           std::vector<VehiclePropValue>&& updatedValues) {
    if (updatedValues.empty()) {
        return;
    }


    // TODO(b/205189110): Use memory pool here and fill in sharedMemoryId.
    VehiclePropValues vehiclePropValues;
    int32_t sharedMemoryFileCount = 0;
    ScopedAStatus status =
            vectorToStableLargeParcelable(std::move(updatedValues), &vehiclePropValues);
    if (!status.isOk()) {
        int statusCode = status.getServiceSpecificError();
        ALOGE("subscribe: failed to marshal result into large parcelable, error: "
              "%s, code: %d",
              status.getMessage(), statusCode);
        return;
    }


    if (ScopedAStatus callbackStatus =
                callback->onPropertyEvent(vehiclePropValues, sharedMemoryFileCount);
        !callbackStatus.isOk()) {
        ALOGE("subscribe: failed to call UpdateValues callback, client ID: %p, error: %s, "
              "exception: %d, service specific error: %d",
              callback->asBinder().get(), callbackStatus.getMessage(),
              callbackStatus.getExceptionCode(), callbackStatus.getServiceSpecificError());
    }
}

在SubscriptionClient的sendUpdatedValues函数中调用AidlSubscriptionClient的onPropertyEvent方法:

//packages/services/Car/service/src/com/android/car/AidlVehicleStub.java
final class AidlVehicleStub extends VehicleStub {
    private class AidlSubscriptionClient extends IVehicleCallback.Stub
            implements SubscriptionClient {
        private final HalClientCallback mCallback;
        private final HalPropValueBuilder mBuilder;
        public void onPropertyEvent(VehiclePropValues propValues, int sharedMemoryFileCount)
                throws RemoteException {
            VehiclePropValues origPropValues = (VehiclePropValues)
                    LargeParcelable.reconstructStableAIDLParcelable(propValues,
                            /* keepSharedMemory= */ false);
            ArrayList<HalPropValue> values = new ArrayList<>(origPropValues.payloads.length);
            for (VehiclePropValue value : origPropValues.payloads) {
                values.add(mBuilder.build(value));
            }
            mCallback.onPropertyEvent(values);
        }
    }
}

AidlVehicleStub内部类AidlSubscriptionClient的onPropertyEvent调用HalClientCallback对象的onPropertyEvent。HalClientCallback是一个接口,它的实现为HalClient的内部类VehicleCallback,因此AidlSubscriptionClient的onPropertyEvent调用的是HalClient内部类VehicleCallback的onPropertyEvent方法:

//packages/services/Car/service/src/com/android/car/hal/HalClient.java
final class HalClient {
    static final class VehicleCallback implements HalClientCallback {
        private final Handler mHandler;


        VehicleCallback(Handler handler) {
            mHandler = handler;
        }


        @Override
        public void onPropertyEvent(ArrayList<HalPropValue> propValues) {
            mHandler.sendMessage(Message.obtain(
                    mHandler, CallbackHandler.MSG_ON_PROPERTY_EVENT, propValues)); 发送MSG_ON_PROPERTY_EVENT消息
        }


        @Override
        public void onPropertySetError(ArrayList<VehiclePropError> errors) {
            mHandler.sendMessage(Message.obtain(
                        mHandler, CallbackHandler.MSG_ON_SET_ERROR, errors)); 
        }
    }
}

发送MSG_ON_PROPERTY_EVENT消息CallbackHandler会收到这个消息:

//packages/services/Car/service/src/com/android/car/hal/HalClient.java
final class HalClient {
    private static final class CallbackHandler extends Handler {
        private static final int MSG_ON_PROPERTY_EVENT = 1;
        private static final int MSG_ON_SET_ERROR = 2;


        private final WeakReference<HalClientCallback> mCallback;


        CallbackHandler(Looper looper, HalClientCallback callback) {
            super(looper);
            mCallback = new WeakReference<HalClientCallback>(callback);
        }


        @Override
        public void handleMessage(Message msg) {
            HalClientCallback callback = mCallback.get();
            if (callback == null) {
                Slogf.i(TAG, "handleMessage null callback");
                return;
            }


            switch (msg.what) {
                case MSG_ON_PROPERTY_EVENT:
                    callback.onPropertyEvent((ArrayList<HalPropValue>) msg.obj);
                    break;
                case MSG_ON_SET_ERROR:
                    callback.onPropertySetError((ArrayList<VehiclePropError>) msg.obj);
                    break;
                default:
                    Slogf.e(TAG, "Unexpected message: %d", msg.what);
            }
        }
    }
}

在CallbackHandler的onPropertyEvent调用VehicleHal 的onPropertyEvent方法:

//packages/services/Car/service/src/com/android/car/hal/VehicleHal.java
public class VehicleHal implements HalClientCallback {
    @Override
    public void onPropertyEvent(ArrayList<HalPropValue> propValues) {
        synchronized (mLock) {
            for (int i = 0; i < propValues.size(); i++) {
                HalPropValue v = propValues.get(i);
                int propId = v.getPropId();
                HalServiceBase service = mPropertyHandlers.get(propId);
                if (service == null) {
                    Slogf.e(CarLog.TAG_HAL, "HalService not found for prop: 0x"
                            + toHexString(propId));
                    continue;
                }
                service.getDispatchList().add(v);
                mServicesToDispatch.add(service);
                VehiclePropertyEventInfo info = mEventLog.get(propId);
                if (info == null) {
                    info = new VehiclePropertyEventInfo(v);
                    mEventLog.put(propId, info);
                } else {
                    info.addNewEvent(v);
                }
            }
        }
        for (HalServiceBase s : mServicesToDispatch) {
            s.onHalEvents(s.getDispatchList());  //循环查询HalServiceBase的子类,调用子类的onHalEvents
            s.getDispatchList().clear();
        }
        mServicesToDispatch.clear();
    }
}

在VehicleHal的onPropertyEvent中调用调用各个HalService的onHalEvents,如PowerHalService、PropertyHalService,之后由不同HalService继续对PropertyEvent进行处理。

3、setValues流程

App调用CarPropertyManager的setProperty API时,CarPropertyManager经过CarPropertyService调用DefaultVehicleHal的setValues函数:
 

//hardware/interfaces/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
    std::unique_ptr<IVehicleHardware> mVehicleHardware;
//hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
class DefaultVehicleHal final : public aidl::android::hardware::automotive::vehicle::BnVehicle {
ScopedAStatus DefaultVehicleHal::setValues(const CallbackType& callback,
                                           const SetValueRequests& requests) {
    expected<LargeParcelableBase::BorrowedOwnedObject<SetValueRequests>, ScopedAStatus>
            deserializedResults = fromStableLargeParcelable(requests);
    if (!deserializedResults.ok()) {
        ALOGE("setValues: failed to parse setValues requests");
        return std::move(deserializedResults.error());
    }
    const std::vector<SetValueRequest>& setValueRequests =
            deserializedResults.value().getObject()->payloads;


    // A list of failed result we already know before sending to hardware.
    std::vector<SetValueResult> failedResults;
    // The list of requests that we would send to hardware.
    std::vector<SetValueRequest> hardwareRequests;


    auto maybeRequestIds = checkDuplicateRequests(setValueRequests);
    if (!maybeRequestIds.ok()) {
        ALOGE("setValues: duplicate request ID");
        return toScopedAStatus(maybeRequestIds, StatusCode::INVALID_ARG);
    }


    for (auto& request : setValueRequests) {
        int64_t requestId = request.requestId;
        if (auto result = checkWritePermission(request.value); !result.ok()) {
            ALOGW("property does not support writing: %s", getErrorMsg(result).c_str());
            failedResults.push_back(SetValueResult{
                    .requestId = requestId,
                    .status = getErrorCode(result),
            });
            continue;
        }
        if (auto result = checkProperty(request.value); !result.ok()) {
            ALOGW("setValues[%" PRId64 "]: property is not valid: %s", requestId,
                  getErrorMsg(result).c_str());
            failedResults.push_back(SetValueResult{
                    .requestId = requestId,
                    .status = StatusCode::INVALID_ARG,
            });
            continue;
        }


        hardwareRequests.push_back(request);
    }


    // The set of request Ids that we would send to hardware.
    std::unordered_set<int64_t> hardwareRequestIds;
    for (const auto& request : hardwareRequests) {
        hardwareRequestIds.insert(request.requestId);
    }


    std::shared_ptr<SetValuesClient> client;
    {
        // Lock to make sure onBinderDied would not be called concurrently.
        std::scoped_lock lockGuard(mLock);
        if (!monitorBinderLifeCycleLocked(callback->asBinder().get())) {
            return ScopedAStatus::fromExceptionCodeWithMessage(EX_TRANSACTION_FAILED,
                                                               "client died");
        }
        client = getOrCreateClient(&mSetValuesClients, callback, mPendingRequestPool);
    }


    // Register the pending hardware requests and also check for duplicate request Ids.
    if (auto addRequestResult = client->addRequests(hardwareRequestIds); !addRequestResult.ok()) {
        ALOGE("setValues[%s], failed to add pending requests, error: %s",
              toString(hardwareRequestIds).c_str(), getErrorMsg(addRequestResult).c_str());
        return toScopedAStatus(addRequestResult);
    }


    if (!failedResults.empty()) {
        // First send the failed results we already know back to the client.
        client->sendResults(std::move(failedResults));
    }


    if (hardwareRequests.empty()) {
        return ScopedAStatus::ok();
    }


    if (StatusCode status =
                mVehicleHardware->setValues(client->getResultCallback(), hardwareRequests); //调用IVehicleHardware的setValues
        status != StatusCode::OK) {
        // If the hardware returns error, finish all the pending requests for this request because
        // we never expect hardware to call callback for these requests.
        client->tryFinishRequests(hardwareRequestIds);
        ALOGE("setValues[%s], failed to set value to VehicleHardware, status: %d",
              toString(hardwareRequestIds).c_str(), toInt(status));
        return ScopedAStatus::fromServiceSpecificErrorWithMessage(
                toInt(status), "failed to set value to VehicleHardware");
    }


    return ScopedAStatus::ok();
}
}

在DefaultVehicleHal的setValues调用IVehicleHardware的setValues,FakeVehicleHardware继承于IVehicleHardware,因此会调用FakeVehicleHardware的setValues:

//hardware/interfaces/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
class FakeVehicleHardware : public IVehicleHardware {
StatusCode FakeVehicleHardware::setValues(std::shared_ptr<const SetValuesCallback> callback,
                                          const std::vector<SetValueRequest>& requests) {
    for (auto& request : requests) {
        if (FAKE_VEHICLEHARDWARE_DEBUG) {
            ALOGD("Set value for property ID: %d", request.value.prop);
        }


        // In a real VHAL implementation, you could either send the setValue request to vehicle bus
        // here in the binder thread, or you could send the request in setValue which runs in
        // the handler thread. If you decide to send the setValue request here, you should not
        // wait for the response here and the handler thread should handle the setValue response.
        mPendingSetValueRequests.addRequest(request, callback);
    }


    return StatusCode::OK;
}
}
  • 22
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值