mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 16:50:18 +00:00
Merge changes I0e0be46f,I2d34138a,I48729915
* changes: Create ConnectedClient to manage VHAL clients. Add MockVehicleCallback for testing. Add ParcelableUtils.
This commit is contained in:
committed by
Android (Google) Code Review
commit
2909ca284c
@@ -25,6 +25,7 @@
|
||||
#include <aidl/android/hardware/automotive/vehicle/FuelType.h>
|
||||
#include <aidl/android/hardware/automotive/vehicle/GetValueRequest.h>
|
||||
#include <aidl/android/hardware/automotive/vehicle/GetValueResult.h>
|
||||
#include <aidl/android/hardware/automotive/vehicle/GetValueResults.h>
|
||||
#include <aidl/android/hardware/automotive/vehicle/Obd2CommonIgnitionMonitors.h>
|
||||
#include <aidl/android/hardware/automotive/vehicle/Obd2FuelSystemStatus.h>
|
||||
#include <aidl/android/hardware/automotive/vehicle/Obd2FuelType.h>
|
||||
@@ -34,6 +35,7 @@
|
||||
#include <aidl/android/hardware/automotive/vehicle/PortLocationType.h>
|
||||
#include <aidl/android/hardware/automotive/vehicle/SetValueRequest.h>
|
||||
#include <aidl/android/hardware/automotive/vehicle/SetValueResult.h>
|
||||
#include <aidl/android/hardware/automotive/vehicle/SetValueResults.h>
|
||||
#include <aidl/android/hardware/automotive/vehicle/StatusCode.h>
|
||||
#include <aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReport.h>
|
||||
#include <aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReq.h>
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include <VehicleHalTypes.h>
|
||||
|
||||
#include <android-base/format.h>
|
||||
#include <android-base/result.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
@@ -208,6 +209,37 @@ std::string getErrorMsg(const ::android::base::Result<T>& result) {
|
||||
return result.error().message();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
::ndk::ScopedAStatus toScopedAStatus(
|
||||
const ::android::base::Result<T>& result,
|
||||
::aidl::android::hardware::automotive::vehicle::StatusCode status,
|
||||
std::string additionalErrorMsg) {
|
||||
if (result.ok()) {
|
||||
return ::ndk::ScopedAStatus::ok();
|
||||
}
|
||||
return ::ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
|
||||
toInt(status),
|
||||
fmt::format("{}, error: {}", additionalErrorMsg, getErrorMsg(result)).c_str());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
::ndk::ScopedAStatus toScopedAStatus(
|
||||
const ::android::base::Result<T>& result,
|
||||
::aidl::android::hardware::automotive::vehicle::StatusCode status) {
|
||||
return toScopedAStatus(result, status, "");
|
||||
}
|
||||
|
||||
template <class T>
|
||||
::ndk::ScopedAStatus toScopedAStatus(const ::android::base::Result<T>& result) {
|
||||
return toScopedAStatus(result, getErrorCode(result));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
::ndk::ScopedAStatus toScopedAStatus(const ::android::base::Result<T>& result,
|
||||
std::string additionalErrorMsg) {
|
||||
return toScopedAStatus(result, getErrorCode(result), additionalErrorMsg);
|
||||
}
|
||||
|
||||
} // namespace vehicle
|
||||
} // namespace automotive
|
||||
} // namespace hardware
|
||||
|
||||
@@ -53,7 +53,10 @@ cc_library {
|
||||
],
|
||||
local_include_dirs: ["include"],
|
||||
export_include_dirs: ["include"],
|
||||
srcs: ["src/DefaultVehicleHal.cpp"],
|
||||
srcs: [
|
||||
"src/ConnectedClient.cpp",
|
||||
"src/DefaultVehicleHal.cpp",
|
||||
],
|
||||
static_libs: [
|
||||
"VehicleHalUtils",
|
||||
"android-automotive-large-parcelable-vendor-lib",
|
||||
|
||||
82
automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h
Normal file
82
automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef android_hardware_automotive_vehicle_aidl_impl_vhal_include_ConnectedClient_H_
|
||||
#define android_hardware_automotive_vehicle_aidl_impl_vhal_include_ConnectedClient_H_
|
||||
|
||||
#include <VehicleHalTypes.h>
|
||||
|
||||
#include <aidl/android/hardware/automotive/vehicle/IVehicleCallback.h>
|
||||
#include <android-base/result.h>
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace automotive {
|
||||
namespace vehicle {
|
||||
|
||||
// A class to represent a binder client with a callback interface. Each callback function, e.g.
|
||||
// GetValues or SetValues for a specific binder client is a separate {@code ConnectedClient}.
|
||||
// For one {@code ConnectedClient}, we use one pending request pool to manage all pending requests,
|
||||
// so the request IDs must be unique for one client. We also manage a set of callback functions
|
||||
// for one client, e.g. timeoutCallback which could be passed to hardware.
|
||||
// This class is thread-safe.
|
||||
class ConnectedClient {
|
||||
public:
|
||||
ConnectedClient(
|
||||
std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback>
|
||||
callback);
|
||||
|
||||
virtual ~ConnectedClient() = default;
|
||||
|
||||
protected:
|
||||
const std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback>
|
||||
mCallback;
|
||||
};
|
||||
|
||||
// A class to represent a client that calls {@code IVehicle.setValues} or {@code
|
||||
// IVehicle.getValues}.
|
||||
template <class ResultType, class ResultsType>
|
||||
class GetSetValuesClient final : public ConnectedClient {
|
||||
public:
|
||||
GetSetValuesClient(
|
||||
std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback>
|
||||
callback);
|
||||
|
||||
// Sends the results to this client.
|
||||
void sendResults(const std::vector<ResultType>& results);
|
||||
|
||||
// Sends each result separately to this client. Each result would be sent through one callback
|
||||
// invocation.
|
||||
void sendResultsSeparately(const std::vector<ResultType>& results);
|
||||
|
||||
// Gets the callback to be called when the request for this client has finished.
|
||||
std::shared_ptr<const std::function<void(std::vector<ResultType>)>> getResultCallback();
|
||||
|
||||
private:
|
||||
// The following members are only initialized during construction.
|
||||
std::shared_ptr<const std::function<void(std::vector<ResultType>)>> mResultCallback;
|
||||
};
|
||||
|
||||
} // namespace vehicle
|
||||
} // namespace automotive
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // android_hardware_automotive_vehicle_aidl_impl_vhal_include_ConnectedClient_H_
|
||||
89
automotive/vehicle/aidl/impl/vhal/include/ParcelableUtils.h
Normal file
89
automotive/vehicle/aidl/impl/vhal/include/ParcelableUtils.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef android_hardware_automotive_vehicle_aidl_impl_vhal_include_ParcelableUtils_H_
|
||||
#define android_hardware_automotive_vehicle_aidl_impl_vhal_include_ParcelableUtils_H_
|
||||
|
||||
#include <LargeParcelableBase.h>
|
||||
#include <VehicleHalTypes.h>
|
||||
#include <VehicleUtils.h>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace automotive {
|
||||
namespace vehicle {
|
||||
|
||||
template <class T1, class T2>
|
||||
::ndk::ScopedAStatus vectorToStableLargeParcelable(std::vector<T1>&& values, T2* output) {
|
||||
auto result = ::android::automotive::car_binder_lib::LargeParcelableBase::
|
||||
parcelableVectorToStableLargeParcelable(values);
|
||||
if (!result.ok()) {
|
||||
return toScopedAStatus(
|
||||
result, ::aidl::android::hardware::automotive::vehicle::StatusCode::INTERNAL_ERROR);
|
||||
}
|
||||
auto& fd = result.value();
|
||||
if (fd == nullptr) {
|
||||
// If we no longer needs values, move it inside the payloads to avoid copying.
|
||||
output->payloads = std::move(values);
|
||||
} else {
|
||||
// Move the returned ScopedFileDescriptor pointer to ScopedFileDescriptor value in
|
||||
// 'sharedMemoryFd' field.
|
||||
output->sharedMemoryFd = std::move(*fd);
|
||||
}
|
||||
return ::ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
::ndk::ScopedAStatus vectorToStableLargeParcelable(const std::vector<T1>& values, T2* output) {
|
||||
// Because 'values' is passed in as const reference, we have to do a copy here.
|
||||
std::vector<T1> valuesCopy = values;
|
||||
|
||||
return vectorToStableLargeParcelable(std::move(valuesCopy), output);
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
::android::base::expected<std::vector<T1>, ::ndk::ScopedAStatus> stableLargeParcelableToVector(
|
||||
const T2& largeParcelable) {
|
||||
::android::base::Result<std::optional<std::vector<T1>>> result =
|
||||
::android::automotive::car_binder_lib::LargeParcelableBase::
|
||||
stableLargeParcelableToParcelableVector<T1>(largeParcelable.sharedMemoryFd);
|
||||
|
||||
if (!result.ok()) {
|
||||
return ::android::base::unexpected(toScopedAStatus(
|
||||
result, ::aidl::android::hardware::automotive::vehicle::StatusCode::INVALID_ARG,
|
||||
"failed to parse large parcelable"));
|
||||
}
|
||||
|
||||
if (!result.value().has_value()) {
|
||||
return ::android::base::unexpected(
|
||||
::ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
|
||||
toInt(::aidl::android::hardware::automotive::vehicle::StatusCode::
|
||||
INVALID_ARG),
|
||||
"empty request"));
|
||||
}
|
||||
|
||||
return std::move(result.value().value());
|
||||
}
|
||||
|
||||
} // namespace vehicle
|
||||
} // namespace automotive
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // android_hardware_automotive_vehicle_aidl_impl_vhal_include_ParcelableUtils_H_
|
||||
160
automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp
Normal file
160
automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp
Normal file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ConnectedClient.h"
|
||||
#include "ParcelableUtils.h"
|
||||
|
||||
#include <VehicleHalTypes.h>
|
||||
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace automotive {
|
||||
namespace vehicle {
|
||||
|
||||
namespace {
|
||||
|
||||
using ::aidl::android::hardware::automotive::vehicle::GetValueResult;
|
||||
using ::aidl::android::hardware::automotive::vehicle::GetValueResults;
|
||||
using ::aidl::android::hardware::automotive::vehicle::IVehicleCallback;
|
||||
using ::aidl::android::hardware::automotive::vehicle::SetValueResult;
|
||||
using ::aidl::android::hardware::automotive::vehicle::SetValueResults;
|
||||
using ::aidl::android::hardware::automotive::vehicle::StatusCode;
|
||||
using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
|
||||
using ::aidl::android::hardware::automotive::vehicle::VehiclePropValues;
|
||||
using ::android::base::Result;
|
||||
using ::ndk::ScopedAStatus;
|
||||
|
||||
// A function to call the specific callback based on results type.
|
||||
template <class T>
|
||||
ScopedAStatus callCallback(std::shared_ptr<IVehicleCallback> callback, const T& results);
|
||||
|
||||
template <>
|
||||
ScopedAStatus callCallback<GetValueResults>(std::shared_ptr<IVehicleCallback> callback,
|
||||
const GetValueResults& results) {
|
||||
return callback->onGetValues(results);
|
||||
}
|
||||
|
||||
template <>
|
||||
ScopedAStatus callCallback<SetValueResults>(std::shared_ptr<IVehicleCallback> callback,
|
||||
const SetValueResults& results) {
|
||||
return callback->onSetValues(results);
|
||||
}
|
||||
|
||||
// Send a single GetValue/SetValue result through the callback.
|
||||
template <class ResultType, class ResultsType>
|
||||
void sendGetOrSetValueResult(std::shared_ptr<IVehicleCallback> callback, const ResultType& result) {
|
||||
ResultsType parcelableResults;
|
||||
parcelableResults.payloads.resize(1);
|
||||
parcelableResults.payloads[0] = result;
|
||||
if (ScopedAStatus callbackStatus = callCallback(callback, parcelableResults);
|
||||
!callbackStatus.isOk()) {
|
||||
ALOGE("failed to call callback, error: %s, code: %d", callbackStatus.getMessage(),
|
||||
callbackStatus.getServiceSpecificError());
|
||||
}
|
||||
}
|
||||
|
||||
// Send all the GetValue/SetValue results through callback, one result in each callback invocation.
|
||||
template <class ResultType, class ResultsType>
|
||||
void sendGetOrSetValueResultsSeparately(std::shared_ptr<IVehicleCallback> callback,
|
||||
const std::vector<ResultType>& results) {
|
||||
for (const auto& result : results) {
|
||||
sendGetOrSetValueResult<ResultType, ResultsType>(callback, result);
|
||||
}
|
||||
}
|
||||
|
||||
// Send all the GetValue/SetValue results through callback in a single callback invocation.
|
||||
template <class ResultType, class ResultsType>
|
||||
void sendGetOrSetValueResults(std::shared_ptr<IVehicleCallback> callback,
|
||||
const std::vector<ResultType>& results) {
|
||||
ResultsType parcelableResults;
|
||||
ScopedAStatus status = vectorToStableLargeParcelable(results, &parcelableResults);
|
||||
if (status.isOk()) {
|
||||
if (ScopedAStatus callbackStatus = callCallback(callback, parcelableResults);
|
||||
!callbackStatus.isOk()) {
|
||||
ALOGE("failed to call callback, error: %s, code: %d", status.getMessage(),
|
||||
status.getServiceSpecificError());
|
||||
}
|
||||
return;
|
||||
}
|
||||
int statusCode = status.getServiceSpecificError();
|
||||
ALOGE("failed to marshal result into large parcelable, error: "
|
||||
"%s, code: %d",
|
||||
status.getMessage(), statusCode);
|
||||
sendGetOrSetValueResultsSeparately<ResultType, ResultsType>(callback, results);
|
||||
}
|
||||
|
||||
// Specify the functions for GetValues and SetValues types.
|
||||
template void sendGetOrSetValueResult<GetValueResult, GetValueResults>(
|
||||
std::shared_ptr<IVehicleCallback> callback, const GetValueResult& result);
|
||||
template void sendGetOrSetValueResult<SetValueResult, SetValueResults>(
|
||||
std::shared_ptr<IVehicleCallback> callback, const SetValueResult& result);
|
||||
|
||||
template void sendGetOrSetValueResults<GetValueResult, GetValueResults>(
|
||||
std::shared_ptr<IVehicleCallback> callback, const std::vector<GetValueResult>& results);
|
||||
template void sendGetOrSetValueResults<SetValueResult, SetValueResults>(
|
||||
std::shared_ptr<IVehicleCallback> callback, const std::vector<SetValueResult>& results);
|
||||
|
||||
template void sendGetOrSetValueResultsSeparately<GetValueResult, GetValueResults>(
|
||||
std::shared_ptr<IVehicleCallback> callback, const std::vector<GetValueResult>& results);
|
||||
template void sendGetOrSetValueResultsSeparately<SetValueResult, SetValueResults>(
|
||||
std::shared_ptr<IVehicleCallback> callback, const std::vector<SetValueResult>& results);
|
||||
|
||||
} // namespace
|
||||
|
||||
ConnectedClient::ConnectedClient(std::shared_ptr<IVehicleCallback> callback)
|
||||
: mCallback(callback) {}
|
||||
|
||||
template <class ResultType, class ResultsType>
|
||||
GetSetValuesClient<ResultType, ResultsType>::GetSetValuesClient(
|
||||
std::shared_ptr<IVehicleCallback> callback)
|
||||
: ConnectedClient(callback) {
|
||||
mResultCallback = std::make_shared<const std::function<void(std::vector<ResultType>)>>(
|
||||
[callback](std::vector<ResultType> results) {
|
||||
return sendGetOrSetValueResults<ResultType, ResultsType>(callback, results);
|
||||
});
|
||||
}
|
||||
|
||||
template <class ResultType, class ResultsType>
|
||||
std::shared_ptr<const std::function<void(std::vector<ResultType>)>>
|
||||
GetSetValuesClient<ResultType, ResultsType>::getResultCallback() {
|
||||
return mResultCallback;
|
||||
}
|
||||
|
||||
template <class ResultType, class ResultsType>
|
||||
void GetSetValuesClient<ResultType, ResultsType>::sendResults(
|
||||
const std::vector<ResultType>& results) {
|
||||
return sendGetOrSetValueResults<ResultType, ResultsType>(mCallback, results);
|
||||
}
|
||||
|
||||
template <class ResultType, class ResultsType>
|
||||
void GetSetValuesClient<ResultType, ResultsType>::sendResultsSeparately(
|
||||
const std::vector<ResultType>& results) {
|
||||
return sendGetOrSetValueResultsSeparately<ResultType, ResultsType>(mCallback, results);
|
||||
}
|
||||
|
||||
template class GetSetValuesClient<GetValueResult, GetValueResults>;
|
||||
template class GetSetValuesClient<SetValueResult, SetValueResults>;
|
||||
|
||||
} // namespace vehicle
|
||||
} // namespace automotive
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
208
automotive/vehicle/aidl/impl/vhal/test/ConnectedClientTest.cpp
Normal file
208
automotive/vehicle/aidl/impl/vhal/test/ConnectedClientTest.cpp
Normal file
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ConnectedClient.h"
|
||||
#include "MockVehicleCallback.h"
|
||||
|
||||
#include <aidl/android/hardware/automotive/vehicle/IVehicleCallback.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace automotive {
|
||||
namespace vehicle {
|
||||
|
||||
using ::aidl::android::hardware::automotive::vehicle::GetValueResult;
|
||||
using ::aidl::android::hardware::automotive::vehicle::GetValueResults;
|
||||
using ::aidl::android::hardware::automotive::vehicle::IVehicleCallback;
|
||||
using ::aidl::android::hardware::automotive::vehicle::SetValueResult;
|
||||
using ::aidl::android::hardware::automotive::vehicle::SetValueResults;
|
||||
using ::aidl::android::hardware::automotive::vehicle::StatusCode;
|
||||
using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
|
||||
|
||||
class ConnectedClientTest : public ::testing::Test {
|
||||
public:
|
||||
void SetUp() override {
|
||||
mCallback = ndk::SharedRefBase::make<MockVehicleCallback>();
|
||||
mCallbackClient = IVehicleCallback::fromBinder(mCallback->asBinder());
|
||||
}
|
||||
|
||||
std::shared_ptr<IVehicleCallback> getCallbackClient() { return mCallbackClient; }
|
||||
|
||||
MockVehicleCallback* getCallback() { return mCallback.get(); }
|
||||
|
||||
protected:
|
||||
using GetValuesClient = GetSetValuesClient<GetValueResult, GetValueResults>;
|
||||
using SetValuesClient = GetSetValuesClient<SetValueResult, SetValueResults>;
|
||||
|
||||
private:
|
||||
std::shared_ptr<MockVehicleCallback> mCallback;
|
||||
std::shared_ptr<IVehicleCallback> mCallbackClient;
|
||||
};
|
||||
|
||||
TEST_F(ConnectedClientTest, testSendGetValueResults) {
|
||||
std::vector<GetValueResult> results = {{
|
||||
.requestId = 0,
|
||||
.status = StatusCode::OK,
|
||||
.prop =
|
||||
VehiclePropValue{
|
||||
.prop = 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
.requestId = 1,
|
||||
.status = StatusCode::OK,
|
||||
.prop =
|
||||
VehiclePropValue{
|
||||
.prop = 1,
|
||||
},
|
||||
}};
|
||||
|
||||
GetValuesClient client(getCallbackClient());
|
||||
|
||||
client.sendResults(results);
|
||||
|
||||
auto maybeGetValueResults = getCallback()->nextGetValueResults();
|
||||
ASSERT_TRUE(maybeGetValueResults.has_value());
|
||||
ASSERT_EQ(maybeGetValueResults.value().payloads, results);
|
||||
}
|
||||
|
||||
TEST_F(ConnectedClientTest, testSendGetValueResultsSeparately) {
|
||||
std::vector<GetValueResult> results = {{
|
||||
.requestId = 0,
|
||||
.status = StatusCode::OK,
|
||||
.prop =
|
||||
VehiclePropValue{
|
||||
.prop = 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
.requestId = 1,
|
||||
.status = StatusCode::OK,
|
||||
.prop =
|
||||
VehiclePropValue{
|
||||
.prop = 1,
|
||||
},
|
||||
}};
|
||||
|
||||
GetValuesClient client(getCallbackClient());
|
||||
|
||||
client.sendResultsSeparately(results);
|
||||
|
||||
for (auto& result : results) {
|
||||
auto maybeGetValueResults = getCallback()->nextGetValueResults();
|
||||
EXPECT_TRUE(maybeGetValueResults.has_value());
|
||||
if (!maybeGetValueResults.has_value()) {
|
||||
continue;
|
||||
}
|
||||
EXPECT_EQ(maybeGetValueResults.value().payloads, std::vector<GetValueResult>({result}));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ConnectedClientTest, testGetValuesGnResultCallback) {
|
||||
std::vector<GetValueResult> results = {{
|
||||
.requestId = 0,
|
||||
.status = StatusCode::OK,
|
||||
.prop =
|
||||
VehiclePropValue{
|
||||
.prop = 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
.requestId = 1,
|
||||
.status = StatusCode::OK,
|
||||
.prop =
|
||||
VehiclePropValue{
|
||||
.prop = 1,
|
||||
},
|
||||
}};
|
||||
|
||||
GetValuesClient client(getCallbackClient());
|
||||
|
||||
(*(client.getResultCallback()))(results);
|
||||
|
||||
auto maybeGetValueResults = getCallback()->nextGetValueResults();
|
||||
ASSERT_TRUE(maybeGetValueResults.has_value());
|
||||
ASSERT_EQ(maybeGetValueResults.value().payloads, results);
|
||||
}
|
||||
|
||||
TEST_F(ConnectedClientTest, testSendSetValueResults) {
|
||||
std::vector<SetValueResult> results = {{
|
||||
.requestId = 0,
|
||||
.status = StatusCode::OK,
|
||||
},
|
||||
{
|
||||
.requestId = 1,
|
||||
.status = StatusCode::OK,
|
||||
}};
|
||||
|
||||
SetValuesClient client(getCallbackClient());
|
||||
|
||||
client.sendResults(results);
|
||||
|
||||
auto maybeSetValueResults = getCallback()->nextSetValueResults();
|
||||
ASSERT_TRUE(maybeSetValueResults.has_value());
|
||||
ASSERT_EQ(maybeSetValueResults.value().payloads, results);
|
||||
}
|
||||
|
||||
TEST_F(ConnectedClientTest, testSendSetValueResultsSeparately) {
|
||||
std::vector<SetValueResult> results = {{
|
||||
.requestId = 0,
|
||||
.status = StatusCode::OK,
|
||||
},
|
||||
{
|
||||
.requestId = 1,
|
||||
.status = StatusCode::OK,
|
||||
}};
|
||||
|
||||
SetValuesClient client(getCallbackClient());
|
||||
|
||||
client.sendResultsSeparately(results);
|
||||
|
||||
for (auto& result : results) {
|
||||
auto maybeSetValueResults = getCallback()->nextSetValueResults();
|
||||
EXPECT_TRUE(maybeSetValueResults.has_value());
|
||||
if (!maybeSetValueResults.has_value()) {
|
||||
continue;
|
||||
}
|
||||
EXPECT_EQ(maybeSetValueResults.value().payloads, std::vector<SetValueResult>({result}));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ConnectedClientTest, testSetValuesGetResultCallback) {
|
||||
std::vector<SetValueResult> results = {{
|
||||
.requestId = 0,
|
||||
.status = StatusCode::OK,
|
||||
},
|
||||
{
|
||||
.requestId = 1,
|
||||
.status = StatusCode::OK,
|
||||
}};
|
||||
|
||||
SetValuesClient client(getCallbackClient());
|
||||
|
||||
(*(client.getResultCallback()))(results);
|
||||
|
||||
auto maybeSetValueResults = getCallback()->nextSetValueResults();
|
||||
ASSERT_TRUE(maybeSetValueResults.has_value());
|
||||
ASSERT_EQ(maybeSetValueResults.value().payloads, results);
|
||||
}
|
||||
|
||||
} // namespace vehicle
|
||||
} // namespace automotive
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "MockVehicleCallback.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace automotive {
|
||||
namespace vehicle {
|
||||
|
||||
namespace {
|
||||
|
||||
using ::aidl::android::hardware::automotive::vehicle::GetValueResults;
|
||||
using ::aidl::android::hardware::automotive::vehicle::SetValueResults;
|
||||
using ::aidl::android::hardware::automotive::vehicle::VehiclePropErrors;
|
||||
using ::aidl::android::hardware::automotive::vehicle::VehiclePropValues;
|
||||
using ::ndk::ScopedAStatus;
|
||||
using ::ndk::ScopedFileDescriptor;
|
||||
|
||||
template <class T>
|
||||
std::optional<T> pop(std::list<T>& items) {
|
||||
if (items.size() > 0) {
|
||||
auto item = std::move(items.front());
|
||||
items.pop_front();
|
||||
return item;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static ScopedAStatus storeResults(const T& results, std::list<T>* storedResults) {
|
||||
T resultsCopy{
|
||||
.payloads = results.payloads,
|
||||
};
|
||||
int fd = results.sharedMemoryFd.get();
|
||||
if (fd != -1) {
|
||||
resultsCopy.sharedMemoryFd = ScopedFileDescriptor(dup(fd));
|
||||
}
|
||||
storedResults->push_back(std::move(resultsCopy));
|
||||
return ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ScopedAStatus MockVehicleCallback::onGetValues(const GetValueResults& results) {
|
||||
std::scoped_lock<std::mutex> lockGuard(mLock);
|
||||
return storeResults(results, &mGetValueResults);
|
||||
}
|
||||
|
||||
ScopedAStatus MockVehicleCallback::onSetValues(const SetValueResults& results) {
|
||||
std::scoped_lock<std::mutex> lockGuard(mLock);
|
||||
return storeResults(results, &mSetValueResults);
|
||||
}
|
||||
|
||||
ScopedAStatus MockVehicleCallback::onPropertyEvent(const VehiclePropValues&, int32_t) {
|
||||
return ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ScopedAStatus MockVehicleCallback::onPropertySetError(const VehiclePropErrors&) {
|
||||
return ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
std::optional<GetValueResults> MockVehicleCallback::nextGetValueResults() {
|
||||
std::scoped_lock<std::mutex> lockGuard(mLock);
|
||||
return pop(mGetValueResults);
|
||||
}
|
||||
|
||||
std::optional<SetValueResults> MockVehicleCallback::nextSetValueResults() {
|
||||
std::scoped_lock<std::mutex> lockGuard(mLock);
|
||||
return pop(mSetValueResults);
|
||||
}
|
||||
|
||||
} // namespace vehicle
|
||||
} // namespace automotive
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
69
automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.h
Normal file
69
automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef android_hardware_automotive_vehicle_aidl_impl_vhal_test_MockVehicleCallback_H_
|
||||
#define android_hardware_automotive_vehicle_aidl_impl_vhal_test_MockVehicleCallback_H_
|
||||
|
||||
#include <VehicleHalTypes.h>
|
||||
|
||||
#include <aidl/android/hardware/automotive/vehicle/BnVehicleCallback.h>
|
||||
#include <android-base/thread_annotations.h>
|
||||
|
||||
#include <list>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace automotive {
|
||||
namespace vehicle {
|
||||
|
||||
// MockVehicleCallback is a mock VehicleCallback implementation that simply stores the results.
|
||||
class MockVehicleCallback final
|
||||
: public ::aidl::android::hardware::automotive::vehicle::BnVehicleCallback {
|
||||
public:
|
||||
::ndk::ScopedAStatus onGetValues(
|
||||
const ::aidl::android::hardware::automotive::vehicle::GetValueResults& results)
|
||||
override;
|
||||
::ndk::ScopedAStatus onSetValues(
|
||||
const ::aidl::android::hardware::automotive::vehicle::SetValueResults& results)
|
||||
override;
|
||||
::ndk::ScopedAStatus onPropertyEvent(
|
||||
const ::aidl::android::hardware::automotive::vehicle::VehiclePropValues&,
|
||||
int32_t) override;
|
||||
::ndk::ScopedAStatus onPropertySetError(
|
||||
const ::aidl::android::hardware::automotive::vehicle::VehiclePropErrors&) override;
|
||||
|
||||
// Test functions
|
||||
std::optional<::aidl::android::hardware::automotive::vehicle::GetValueResults>
|
||||
nextGetValueResults();
|
||||
std::optional<::aidl::android::hardware::automotive::vehicle::SetValueResults>
|
||||
nextSetValueResults();
|
||||
|
||||
private:
|
||||
std::mutex mLock;
|
||||
std::list<::aidl::android::hardware::automotive::vehicle::GetValueResults> mGetValueResults
|
||||
GUARDED_BY(mLock);
|
||||
std::list<::aidl::android::hardware::automotive::vehicle::SetValueResults> mSetValueResults
|
||||
GUARDED_BY(mLock);
|
||||
};
|
||||
|
||||
} // namespace vehicle
|
||||
} // namespace automotive
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // android_hardware_automotive_vehicle_aidl_impl_vhal_test_MockVehicleCallback_H_
|
||||
Reference in New Issue
Block a user