Merge "Add EXTERNAL_CAR_TIME property in the Vehicle HAL."
diff --git a/automotive/vehicle/2.0/utils/UserHalHelper.cpp b/automotive/vehicle/2.0/utils/UserHalHelper.cpp
index abf59b7..dccdb2b 100644
--- a/automotive/vehicle/2.0/utils/UserHalHelper.cpp
+++ b/automotive/vehicle/2.0/utils/UserHalHelper.cpp
@@ -60,11 +60,22 @@
<< int32Values.size();
}
userInfo->userId = int32Values[startPos];
- auto userFlags = verifyAndCast<UserFlags>(int32Values[startPos + 1]);
- if (!userFlags.ok()) {
- return Error() << "Invalid user flags: " << userFlags.error();
+ int32_t intUserFlags = int32Values[startPos + 1];
+ int32_t expectedUserFlags = 0;
+ for (const auto& v : hidl_enum_range<UserFlags>()) {
+ int32_t intEnumUserFlag = static_cast<int32_t>(v);
+ if ((intUserFlags & intEnumUserFlag) != 0) {
+ expectedUserFlags |= intEnumUserFlag;
+ }
}
- userInfo->flags = *userFlags;
+ if (intUserFlags != expectedUserFlags) {
+ return Error() << "Invalid user flags: " << intUserFlags << ", must be '|' of UserFlags";
+ }
+ // intUserFlags is actually not a valid UserFlags enum, instead, it is a 'bit or' of possible
+ // multiple UserFlags. However, because the HAL interface was defined incorrectly, we have to
+ // cast it to UserFlags here, which is defined behavior because the underlying type for
+ // UserFlags is int32_t and our intUserFlags is within the range of int32_t.
+ userInfo->flags = static_cast<UserFlags>(intUserFlags);
return {};
}
diff --git a/automotive/vehicle/2.0/utils/tests/UserHalHelper_test.cpp b/automotive/vehicle/2.0/utils/tests/UserHalHelper_test.cpp
index 7da87a2..0562a54 100644
--- a/automotive/vehicle/2.0/utils/tests/UserHalHelper_test.cpp
+++ b/automotive/vehicle/2.0/utils/tests/UserHalHelper_test.cpp
@@ -54,6 +54,10 @@
constexpr int32_t GUEST_USER = static_cast<int32_t>(UserFlags::GUEST);
constexpr int32_t NONE_USER = static_cast<int32_t>(UserFlags::NONE);
constexpr int32_t SYSTEM_USER = static_cast<int32_t>(UserFlags::SYSTEM);
+constexpr int32_t ADMIN_USER = static_cast<int32_t>(UserFlags::ADMIN);
+constexpr int32_t SYSTEM_ADMIN_USER = static_cast<int32_t>(UserFlags::SYSTEM | UserFlags::ADMIN);
+// 0x1111 is not a valid UserFlags combination.
+constexpr int32_t INVALID_USER_FLAG = 0x1111;
constexpr int32_t USER_ID_ASSOC_KEY_FOB =
static_cast<int32_t>(UserIdentificationAssociationType::KEY_FOB);
@@ -72,7 +76,7 @@
} // namespace
-TEST(UserHalHelperTest, TestToInitialUserInfoRequest) {
+TEST(UserHalHelperTest, TestToInitialUserInfoRequestSystemUser) {
VehiclePropValue propValue{
.prop = INITIAL_USER_INFO,
.value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0, SYSTEM_USER,
@@ -92,6 +96,58 @@
EXPECT_THAT(actual.value(), Eq(expected));
}
+TEST(UserHalHelperTest, TestToInitialUserInfoRequestAdminUser) {
+ VehiclePropValue propValue{
+ .prop = INITIAL_USER_INFO,
+ .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0, ADMIN_USER, 10,
+ NONE_USER}},
+ };
+ InitialUserInfoRequest expected{
+ .requestId = 23,
+ .requestType = InitialUserInfoRequestType::FIRST_BOOT_AFTER_OTA,
+ .usersInfo = {{10, UserFlags::NONE}, 2, {{0, UserFlags::ADMIN}, {10, UserFlags::NONE}}},
+ };
+
+ auto actual = toInitialUserInfoRequest(propValue);
+
+ ASSERT_TRUE(actual.ok()) << actual.error().message();
+ EXPECT_THAT(actual.value(), Eq(expected));
+}
+
+TEST(UserHalHelperTest, TestToInitialUserInfoRequestUserFlagsBitCombination) {
+ // SYSTEM_ADMIN_USER is two UserFlags combined and is itself not a defined UserFlags enum.
+ VehiclePropValue propValue{
+ .prop = INITIAL_USER_INFO,
+ .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0,
+ SYSTEM_ADMIN_USER, 10, NONE_USER}},
+ };
+ InitialUserInfoRequest expected{
+ .requestId = 23,
+ .requestType = InitialUserInfoRequestType::FIRST_BOOT_AFTER_OTA,
+ .usersInfo = {{10, UserFlags::NONE},
+ 2,
+ {{0, static_cast<UserFlags>(SYSTEM_ADMIN_USER)}, {10, UserFlags::NONE}}},
+ };
+
+ auto actual = toInitialUserInfoRequest(propValue);
+
+ ASSERT_TRUE(actual.ok()) << actual.error().message();
+ EXPECT_THAT(actual.value(), Eq(expected));
+}
+
+TEST(UserHalHelperTest, TestToInitialUserInfoRequestUserInvalidUserFlag) {
+ // 0x1111 is not a valid UserFlags flag combination.
+ VehiclePropValue propValue{
+ .prop = INITIAL_USER_INFO,
+ .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0,
+ INVALID_USER_FLAG, 10, NONE_USER}},
+ };
+
+ auto actual = toInitialUserInfoRequest(propValue);
+
+ EXPECT_FALSE(actual.ok()) << "No error returned on invalid user flags";
+}
+
TEST(UserHalHelperTest, TestFailsToInitialUserInfoRequestWithMismatchingPropType) {
VehiclePropValue propValue{
.prop = INT32_MAX,
diff --git a/automotive/vehicle/TEST_MAPPING b/automotive/vehicle/TEST_MAPPING
index 4820fd4..9924581 100644
--- a/automotive/vehicle/TEST_MAPPING
+++ b/automotive/vehicle/TEST_MAPPING
@@ -8,6 +8,12 @@
},
{
"name": "VehicleHalVehicleUtilsTest"
+ },
+ {
+ "name": "FakeVehicleHardwareTest"
+ },
+ {
+ "name": "FakeVehicleHalValueGeneratorsTest"
}
]
}
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/Android.bp b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/Android.bp
new file mode 100644
index 0000000..4735313
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/Android.bp
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_library {
+ name: "FakeVehicleHalValueGenerators",
+ vendor: true,
+ srcs: ["src/*.cpp"],
+ local_include_dirs: ["include"],
+ export_include_dirs: ["include"],
+ defaults: ["VehicleHalDefaults"],
+ static_libs: ["VehicleHalUtils"],
+ shared_libs: [
+ "libjsoncpp",
+ ],
+}
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/FakeValueGenerator.h b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/FakeValueGenerator.h
new file mode 100644
index 0000000..93ffebf
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/FakeValueGenerator.h
@@ -0,0 +1,46 @@
+/*
+ * 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_fake_impl_GeneratorHub_include_FakeValueGenerator_H_
+#define android_hardware_automotive_vehicle_aidl_impl_fake_impl_GeneratorHub_include_FakeValueGenerator_H_
+
+#include <VehicleHalTypes.h>
+
+#include <optional>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+
+// A abstract class for all fake value generators.
+class FakeValueGenerator {
+ public:
+ virtual ~FakeValueGenerator() = default;
+
+ // Returns the next event if there is one or {@code std::nullopt} if there is none.
+ virtual std::optional<::aidl::android::hardware::automotive::vehicle::VehiclePropValue>
+ nextEvent() = 0;
+};
+
+} // namespace fake
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_automotive_vehicle_aidl_impl_fake_impl_GeneratorHub_include_FakeValueGenerator_H_
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/GeneratorHub.h b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/GeneratorHub.h
new file mode 100644
index 0000000..ad04d23
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/GeneratorHub.h
@@ -0,0 +1,92 @@
+/*
+ * 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_interfaces_automotive_vehicle_aidl_fake_impl_GeneratorHub_include_GeneratorHub_h_
+#define android_hardware_interfaces_automotive_vehicle_aidl_fake_impl_GeneratorHub_include_GeneratorHub_h_
+
+#include "FakeValueGenerator.h"
+
+#include <android-base/thread_annotations.h>
+
+#include <atomic>
+#include <chrono>
+#include <condition_variable>
+#include <iostream>
+#include <mutex>
+#include <optional>
+#include <queue>
+#include <thread>
+#include <unordered_map>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+
+// This is the scheduler for all VHAL event generators. It manages all generators and uses priority
+// queue to maintain generated events ordered by timestamp. The scheduler uses a single thread to
+// keep querying and updating the event queue to make sure events from all generators are produced
+// in order.
+class GeneratorHub {
+ public:
+ using OnHalEvent = std::function<void(
+ const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& event)>;
+
+ explicit GeneratorHub(OnHalEvent&& onHalEvent);
+ ~GeneratorHub();
+
+ // Register a new generator. The generator will be discarded if it could not produce next event.
+ // The existing generator will be overridden if it has the same generatorId.
+ void registerGenerator(int32_t generatorId, std::unique_ptr<FakeValueGenerator> generator);
+
+ // Unregister a generator with the generatorId. If no registered generator is found, this
+ // function does nothing.
+ void unregisterGenerator(int32_t generatorId);
+
+ private:
+ struct VhalEvent {
+ int32_t generatorId;
+ ::aidl::android::hardware::automotive::vehicle::VehiclePropValue val;
+ };
+
+ // Comparator used by priority queue to keep track of soonest event.
+ struct GreaterByTime {
+ bool operator()(const VhalEvent& lhs, const VhalEvent& rhs) const {
+ return lhs.val.timestamp > rhs.val.timestamp;
+ }
+ };
+
+ std::priority_queue<VhalEvent, std::vector<VhalEvent>, GreaterByTime> mEventQueue;
+ std::mutex mGeneratorsLock;
+ std::unordered_map<int32_t, std::unique_ptr<FakeValueGenerator>> mGenerators
+ GUARDED_BY(mGeneratorsLock);
+ OnHalEvent mOnHalEvent;
+ std::condition_variable mCond;
+ std::thread mThread;
+ std::atomic<bool> mShuttingDownFlag{false};
+
+ // Main loop of the single thread to producing event and updating event queue.
+ void run();
+};
+
+} // namespace fake
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_interfaces_automotive_vehicle_aidl_fake_impl_GeneratorHub_include_GeneratorHub_h_
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/JsonFakeValueGenerator.h b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/JsonFakeValueGenerator.h
new file mode 100644
index 0000000..8116ed2
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/JsonFakeValueGenerator.h
@@ -0,0 +1,72 @@
+/*
+ * 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_fake_impl_GeneratorHub_include_JsonFakeValueGenerator_H_
+#define android_hardware_automotive_vehicle_aidl_impl_fake_impl_GeneratorHub_include_JsonFakeValueGenerator_H_
+
+#include "FakeValueGenerator.h"
+
+#include <json/json.h>
+
+#include <iostream>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+
+class JsonFakeValueGenerator : public FakeValueGenerator {
+ public:
+ // Create a new JSON fake value generator. {@code request.value.stringValue} is the JSON file
+ // name. {@code request.value.int32Values[1]} if exists, is the number of iterations. If
+ // {@code int32Values} has less than 2 elements, number of iterations would be set to -1, which
+ // means iterate indefinitely.
+ explicit JsonFakeValueGenerator(
+ const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& request);
+ // Create a new JSON fake value generator using the specified JSON file path. All the events
+ // in the JSON file would be generated for number of {@code iteration}. If iteration is 0, no
+ // value would be generated. If iteration is less than 0, it would iterate indefinitely.
+ explicit JsonFakeValueGenerator(const std::string& path, int32_t iteration);
+ // Create a new JSON fake value generator using the specified JSON file path. All the events
+ // in the JSON file would be generated once.
+ explicit JsonFakeValueGenerator(const std::string& path);
+
+ ~JsonFakeValueGenerator() = default;
+
+ std::optional<::aidl::android::hardware::automotive::vehicle::VehiclePropValue> nextEvent()
+ override;
+ const std::vector<::aidl::android::hardware::automotive::vehicle::VehiclePropValue>&
+ getAllEvents();
+
+ private:
+ size_t mEventIndex = 0;
+ std::vector<::aidl::android::hardware::automotive::vehicle::VehiclePropValue> mEvents;
+ long mLastEventTimestamp = 0;
+ int32_t mNumOfIterations = 0;
+
+ void setBit(std::vector<uint8_t>& bytes, size_t idx);
+ void init(const std::string& path, int32_t iteration);
+};
+
+} // namespace fake
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_automotive_vehicle_aidl_impl_fake_impl_GeneratorHub_include_JsonFakeValueGenerator_H_
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/LinearFakeValueGenerator.h b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/LinearFakeValueGenerator.h
new file mode 100644
index 0000000..bd004f3
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/LinearFakeValueGenerator.h
@@ -0,0 +1,75 @@
+/*
+ * 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_fake_impl_GeneratorHub_include_LinearFakeValueGenerator_H_
+#define android_hardware_automotive_vehicle_aidl_impl_fake_impl_GeneratorHub_include_LinearFakeValueGenerator_H_
+
+#include "FakeValueGenerator.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+
+class LinearFakeValueGenerator : public FakeValueGenerator {
+ public:
+ // A linear value generator initialized using values in request.
+ // int32Values[1]: propId
+ // floatValues[0]: middleValue and currentValue
+ // floatValues[1]: dispersion
+ // floatValues[2]: increment
+ // int64Values[0]: interval
+ // {@code propId} must be INT32 or INT64 or FLOAT type.
+ explicit LinearFakeValueGenerator(
+ const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& request);
+ // A linear value generator in range [middleValue - dispersion, middleValue + dispersion),
+ // starts at 'currentValue' and at each 'interval', increase by 'increment' and loop back if
+ // exceeds middleValue + dispersion. {@code propId} must be INT32 or INT64 or FLOAT type.
+ explicit LinearFakeValueGenerator(int32_t propId, float middleValue, float initValue,
+ float dispersion, float increment, int64_t interval);
+ ~LinearFakeValueGenerator() = default;
+
+ std::optional<::aidl::android::hardware::automotive::vehicle::VehiclePropValue> nextEvent()
+ override;
+
+ private:
+ // In every timer tick we may want to generate new value based on initial value for debug
+ // purpose. It's better to have sequential values to see if events gets delivered in order
+ // to the client.
+ struct GeneratorCfg {
+ int32_t propId;
+ float middleValue;
+ float currentValue; // Should be in range (middleValue +/- dispersion).
+ float dispersion; // Defines minimum and maximum value based on initial value.
+ float increment; // Value that we will be added to currentValue with each timer tick.
+ int64_t interval;
+ long lastEventTimestamp;
+ };
+
+ GeneratorCfg mGenCfg;
+
+ void initGenCfg(int32_t propId, float middleValue, float initValue, float dispersion,
+ float increment, int64_t interval);
+};
+
+} // namespace fake
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_automotive_vehicle_aidl_impl_fake_impl_GeneratorHub_include_LinearFakeValueGenerator_H_
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/GeneratorHub.cpp b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/GeneratorHub.cpp
new file mode 100644
index 0000000..0c182d9
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/GeneratorHub.cpp
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "GeneratorHub"
+
+#include "GeneratorHub.h"
+
+#include <utils/Log.h>
+#include <utils/SystemClock.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+
+using ::android::base::ScopedLockAssertion;
+
+GeneratorHub::GeneratorHub(OnHalEvent&& onHalEvent)
+ : mOnHalEvent(onHalEvent), mThread(&GeneratorHub::run, this) {}
+
+GeneratorHub::~GeneratorHub() {
+ mShuttingDownFlag.store(true);
+ mCond.notify_all();
+ if (mThread.joinable()) {
+ mThread.join();
+ }
+}
+
+void GeneratorHub::registerGenerator(int32_t id, std::unique_ptr<FakeValueGenerator> generator) {
+ {
+ std::scoped_lock<std::mutex> lockGuard(mGeneratorsLock);
+ auto maybeNextEvent = generator->nextEvent();
+ // Register only if the generator can produce at least one event.
+ if (maybeNextEvent.has_value()) {
+ // Push the next event if it is a new generator
+ if (mGenerators.find(id) == mGenerators.end()) {
+ ALOGI("%s: Registering new generator, id: %d", __func__, id);
+ mEventQueue.push({id, maybeNextEvent.value()});
+ }
+ mGenerators[id] = std::move(generator);
+ ALOGI("%s: Registered generator, id: %d", __func__, id);
+ }
+ }
+ mCond.notify_one();
+}
+
+void GeneratorHub::unregisterGenerator(int32_t id) {
+ {
+ std::scoped_lock<std::mutex> lockGuard(mGeneratorsLock);
+ mGenerators.erase(id);
+ }
+ mCond.notify_one();
+ ALOGI("%s: Unregistered generator, id: %d", __func__, id);
+}
+
+void GeneratorHub::run() {
+ while (!mShuttingDownFlag.load()) {
+ std::unique_lock<std::mutex> lock(mGeneratorsLock);
+ ScopedLockAssertion lock_assertion(mGeneratorsLock);
+ // Pop events whose generator does not exist (may be already unregistered)
+ while (!mEventQueue.empty() &&
+ mGenerators.find(mEventQueue.top().generatorId) == mGenerators.end()) {
+ mEventQueue.pop();
+ }
+ // Wait until event queue is not empty or shutting down flag is set.
+ // This would unlock mGeneratorsLock and reacquire later.
+ mCond.wait(lock, [this] { return !mEventQueue.empty() || mShuttingDownFlag.load(); });
+ if (mShuttingDownFlag.load()) {
+ break;
+ }
+
+ const VhalEvent& curEvent = mEventQueue.top();
+ long currentTime = elapsedRealtimeNano();
+ long waitTime =
+ curEvent.val.timestamp > currentTime ? curEvent.val.timestamp - currentTime : 0;
+ if (waitTime != 0) {
+ // Wait until the soonest event happen
+ if (mCond.wait_for(lock, std::chrono::nanoseconds(waitTime)) !=
+ std::cv_status::timeout) {
+ // It is possible that a new generator is registered and produced a sooner event, or
+ // current generator is unregistered, in this case the thread will re-evaluate the
+ // soonest event
+ ALOGI("Something happened while waiting");
+ continue;
+ }
+ }
+ // Now it's time to handle current event.
+ mOnHalEvent(curEvent.val);
+ // Update queue by popping current event and producing next event from the same generator
+ int32_t id = curEvent.generatorId;
+ mEventQueue.pop();
+ if (mGenerators.find(id) != mGenerators.end()) {
+ auto maybeNextEvent = mGenerators[id]->nextEvent();
+ if (maybeNextEvent.has_value()) {
+ mEventQueue.push({id, maybeNextEvent.value()});
+ continue;
+ }
+ }
+
+ ALOGI("%s: Generator ended, unregister it, id: %d", __func__, id);
+ mGenerators.erase(id);
+ }
+}
+
+} // namespace fake
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/JsonFakeValueGenerator.cpp b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/JsonFakeValueGenerator.cpp
new file mode 100644
index 0000000..521ce45
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/JsonFakeValueGenerator.cpp
@@ -0,0 +1,256 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "JsonFakeValueGenerator"
+
+#include "JsonFakeValueGenerator.h"
+
+#include <fstream>
+#include <type_traits>
+#include <typeinfo>
+
+#include <VehicleUtils.h>
+#include <android/binder_enums.h>
+#include <utils/Log.h>
+#include <utils/SystemClock.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+
+namespace {
+
+using ::aidl::android::hardware::automotive::vehicle::DiagnosticFloatSensorIndex;
+using ::aidl::android::hardware::automotive::vehicle::DiagnosticIntegerSensorIndex;
+using ::aidl::android::hardware::automotive::vehicle::RawPropValues;
+using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+
+template <class T>
+int getLastIndex() {
+ auto range = ::ndk::enum_range<T>();
+ auto it = range.begin();
+ while (std::next(it) != range.end()) {
+ it++;
+ }
+ return toInt(*it);
+}
+
+bool isDiagnosticProperty(int32_t prop) {
+ return prop == toInt(VehicleProperty::OBD2_LIVE_FRAME) ||
+ prop == toInt(VehicleProperty::OBD2_FREEZE_FRAME);
+}
+
+void setBit(std::vector<uint8_t>& bytes, size_t idx) {
+ uint8_t mask = 1 << (idx % 8);
+ bytes[idx / 8] |= mask;
+}
+
+template <typename T>
+void copyJsonArray(const Json::Value& jsonArray, std::vector<T>& dest) {
+ dest.resize(jsonArray.size());
+ for (Json::Value::ArrayIndex i = 0; i < jsonArray.size(); i++) {
+ if (std::is_same<T, int32_t>::value) {
+ dest[i] = jsonArray[i].asInt();
+ } else if (std::is_same<T, int64_t>::value) {
+ dest[i] = jsonArray[i].asInt64();
+ } else if (std::is_same<T, float>::value) {
+ dest[i] = jsonArray[i].asFloat();
+ }
+ }
+}
+
+void copyMixedValueJson(const Json::Value& jsonValue, RawPropValues& dest) {
+ copyJsonArray(jsonValue["int32Values"], dest.int32Values);
+ copyJsonArray(jsonValue["int64Values"], dest.int64Values);
+ copyJsonArray(jsonValue["floatValues"], dest.floatValues);
+ dest.stringValue = jsonValue["stringValue"].asString();
+}
+
+std::vector<uint8_t> generateDiagnosticBytes(const RawPropValues& diagnosticValue) {
+ size_t lastIntegerSensorIndex =
+ static_cast<size_t>(getLastIndex<DiagnosticIntegerSensorIndex>());
+ size_t lastFloatSensorIndex = static_cast<size_t>(getLastIndex<DiagnosticFloatSensorIndex>());
+
+ size_t byteSize = (lastIntegerSensorIndex + lastFloatSensorIndex + 2);
+ std::vector<uint8_t> bytes((byteSize + 7) / 8);
+
+ auto& int32Values = diagnosticValue.int32Values;
+ for (size_t i = 0; i < int32Values.size(); i++) {
+ if (int32Values[i] != 0) {
+ setBit(bytes, i);
+ }
+ }
+
+ auto& floatValues = diagnosticValue.floatValues;
+ for (size_t i = 0; i < floatValues.size(); i++) {
+ if (floatValues[i] != 0.0) {
+ setBit(bytes, i + lastIntegerSensorIndex + 1);
+ }
+ }
+ return bytes;
+}
+
+std::vector<VehiclePropValue> parseFakeValueJson(std::istream& is) {
+ std::vector<VehiclePropValue> fakeVhalEvents;
+
+ Json::CharReaderBuilder builder;
+ Json::Value rawEvents;
+ std::string errorMessage;
+ if (!Json::parseFromStream(builder, is, &rawEvents, &errorMessage)) {
+ ALOGE("%s: Failed to parse fake data JSON file. Error: %s", __func__, errorMessage.c_str());
+ return fakeVhalEvents;
+ }
+
+ for (Json::Value::ArrayIndex i = 0; i < rawEvents.size(); i++) {
+ Json::Value rawEvent = rawEvents[i];
+ if (!rawEvent.isObject()) {
+ ALOGE("%s: VHAL JSON event should be an object, %s", __func__,
+ rawEvent.toStyledString().c_str());
+ continue;
+ }
+ if (rawEvent["prop"].empty() || rawEvent["areaId"].empty() || rawEvent["value"].empty() ||
+ rawEvent["timestamp"].empty()) {
+ ALOGE("%s: VHAL JSON event has missing fields, skip it, %s", __func__,
+ rawEvent.toStyledString().c_str());
+ continue;
+ }
+ VehiclePropValue event = {
+ .timestamp = rawEvent["timestamp"].asInt64(),
+ .areaId = rawEvent["areaId"].asInt(),
+ .prop = rawEvent["prop"].asInt(),
+ };
+
+ Json::Value rawEventValue = rawEvent["value"];
+ auto& value = event.value;
+ int32_t count;
+ switch (getPropType(event.prop)) {
+ case VehiclePropertyType::BOOLEAN:
+ case VehiclePropertyType::INT32:
+ value.int32Values.resize(1);
+ value.int32Values[0] = rawEventValue.asInt();
+ break;
+ case VehiclePropertyType::INT64:
+ value.int64Values.resize(1);
+ value.int64Values[0] = rawEventValue.asInt64();
+ break;
+ case VehiclePropertyType::FLOAT:
+ value.floatValues.resize(1);
+ value.floatValues[0] = rawEventValue.asFloat();
+ break;
+ case VehiclePropertyType::STRING:
+ value.stringValue = rawEventValue.asString();
+ break;
+ case VehiclePropertyType::INT32_VEC:
+ value.int32Values.resize(rawEventValue.size());
+ count = 0;
+ for (auto& it : rawEventValue) {
+ value.int32Values[count++] = it.asInt();
+ }
+ break;
+ case VehiclePropertyType::MIXED:
+ copyMixedValueJson(rawEventValue, value);
+ if (isDiagnosticProperty(event.prop)) {
+ value.byteValues = generateDiagnosticBytes(value);
+ }
+ break;
+ default:
+ ALOGE("%s: unsupported type for property: 0x%x", __func__, event.prop);
+ continue;
+ }
+ fakeVhalEvents.push_back(event);
+ }
+ return fakeVhalEvents;
+}
+
+} // namespace
+
+JsonFakeValueGenerator::JsonFakeValueGenerator(const std::string& path) {
+ init(path, 1);
+}
+
+JsonFakeValueGenerator::JsonFakeValueGenerator(const std::string& path, int32_t iteration) {
+ init(path, iteration);
+}
+
+JsonFakeValueGenerator::JsonFakeValueGenerator(const VehiclePropValue& request) {
+ const auto& v = request.value;
+ // Iterate infinitely if iteration number is not provided
+ int32_t numOfIterations = v.int32Values.size() < 2 ? -1 : v.int32Values[1];
+
+ init(v.stringValue, numOfIterations);
+}
+
+void JsonFakeValueGenerator::init(const std::string& path, int32_t iteration) {
+ std::ifstream ifs(path);
+ if (!ifs) {
+ ALOGE("%s: couldn't open %s for parsing.", __func__, path.c_str());
+ return;
+ }
+ mEvents = parseFakeValueJson(ifs);
+ mNumOfIterations = iteration;
+}
+
+const std::vector<VehiclePropValue>& JsonFakeValueGenerator::getAllEvents() {
+ return mEvents;
+}
+
+std::optional<VehiclePropValue> JsonFakeValueGenerator::nextEvent() {
+ if (mNumOfIterations == 0 || mEvents.size() == 0) {
+ return std::nullopt;
+ }
+
+ VehiclePropValue generatedValue = mEvents[mEventIndex];
+
+ if (mLastEventTimestamp == 0) {
+ mLastEventTimestamp = elapsedRealtimeNano();
+ } else {
+ long nextEventTime = 0;
+ if (mEventIndex > 0) {
+ // All events (start from 2nd one) are supposed to happen in the future with a delay
+ // equals to the duration between previous and current event.
+ nextEventTime = mLastEventTimestamp +
+ (mEvents[mEventIndex].timestamp - mEvents[mEventIndex - 1].timestamp);
+ } else {
+ // We are starting another iteration, immediately send the next event after 1ms.
+ nextEventTime = mLastEventTimestamp + 1000000;
+ }
+ // Prevent overflow.
+ assert(nextEventTime > mLastEventTimestamp);
+ mLastEventTimestamp = nextEventTime;
+ }
+
+ mEventIndex++;
+ if (mEventIndex == mEvents.size()) {
+ mEventIndex = 0;
+ if (mNumOfIterations > 0) {
+ mNumOfIterations--;
+ }
+ }
+
+ generatedValue.timestamp = mLastEventTimestamp;
+
+ return generatedValue;
+}
+
+} // namespace fake
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/LinearFakeValueGenerator.cpp b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/LinearFakeValueGenerator.cpp
new file mode 100644
index 0000000..9133144
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/LinearFakeValueGenerator.cpp
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "LinearFakeValueGenerator"
+
+#include "LinearFakeValueGenerator.h"
+
+#include <VehicleUtils.h>
+#include <utils/Log.h>
+#include <utils/SystemClock.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+
+LinearFakeValueGenerator::LinearFakeValueGenerator(int32_t propId, float middleValue,
+ float initValue, float dispersion,
+ float increment, int64_t interval) {
+ initGenCfg(propId, middleValue, initValue, dispersion, increment, interval);
+}
+
+LinearFakeValueGenerator::LinearFakeValueGenerator(const VehiclePropValue& request) {
+ const auto& v = request.value;
+ initGenCfg(v.int32Values[1], v.floatValues[0], v.floatValues[0], v.floatValues[1],
+ v.floatValues[2], v.int64Values[0]);
+}
+
+void LinearFakeValueGenerator::initGenCfg(int32_t propId, float middleValue, float initValue,
+ float dispersion, float increment, int64_t interval) {
+ // Other types are not supported.
+ assert(getPropType(propId) == VehicleProperty::INT32 ||
+ getPropType(propId) == VehicleProperty::INT64 ||
+ getPropType(propId) == VehicleProperty::FLOAT);
+
+ if (initValue < middleValue - dispersion || initValue >= middleValue + dispersion) {
+ ALOGW("%s: invalid initValue: %f, out of range, default to %f", __func__, initValue,
+ middleValue);
+ initValue = middleValue;
+ }
+ mGenCfg = GeneratorCfg{
+ .propId = propId,
+ .middleValue = middleValue,
+ .currentValue = initValue,
+ .dispersion = dispersion,
+ .increment = increment,
+ .interval = interval,
+ };
+}
+
+std::optional<VehiclePropValue> LinearFakeValueGenerator::nextEvent() {
+ VehiclePropValue event = {
+ .prop = mGenCfg.propId,
+ };
+ auto& value = event.value;
+ switch (getPropType(event.prop)) {
+ case VehiclePropertyType::INT32:
+ value.int32Values = {static_cast<int32_t>(mGenCfg.currentValue)};
+ break;
+ case VehiclePropertyType::INT64:
+ value.int64Values = {static_cast<int64_t>(mGenCfg.currentValue)};
+ break;
+ case VehiclePropertyType::FLOAT:
+ value.floatValues = {mGenCfg.currentValue};
+ break;
+ default:
+ ALOGE("%s: unsupported property type for 0x%x", __func__, event.prop);
+ }
+ if (mGenCfg.lastEventTimestamp == 0) {
+ mGenCfg.lastEventTimestamp = elapsedRealtimeNano();
+ } else {
+ long nextEventTime = mGenCfg.lastEventTimestamp + mGenCfg.interval;
+ // Prevent overflow.
+ assert(nextEventTime > mGenCfg.lastEventTimestamp);
+ mGenCfg.lastEventTimestamp = nextEventTime;
+ }
+ event.timestamp = mGenCfg.lastEventTimestamp;
+
+ mGenCfg.currentValue += mGenCfg.increment;
+ if (mGenCfg.currentValue >= mGenCfg.middleValue + mGenCfg.dispersion) {
+ // Wrap around, (i - d) + c - (i + d) = c - 2 * d
+ mGenCfg.currentValue = mGenCfg.currentValue - 2 * mGenCfg.dispersion;
+ }
+ return event;
+}
+
+} // namespace fake
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/Android.bp b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/Android.bp
new file mode 100644
index 0000000..d3d3a10
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/Android.bp
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+ name: "FakeVehicleHalValueGeneratorsTest",
+ vendor: true,
+ srcs: ["*.cpp"],
+ defaults: ["VehicleHalDefaults"],
+ static_libs: [
+ "VehicleHalUtils",
+ "FakeVehicleHalValueGenerators",
+ ],
+ shared_libs: [
+ "libjsoncpp",
+ ],
+ data: [
+ ":FakeVehicleHalValueGeneratorsTestFiles",
+ ],
+ test_suites: ["device-tests"],
+}
+
+filegroup {
+ name: "FakeVehicleHalValueGeneratorsTestFiles",
+ srcs: [
+ "prop.json",
+ "prop_invalid.json",
+ ],
+}
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/FakeVehicleHalValueGeneratorsTest.cpp b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/FakeVehicleHalValueGeneratorsTest.cpp
new file mode 100644
index 0000000..21aa680
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/FakeVehicleHalValueGeneratorsTest.cpp
@@ -0,0 +1,417 @@
+/*
+ * 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 <GeneratorHub.h>
+#include <JsonFakeValueGenerator.h>
+#include <LinearFakeValueGenerator.h>
+#include <VehicleUtils.h>
+#include <android-base/file.h>
+#include <android-base/thread_annotations.h>
+#include <gtest/gtest.h>
+#include <utils/SystemClock.h>
+
+#include <chrono>
+#include <memory>
+#include <mutex>
+#include <optional>
+#include <thread>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+
+using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+
+class FakeVehicleHalValueGeneratorsTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ mHub = std::make_unique<GeneratorHub>(
+ [this](const VehiclePropValue& event) { return onHalEvent(event); });
+ }
+
+ GeneratorHub* getHub() { return mHub.get(); }
+
+ std::vector<VehiclePropValue> getEvents() {
+ std::scoped_lock<std::mutex> lockGuard(mEventsLock);
+ return mEvents;
+ }
+
+ void clearEvents() {
+ std::scoped_lock<std::mutex> lockGuard(mEventsLock);
+ mEvents.clear();
+ }
+
+ void TearDown() override {
+ // Generator callback uses mEvents, must stop generator before destroying mEvents.
+ mHub.reset();
+ }
+
+ static std::string getTestFilePath(const char* filename) {
+ static std::string baseDir = android::base::GetExecutableDirectory();
+ return baseDir + "/" + filename;
+ }
+
+ private:
+ void onHalEvent(const VehiclePropValue& event) {
+ VehiclePropValue eventCopy = event;
+ std::scoped_lock<std::mutex> lockGuard(mEventsLock);
+ mEvents.push_back(std::move(eventCopy));
+ }
+
+ std::unique_ptr<GeneratorHub> mHub;
+ std::mutex mEventsLock;
+ std::vector<VehiclePropValue> mEvents GUARDED_BY(mEventsLock);
+};
+
+class TestFakeValueGenerator : public FakeValueGenerator {
+ public:
+ void setEvents(const std::vector<VehiclePropValue>& events) {
+ mEvents = events;
+ mEventIndex = 0;
+ }
+
+ std::optional<::aidl::android::hardware::automotive::vehicle::VehiclePropValue> nextEvent()
+ override {
+ if (mEventIndex == mEvents.size()) {
+ return std::nullopt;
+ }
+ return mEvents[mEventIndex++];
+ }
+
+ private:
+ std::vector<VehiclePropValue> mEvents;
+ size_t mEventIndex = 0;
+};
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testRegisterTestFakeValueGenerator) {
+ auto generator = std::make_unique<TestFakeValueGenerator>();
+ std::vector<VehiclePropValue> events;
+ size_t eventCount = 10;
+ int64_t timestamp = elapsedRealtimeNano();
+ for (size_t i = 0; i < eventCount; i++) {
+ events.push_back(VehiclePropValue{
+ .prop = static_cast<int32_t>(i),
+ .timestamp = timestamp + static_cast<int64_t>(50 * i),
+ });
+ }
+ generator->setEvents(events);
+
+ getHub()->registerGenerator(0, std::move(generator));
+
+ // All the events require 500ms to generate, so waiting for 1000ms should be enough.
+ std::this_thread::sleep_for(std::chrono::milliseconds(1000));
+
+ ASSERT_EQ(getEvents(), events);
+
+ getHub()->unregisterGenerator(0);
+}
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testUnregisterGeneratorStopGeneration) {
+ auto generator = std::make_unique<TestFakeValueGenerator>();
+ std::vector<VehiclePropValue> events;
+ size_t eventCount = 10;
+ int64_t timestamp = elapsedRealtimeNano();
+ for (size_t i = 0; i < eventCount; i++) {
+ events.push_back(VehiclePropValue{
+ .prop = static_cast<int32_t>(i),
+ .timestamp = timestamp + static_cast<int64_t>(50 * i),
+ });
+ }
+ generator->setEvents(events);
+
+ getHub()->registerGenerator(0, std::move(generator));
+ getHub()->unregisterGenerator(0);
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(1000));
+
+ ASSERT_LT(getEvents().size(), static_cast<size_t>(10))
+ << "Must stop generating event after generator is unregistered";
+}
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testLinerFakeValueGeneratorFloat) {
+ std::unique_ptr<LinearFakeValueGenerator> generator =
+ std::make_unique<LinearFakeValueGenerator>(toInt(VehicleProperty::PERF_VEHICLE_SPEED),
+ /*middleValue=*/50.0,
+ /*initValue=*/30.0,
+ /*dispersion=*/50.0,
+ /*increment=*/20.0,
+ /*interval=*/10000000);
+ getHub()->registerGenerator(0, std::move(generator));
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+ auto events = getEvents();
+ // We should get 10 events ideally, but let's be safe here.
+ ASSERT_LE((size_t)5, events.size());
+ int value = 30;
+ for (size_t i = 0; i < 5; i++) {
+ EXPECT_EQ(std::vector<float>({static_cast<float>(value)}), events[i].value.floatValues);
+ value = (value + 20) % 100;
+ }
+}
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testLinerFakeValueGeneratorInt32) {
+ std::unique_ptr<LinearFakeValueGenerator> generator =
+ std::make_unique<LinearFakeValueGenerator>(toInt(VehicleProperty::INFO_MODEL_YEAR),
+ /*middleValue=*/50.0,
+ /*initValue=*/30.0,
+ /*dispersion=*/50.0,
+ /*increment=*/20.0,
+ /*interval=*/10000000);
+ getHub()->registerGenerator(0, std::move(generator));
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+ auto events = getEvents();
+ // We should get 10 events ideally, but let's be safe here.
+ ASSERT_LE((size_t)5, events.size());
+ int value = 30;
+ for (size_t i = 0; i < 5; i++) {
+ EXPECT_EQ(std::vector<int32_t>({value}), events[i].value.int32Values);
+ value = (value + 20) % 100;
+ }
+}
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testLinerFakeValueGeneratorInt64) {
+ std::unique_ptr<LinearFakeValueGenerator> generator =
+ std::make_unique<LinearFakeValueGenerator>(toInt(VehicleProperty::ANDROID_EPOCH_TIME),
+ /*middleValue=*/50.0,
+ /*initValue=*/30.0,
+ /*dispersion=*/50.0,
+ /*increment=*/20.0,
+ /*interval=*/10000000);
+ getHub()->registerGenerator(0, std::move(generator));
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+ auto events = getEvents();
+ // We should get 10 events ideally, but let's be safe here.
+ ASSERT_LE((size_t)5, events.size());
+ int value = 30;
+ for (size_t i = 0; i < 5; i++) {
+ EXPECT_EQ(std::vector<int64_t>({value}), events[i].value.int64Values);
+ value = (value + 20) % 100;
+ }
+}
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testLinerFakeValueGeneratorUsingRequest) {
+ VehiclePropValue request;
+ request.value.int32Values = {0, toInt(VehicleProperty::PERF_VEHICLE_SPEED)};
+ request.value.floatValues = {/*middleValue=*/50.0, /*dispersion=*/50.0, /*increment=*/20.0};
+ request.value.int64Values = {/*interval=*/10000000};
+
+ std::unique_ptr<LinearFakeValueGenerator> generator =
+ std::make_unique<LinearFakeValueGenerator>(request);
+ getHub()->registerGenerator(0, std::move(generator));
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+ auto events = getEvents();
+ // We should get 10 events ideally, but let's be safe here.
+ ASSERT_LE((size_t)5, events.size());
+ int value = 50;
+ for (size_t i = 0; i < 5; i++) {
+ EXPECT_EQ(std::vector<float>({static_cast<float>(value)}), events[i].value.floatValues);
+ value = (value + 20) % 100;
+ }
+}
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testLinerFakeValueGeneratorInvalidInitValue) {
+ std::unique_ptr<LinearFakeValueGenerator> generator =
+ std::make_unique<LinearFakeValueGenerator>(toInt(VehicleProperty::PERF_VEHICLE_SPEED),
+ /*middleValue=*/50.0,
+ // Out of range
+ /*initValue=*/110.0,
+ /*dispersion=*/50.0,
+ /*increment=*/20.0,
+ /*interval=*/10000000);
+ getHub()->registerGenerator(0, std::move(generator));
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+ auto events = getEvents();
+ // We should get 10 events ideally, but let's be safe here.
+ ASSERT_LE((size_t)5, events.size());
+
+ // Init value would be set to middleValue if given initValue is not valid.
+ int value = 50;
+ for (size_t i = 0; i < 5; i++) {
+ EXPECT_EQ(std::vector<float>({static_cast<float>(value)}), events[i].value.floatValues);
+ value = (value + 20) % 100;
+ }
+}
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testJsonFakeValueGenerator) {
+ long currentTime = elapsedRealtimeNano();
+
+ std::unique_ptr<JsonFakeValueGenerator> generator =
+ std::make_unique<JsonFakeValueGenerator>(getTestFilePath("prop.json"), 2);
+ getHub()->registerGenerator(0, std::move(generator));
+
+ // wait for some time.
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+ std::vector<VehiclePropValue> expectedValues = {
+ VehiclePropValue{
+ .areaId = 0,
+ .value.int32Values = {8},
+ .prop = 289408000,
+ },
+ VehiclePropValue{
+ .areaId = 0,
+ .value.int32Values = {4},
+ .prop = 289408000,
+ },
+ VehiclePropValue{
+ .areaId = 0,
+ .value.int32Values = {16},
+ .prop = 289408000,
+ },
+ VehiclePropValue{
+ .areaId = 0,
+ .value.int32Values = {10},
+ .prop = 289408000,
+ },
+ };
+
+ // We have two iterations.
+ for (size_t i = 0; i < 4; i++) {
+ expectedValues.push_back(expectedValues[i]);
+ }
+
+ auto events = getEvents();
+
+ long lastEventTime = currentTime;
+ for (auto& event : events) {
+ EXPECT_GT(event.timestamp, lastEventTime);
+ lastEventTime = event.timestamp;
+ event.timestamp = 0;
+ }
+
+ EXPECT_EQ(events, expectedValues);
+}
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testJsonFakeValueGeneratorIterateIndefinitely) {
+ std::unique_ptr<JsonFakeValueGenerator> generator =
+ std::make_unique<JsonFakeValueGenerator>(getTestFilePath("prop.json"), -1);
+ getHub()->registerGenerator(0, std::move(generator));
+
+ // wait for some time.
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+ auto events = getEvents();
+
+ // Send 1 iteration takes 4ms + 1ms interval between iteration, so for 100ms we should get about
+ // 20 iteration, which is 80 events.
+ EXPECT_GT(events.size(), static_cast<size_t>(50));
+}
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testJsonFakeValueGeneratorUsingRequest) {
+ long currentTime = elapsedRealtimeNano();
+
+ VehiclePropValue request = {.value = {
+ .stringValue = getTestFilePath("prop.json"),
+ .int32Values = {0, 2},
+ }};
+
+ std::unique_ptr<JsonFakeValueGenerator> generator =
+ std::make_unique<JsonFakeValueGenerator>(request);
+ getHub()->registerGenerator(0, std::move(generator));
+
+ // wait for some time.
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+ std::vector<VehiclePropValue> expectedValues = {
+ VehiclePropValue{
+ .areaId = 0,
+ .value.int32Values = {8},
+ .prop = 289408000,
+ },
+ VehiclePropValue{
+ .areaId = 0,
+ .value.int32Values = {4},
+ .prop = 289408000,
+ },
+ VehiclePropValue{
+ .areaId = 0,
+ .value.int32Values = {16},
+ .prop = 289408000,
+ },
+ VehiclePropValue{
+ .areaId = 0,
+ .value.int32Values = {10},
+ .prop = 289408000,
+ },
+ };
+
+ // We have two iterations.
+ for (size_t i = 0; i < 4; i++) {
+ expectedValues.push_back(expectedValues[i]);
+ }
+
+ auto events = getEvents();
+
+ long lastEventTime = currentTime;
+ for (auto& event : events) {
+ EXPECT_GT(event.timestamp, lastEventTime);
+ lastEventTime = event.timestamp;
+ event.timestamp = 0;
+ }
+
+ EXPECT_EQ(events, expectedValues);
+}
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testJsonFakeValueGeneratorInvalidFile) {
+ VehiclePropValue request = {.value = {
+ .stringValue = getTestFilePath("prop_invalid.json"),
+ .int32Values = {0, 2},
+ }};
+
+ std::unique_ptr<JsonFakeValueGenerator> generator =
+ std::make_unique<JsonFakeValueGenerator>(request);
+ getHub()->registerGenerator(0, std::move(generator));
+
+ // wait for some time.
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+ ASSERT_TRUE(getEvents().empty());
+}
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testJsonFakeValueGeneratorNonExistingFile) {
+ VehiclePropValue request = {.value = {
+ .stringValue = "non_existing_file",
+ .int32Values = {0, 2},
+ }};
+
+ std::unique_ptr<JsonFakeValueGenerator> generator =
+ std::make_unique<JsonFakeValueGenerator>(request);
+ getHub()->registerGenerator(0, std::move(generator));
+
+ // wait for some time.
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+ ASSERT_TRUE(getEvents().empty());
+}
+
+} // namespace fake
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/prop.json b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/prop.json
new file mode 100644
index 0000000..b881109
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/prop.json
@@ -0,0 +1,26 @@
+[
+ {
+ "timestamp": 1000000,
+ "areaId": 0,
+ "value": 8,
+ "prop": 289408000
+ },
+ {
+ "timestamp": 2000000,
+ "areaId": 0,
+ "value": 4,
+ "prop": 289408000
+ },
+ {
+ "timestamp": 3000000,
+ "areaId": 0,
+ "value": 16,
+ "prop": 289408000
+ },
+ {
+ "timestamp": 4000000,
+ "areaId": 0,
+ "value": 10,
+ "prop": 289408000
+ }
+]
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/prop_invalid.json b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/prop_invalid.json
new file mode 100644
index 0000000..98232c6
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/prop_invalid.json
@@ -0,0 +1 @@
+{
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
index 2aa949a..dee36f4 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
@@ -32,6 +32,7 @@
namespace hardware {
namespace automotive {
namespace vehicle {
+namespace fake {
class FakeVehicleHardware final : public IVehicleHardware {
public:
@@ -94,6 +95,7 @@
OnPropertySetErrorCallback mOnPropertySetErrorCallback GUARDED_BY(mCallbackLock);
};
+} // namespace fake
} // namespace vehicle
} // namespace automotive
} // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
index b091517..f8bf7de 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
@@ -28,6 +28,7 @@
namespace hardware {
namespace automotive {
namespace vehicle {
+namespace fake {
using ::aidl::android::hardware::automotive::vehicle::GetValueRequest;
using ::aidl::android::hardware::automotive::vehicle::GetValueResult;
@@ -106,15 +107,67 @@
return mServerSidePropStore->getAllConfigs();
}
-StatusCode FakeVehicleHardware::setValues(FakeVehicleHardware::SetValuesCallback&&,
- const std::vector<SetValueRequest>&) {
- // TODO(b/201830716): Implement this.
+StatusCode FakeVehicleHardware::setValues(FakeVehicleHardware::SetValuesCallback&& callback,
+ const std::vector<SetValueRequest>& requests) {
+ std::vector<VehiclePropValue> updatedValues;
+ std::vector<SetValueResult> results;
+ for (auto& request : requests) {
+ const VehiclePropValue* value = &request.value;
+ ALOGD("setValues(%d)", value->prop);
+
+ auto updatedValue = mValuePool->obtain(*value);
+ int64_t timestamp = elapsedRealtimeNano();
+ updatedValue->timestamp = timestamp;
+
+ auto writeResult = mServerSidePropStore->writeValue(std::move(updatedValue));
+ SetValueResult setValueResult;
+ setValueResult.requestId = request.requestId;
+ if (!writeResult.ok()) {
+ ALOGE("failed to write value into property store, error: %s, code: %d",
+ writeResult.error().message().c_str(), writeResult.error().code());
+ setValueResult.status = StatusCode::INVALID_ARG;
+ } else {
+ setValueResult.status = StatusCode::OK;
+ }
+ results.push_back(std::move(setValueResult));
+ }
+
+ // In the real vhal, the values will be sent to Car ECU. We just pretend it is done here and
+ // send back the updated property values to client.
+ callback(std::move(results));
+
return StatusCode::OK;
}
-StatusCode FakeVehicleHardware::getValues(FakeVehicleHardware::GetValuesCallback&&,
- const std::vector<GetValueRequest>&) const {
- // TODO(b/201830716): Implement this.
+StatusCode FakeVehicleHardware::getValues(FakeVehicleHardware::GetValuesCallback&& callback,
+ const std::vector<GetValueRequest>& requests) const {
+ std::vector<GetValueResult> results;
+ for (auto& request : requests) {
+ const VehiclePropValue* value = &request.prop;
+ ALOGD("getValues(%d)", value->prop);
+
+ auto readResult = mServerSidePropStore->readValue(*value);
+ GetValueResult getValueResult;
+ getValueResult.requestId = request.requestId;
+ if (!readResult.ok()) {
+ auto error = readResult.error();
+ if (error.code() == toInt(StatusCode::NOT_AVAILABLE)) {
+ ALOGW("%s", "value has not been set yet");
+ getValueResult.status = StatusCode::NOT_AVAILABLE;
+ } else {
+ ALOGE("failed to get value, error: %s, code: %d", error.message().c_str(),
+ error.code());
+ getValueResult.status = StatusCode::INVALID_ARG;
+ }
+ } else {
+ getValueResult.status = StatusCode::OK;
+ getValueResult.prop = *readResult.value();
+ }
+ results.push_back(std::move(getValueResult));
+ }
+
+ callback(std::move(results));
+
return StatusCode::OK;
}
@@ -130,17 +183,17 @@
}
void FakeVehicleHardware::registerOnPropertyChangeEvent(OnPropertyChangeCallback&& callback) {
- std::lock_guard<std::mutex> lockGuard(mCallbackLock);
+ std::scoped_lock<std::mutex> lockGuard(mCallbackLock);
mOnPropertyChangeCallback = std::move(callback);
}
void FakeVehicleHardware::registerOnPropertySetErrorEvent(OnPropertySetErrorCallback&& callback) {
- std::lock_guard<std::mutex> lockGuard(mCallbackLock);
+ std::scoped_lock<std::mutex> lockGuard(mCallbackLock);
mOnPropertySetErrorCallback = std::move(callback);
}
void FakeVehicleHardware::onValueChangeCallback(const VehiclePropValue& value) {
- std::lock_guard<std::mutex> lockGuard(mCallbackLock);
+ std::scoped_lock<std::mutex> lockGuard(mCallbackLock);
if (mOnPropertyChangeCallback != nullptr) {
std::vector<VehiclePropValue> updatedValues;
updatedValues.push_back(value);
@@ -148,6 +201,7 @@
}
}
+} // namespace fake
} // namespace vehicle
} // namespace automotive
} // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
index d901b38..53e647d 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
@@ -24,6 +24,7 @@
namespace hardware {
namespace automotive {
namespace vehicle {
+namespace fake {
namespace {
@@ -41,6 +42,8 @@
using ::testing::Eq;
using ::testing::WhenSortedBy;
+constexpr int INVALID_PROP_ID = 0;
+
} // namespace
class FakeVehicleHardwareTest : public ::testing::Test {
@@ -159,6 +162,269 @@
ASSERT_EQ(configs.size(), defaultconfig::getDefaultConfigs().size());
}
+TEST_F(FakeVehicleHardwareTest, testGetDefaultValues) {
+ std::vector<GetValueRequest> getValueRequests;
+ std::vector<GetValueResult> expectedGetValueResults;
+ int64_t requestId = 1;
+
+ for (auto& config : defaultconfig::getDefaultConfigs()) {
+ int propId = config.config.prop;
+ if (isGlobalProp(propId)) {
+ if (config.initialValue == RawPropValues{}) {
+ addGetValueRequest(getValueRequests, expectedGetValueResults, requestId++,
+ VehiclePropValue{.prop = propId}, StatusCode::NOT_AVAILABLE);
+ continue;
+ }
+ addGetValueRequest(getValueRequests, expectedGetValueResults, requestId++,
+ VehiclePropValue{
+ .prop = propId,
+ .value = config.initialValue,
+ },
+ StatusCode::OK);
+ continue;
+ }
+ for (auto areaConfig : config.config.areaConfigs) {
+ StatusCode status = StatusCode::OK;
+ VehiclePropValue propValue{
+ .prop = propId,
+ .areaId = areaConfig.areaId,
+ };
+ if (config.initialAreaValues.empty()) {
+ if (config.initialValue == RawPropValues{}) {
+ status = StatusCode::NOT_AVAILABLE;
+ } else {
+ propValue.value = config.initialValue;
+ }
+ } else if (auto valueForAreaIt = config.initialAreaValues.find(areaConfig.areaId);
+ valueForAreaIt != config.initialAreaValues.end()) {
+ propValue.value = valueForAreaIt->second;
+ } else {
+ status = StatusCode::NOT_AVAILABLE;
+ }
+ addGetValueRequest(getValueRequests, expectedGetValueResults, requestId++, propValue,
+ status);
+ }
+ }
+
+ // In our implementation, this would finish immediately.
+ StatusCode status = getValues(getValueRequests);
+
+ ASSERT_EQ(status, StatusCode::OK);
+
+ std::vector<GetValueResult> getValueResultsWithNoTimestamp;
+ for (auto& result : getGetValueResults()) {
+ GetValueResult resultCopy = result;
+ resultCopy.prop->timestamp = 0;
+ getValueResultsWithNoTimestamp.push_back(std::move(resultCopy));
+ }
+ ASSERT_THAT(getValueResultsWithNoTimestamp, ContainerEq(expectedGetValueResults));
+}
+
+TEST_F(FakeVehicleHardwareTest, testSetValues) {
+ std::vector<SetValueRequest> requests;
+ std::vector<SetValueResult> expectedResults;
+
+ int64_t requestId = 1;
+ for (auto& value : getTestPropValues()) {
+ addSetValueRequest(requests, expectedResults, requestId++, value, StatusCode::OK);
+ }
+
+ StatusCode status = setValues(requests);
+
+ ASSERT_EQ(status, StatusCode::OK);
+
+ // Although callback might be called asynchronously, in our implementation, the callback would
+ // be called before setValues returns.
+ ASSERT_THAT(getSetValueResults(), ContainerEq(expectedResults));
+}
+
+TEST_F(FakeVehicleHardwareTest, testSetValuesError) {
+ std::vector<SetValueRequest> requests;
+ std::vector<SetValueResult> expectedResults;
+
+ int64_t requestId = 1;
+
+ VehiclePropValue invalidProp = {
+ .prop = INVALID_PROP_ID,
+ };
+ addSetValueRequest(requests, expectedResults, requestId++, invalidProp,
+ StatusCode::INVALID_ARG);
+
+ for (auto& value : getTestPropValues()) {
+ addSetValueRequest(requests, expectedResults, requestId++, value, StatusCode::OK);
+ }
+
+ StatusCode status = setValues(requests);
+
+ ASSERT_EQ(status, StatusCode::OK);
+
+ // Although callback might be called asynchronously, in our implementation, the callback would
+ // be called before setValues returns.
+ ASSERT_THAT(getSetValueResults(), ContainerEq(expectedResults));
+}
+
+TEST_F(FakeVehicleHardwareTest, testRegisterOnPropertyChangeEvent) {
+ getHardware()->registerOnPropertyChangeEvent(std::bind(
+ &FakeVehicleHardwareTest_testRegisterOnPropertyChangeEvent_Test::onPropertyChangeEvent,
+ this, std::placeholders::_1));
+
+ auto testValues = getTestPropValues();
+ std::vector<SetValueRequest> requests;
+ std::vector<SetValueResult> expectedResults;
+ int64_t requestId = 1;
+ for (auto& value : testValues) {
+ addSetValueRequest(requests, expectedResults, requestId++, value, StatusCode::OK);
+ }
+ int64_t timestamp = elapsedRealtimeNano();
+
+ StatusCode status = setValues(requests);
+
+ ASSERT_EQ(status, StatusCode::OK);
+
+ auto updatedValues = getChangedProperties();
+ std::vector<VehiclePropValue> updatedValuesWithNoTimestamp;
+ for (auto& value : updatedValues) {
+ ASSERT_GE(value.timestamp, timestamp);
+ VehiclePropValue valueCopy = value;
+ valueCopy.timestamp = 0;
+ updatedValuesWithNoTimestamp.push_back(std::move(valueCopy));
+ }
+
+ ASSERT_THAT(updatedValuesWithNoTimestamp, WhenSortedBy(mPropValueCmp, Eq(testValues)));
+}
+
+TEST_F(FakeVehicleHardwareTest, testReadValues) {
+ std::vector<SetValueRequest> setValueRequests;
+ std::vector<SetValueResult> expectedSetValueResults;
+
+ int64_t requestId = 1;
+ for (auto& value : getTestPropValues()) {
+ addSetValueRequest(setValueRequests, expectedSetValueResults, requestId++, value,
+ StatusCode::OK);
+ }
+ int64_t timestamp = elapsedRealtimeNano();
+
+ // In our implementation, this would finish immediately.
+ StatusCode status = setValues(setValueRequests);
+
+ ASSERT_EQ(status, StatusCode::OK);
+
+ std::vector<GetValueRequest> getValueRequests;
+ std::vector<GetValueResult> expectedGetValueResults;
+ for (auto& value : getTestPropValues()) {
+ addGetValueRequest(getValueRequests, expectedGetValueResults, requestId++, value,
+ StatusCode::OK);
+ }
+
+ // In our implementation, this would finish immediately.
+ status = getValues(getValueRequests);
+
+ ASSERT_EQ(status, StatusCode::OK);
+
+ std::vector<GetValueResult> getValueResultsWithNoTimestamp;
+ for (auto& result : getGetValueResults()) {
+ ASSERT_GE(result.prop->timestamp, timestamp);
+ GetValueResult resultCopy = result;
+ resultCopy.prop->timestamp = 0;
+ getValueResultsWithNoTimestamp.push_back(std::move(resultCopy));
+ }
+ ASSERT_THAT(getValueResultsWithNoTimestamp, ContainerEq(expectedGetValueResults));
+}
+
+TEST_F(FakeVehicleHardwareTest, testReadValuesErrorInvalidProp) {
+ std::vector<SetValueRequest> setValueRequests;
+ std::vector<SetValueResult> expectedSetValueResults;
+
+ int64_t requestId = 1;
+ for (auto& value : getTestPropValues()) {
+ addSetValueRequest(setValueRequests, expectedSetValueResults, requestId++, value,
+ StatusCode::OK);
+ }
+
+ // In our implementation, this would finish immediately.
+ StatusCode status = setValues(setValueRequests);
+
+ ASSERT_EQ(status, StatusCode::OK);
+
+ std::vector<GetValueRequest> getValueRequests;
+ std::vector<GetValueResult> expectedGetValueResults;
+ VehiclePropValue invalidProp = {
+ .prop = INVALID_PROP_ID,
+ };
+ addGetValueRequest(getValueRequests, expectedGetValueResults, requestId++, invalidProp,
+ StatusCode::INVALID_ARG);
+
+ // In our implementation, this would finish immediately.
+ status = getValues(getValueRequests);
+
+ ASSERT_EQ(status, StatusCode::OK);
+ ASSERT_THAT(getGetValueResults(), ContainerEq(expectedGetValueResults));
+}
+
+TEST_F(FakeVehicleHardwareTest, testReadValuesErrorNotAvailable) {
+ std::vector<GetValueRequest> getValueRequests;
+ std::vector<GetValueResult> expectedGetValueResults;
+ // VEHICLE_MAP_SERVICE does not have initial value, 'get' must always return
+ // StatusCode::NOT_AVAILABLE.
+ addGetValueRequest(getValueRequests, expectedGetValueResults, 0,
+ VehiclePropValue{
+ .prop = VEHICLE_MAP_SERVICE,
+ },
+ StatusCode::NOT_AVAILABLE);
+
+ // In our implementation, this would finish immediately.
+ StatusCode status = getValues(getValueRequests);
+
+ ASSERT_EQ(status, StatusCode::OK);
+ ASSERT_THAT(getGetValueResults(), ContainerEq(expectedGetValueResults));
+}
+
+TEST_F(FakeVehicleHardwareTest, testSetStatusMustIgnore) {
+ VehiclePropValue testValue = getTestPropValues()[0];
+ testValue.status = VehiclePropertyStatus::UNAVAILABLE;
+
+ std::vector<SetValueRequest> setValueRequests;
+ std::vector<SetValueResult> expectedSetValueResults;
+
+ int64_t requestId = 1;
+ addSetValueRequest(setValueRequests, expectedSetValueResults, requestId++, testValue,
+ StatusCode::OK);
+
+ // In our implementation, this would finish immediately.
+ StatusCode status = setValues(setValueRequests);
+
+ ASSERT_EQ(status, StatusCode::OK);
+ ASSERT_THAT(getSetValueResults(), ContainerEq(expectedSetValueResults));
+
+ std::vector<GetValueRequest> getValueRequests;
+ getValueRequests.push_back(GetValueRequest{
+ .requestId = requestId++,
+ .prop = testValue,
+ });
+
+ // In our implementation, this would finish immediately.
+ status = getValues(getValueRequests);
+
+ ASSERT_EQ(status, StatusCode::OK);
+ ASSERT_EQ(getGetValueResults().size(), static_cast<size_t>(1));
+ ASSERT_EQ(getGetValueResults()[0].status, StatusCode::OK);
+ // The status should be by-default AVAILABLE for new status.
+ ASSERT_EQ(getGetValueResults()[0].prop->status, VehiclePropertyStatus::AVAILABLE);
+
+ // Try to set the property again. The status should not be overwritten.
+ status = setValues(setValueRequests);
+
+ ASSERT_EQ(status, StatusCode::OK);
+
+ status = getValues(getValueRequests);
+
+ ASSERT_EQ(status, StatusCode::OK);
+ ASSERT_EQ(getGetValueResults().size(), static_cast<size_t>(2));
+ ASSERT_EQ(getGetValueResults()[1].status, StatusCode::OK);
+ ASSERT_EQ(getGetValueResults()[1].prop->status, VehiclePropertyStatus::AVAILABLE);
+}
+
+} // namespace fake
} // namespace vehicle
} // namespace automotive
} // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/ConcurrentQueue.h b/automotive/vehicle/aidl/impl/utils/common/include/ConcurrentQueue.h
index 68bd559..9a8f19b 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/ConcurrentQueue.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/ConcurrentQueue.h
@@ -44,7 +44,7 @@
std::vector<T> flush() {
std::vector<T> items;
- std::lock_guard<std::mutex> lockGuard(mLock);
+ std::scoped_lock<std::mutex> lockGuard(mLock);
if (mQueue.empty()) {
return items;
}
@@ -59,7 +59,7 @@
void push(T&& item) {
{
- std::lock_guard<std::mutex> lockGuard(mLock);
+ std::scoped_lock<std::mutex> lockGuard(mLock);
if (!mIsActive) {
return;
}
@@ -72,7 +72,7 @@
// The items already in the queue could still be flushed even after the queue is deactivated.
void deactivate() {
{
- std::lock_guard<std::mutex> lockGuard(mLock);
+ std::scoped_lock<std::mutex> lockGuard(mLock);
mIsActive = false;
}
// To unblock all waiting consumers.
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h b/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h
index 545cf6a..9da2b14 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h
@@ -17,6 +17,8 @@
#ifndef android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehicleHalTypes_H_
#define android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehicleHalTypes_H_
+#include <aidl/android/hardware/automotive/vehicle/DiagnosticFloatSensorIndex.h>
+#include <aidl/android/hardware/automotive/vehicle/DiagnosticIntegerSensorIndex.h>
#include <aidl/android/hardware/automotive/vehicle/EvConnectorType.h>
#include <aidl/android/hardware/automotive/vehicle/EvsServiceState.h>
#include <aidl/android/hardware/automotive/vehicle/EvsServiceType.h>
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehicleObjectPool.h b/automotive/vehicle/aidl/impl/utils/common/include/VehicleObjectPool.h
index 61e475a..4b2a11a 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/VehicleObjectPool.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/VehicleObjectPool.h
@@ -80,7 +80,7 @@
virtual ~ObjectPool() = default;
virtual recyclable_ptr<T> obtain() {
- std::lock_guard<std::mutex> lock(mLock);
+ std::scoped_lock<std::mutex> lock(mLock);
INC_METRIC_IF_DEBUG(Obtained)
if (mObjects.empty()) {
INC_METRIC_IF_DEBUG(Created)
@@ -100,7 +100,7 @@
virtual T* createObject() = 0;
virtual void recycle(T* o) {
- std::lock_guard<std::mutex> lock(mLock);
+ std::scoped_lock<std::mutex> lock(mLock);
size_t objectSize = mGetSizeFunc(*o);
if (objectSize > mMaxPoolObjectsSize ||
diff --git a/automotive/vehicle/aidl/impl/utils/common/src/VehicleObjectPool.cpp b/automotive/vehicle/aidl/impl/utils/common/src/VehicleObjectPool.cpp
index 0ff58f7..1cdc461 100644
--- a/automotive/vehicle/aidl/impl/utils/common/src/VehicleObjectPool.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/src/VehicleObjectPool.cpp
@@ -101,7 +101,7 @@
VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainRecyclable(
VehiclePropertyType type, size_t vectorSize) {
- std::lock_guard<std::mutex> lock(mLock);
+ std::scoped_lock<std::mutex> lock(mLock);
assert(vectorSize > 0);
// VehiclePropertyType is not overlapping with vectorSize.
diff --git a/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp b/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp
index 8d12c2b..1a79230 100644
--- a/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp
@@ -53,7 +53,7 @@
}
VehiclePropertyStore::~VehiclePropertyStore() {
- std::lock_guard<std::mutex> lockGuard(mLock);
+ std::scoped_lock<std::mutex> lockGuard(mLock);
// Recycling record requires mValuePool, so need to recycle them before destroying mValuePool.
mRecordsByPropId.clear();
@@ -95,7 +95,7 @@
void VehiclePropertyStore::registerProperty(const VehiclePropConfig& config,
VehiclePropertyStore::TokenFunction tokenFunc) {
- std::lock_guard<std::mutex> g(mLock);
+ std::scoped_lock<std::mutex> g(mLock);
mRecordsByPropId[config.prop] = Record{
.propConfig = config,
@@ -105,7 +105,7 @@
Result<void> VehiclePropertyStore::writeValue(VehiclePropValuePool::RecyclableType propValue,
bool updateStatus) {
- std::lock_guard<std::mutex> g(mLock);
+ std::scoped_lock<std::mutex> g(mLock);
int32_t propId = propValue->prop;
@@ -150,7 +150,7 @@
}
void VehiclePropertyStore::removeValue(const VehiclePropValue& propValue) {
- std::lock_guard<std::mutex> g(mLock);
+ std::scoped_lock<std::mutex> g(mLock);
VehiclePropertyStore::Record* record = getRecordLocked(propValue.prop);
if (record == nullptr) {
@@ -164,7 +164,7 @@
}
void VehiclePropertyStore::removeValuesForProperty(int32_t propId) {
- std::lock_guard<std::mutex> g(mLock);
+ std::scoped_lock<std::mutex> g(mLock);
VehiclePropertyStore::Record* record = getRecordLocked(propId);
if (record == nullptr) {
@@ -175,7 +175,7 @@
}
std::vector<VehiclePropValuePool::RecyclableType> VehiclePropertyStore::readAllValues() const {
- std::lock_guard<std::mutex> g(mLock);
+ std::scoped_lock<std::mutex> g(mLock);
std::vector<VehiclePropValuePool::RecyclableType> allValues;
@@ -190,7 +190,7 @@
Result<std::vector<VehiclePropValuePool::RecyclableType>>
VehiclePropertyStore::readValuesForProperty(int32_t propId) const {
- std::lock_guard<std::mutex> g(mLock);
+ std::scoped_lock<std::mutex> g(mLock);
std::vector<VehiclePropValuePool::RecyclableType> values;
@@ -207,7 +207,7 @@
Result<VehiclePropValuePool::RecyclableType> VehiclePropertyStore::readValue(
const VehiclePropValue& propValue) const {
- std::lock_guard<std::mutex> g(mLock);
+ std::scoped_lock<std::mutex> g(mLock);
int32_t propId = propValue.prop;
const VehiclePropertyStore::Record* record = getRecordLocked(propId);
@@ -222,7 +222,7 @@
Result<VehiclePropValuePool::RecyclableType> VehiclePropertyStore::readValue(int32_t propId,
int32_t areaId,
int64_t token) const {
- std::lock_guard<std::mutex> g(mLock);
+ std::scoped_lock<std::mutex> g(mLock);
const VehiclePropertyStore::Record* record = getRecordLocked(propId);
if (record == nullptr) {
@@ -234,7 +234,7 @@
}
std::vector<VehiclePropConfig> VehiclePropertyStore::getAllConfigs() const {
- std::lock_guard<std::mutex> g(mLock);
+ std::scoped_lock<std::mutex> g(mLock);
std::vector<VehiclePropConfig> configs;
configs.reserve(mRecordsByPropId.size());
@@ -245,7 +245,7 @@
}
Result<const VehiclePropConfig*> VehiclePropertyStore::getConfig(int32_t propId) const {
- std::lock_guard<std::mutex> g(mLock);
+ std::scoped_lock<std::mutex> g(mLock);
const VehiclePropertyStore::Record* record = getRecordLocked(propId);
if (record == nullptr) {
@@ -257,7 +257,7 @@
void VehiclePropertyStore::setOnValueChangeCallback(
const VehiclePropertyStore::OnValueChangeCallback& callback) {
- std::lock_guard<std::mutex> g(mLock);
+ std::scoped_lock<std::mutex> g(mLock);
mOnValueChangeCallback = callback;
}
diff --git a/neuralnetworks/1.0/utils/Android.bp b/neuralnetworks/1.0/utils/Android.bp
index 71a190e..8c51c67 100644
--- a/neuralnetworks/1.0/utils/Android.bp
+++ b/neuralnetworks/1.0/utils/Android.bp
@@ -49,7 +49,7 @@
static_libs: [
"android.hardware.neuralnetworks@1.0",
"libgmock",
- "libneuralnetworks_common_hidl",
+ "libneuralnetworks_common",
"neuralnetworks_types",
"neuralnetworks_utils_hal_common",
"neuralnetworks_utils_hal_1_0",
diff --git a/neuralnetworks/1.0/vts/functional/Android.bp b/neuralnetworks/1.0/vts/functional/Android.bp
index ae9ff0a..b33c581 100644
--- a/neuralnetworks/1.0/vts/functional/Android.bp
+++ b/neuralnetworks/1.0/vts/functional/Android.bp
@@ -50,7 +50,7 @@
"libgmock",
"libhidlmemory",
"libneuralnetworks_generated_test_harness",
- "libneuralnetworks_common_hidl",
+ "libneuralnetworks_utils",
],
header_libs: [
"libneuralnetworks_headers",
@@ -81,7 +81,7 @@
"libgmock",
"libhidlmemory",
"libneuralnetworks_generated_test_harness",
- "libneuralnetworks_common_hidl",
+ "libneuralnetworks_utils",
],
whole_static_libs: [
"neuralnetworks_generated_V1_0_example",
diff --git a/neuralnetworks/1.1/utils/Android.bp b/neuralnetworks/1.1/utils/Android.bp
index 478a742..737ff58 100644
--- a/neuralnetworks/1.1/utils/Android.bp
+++ b/neuralnetworks/1.1/utils/Android.bp
@@ -52,7 +52,7 @@
"android.hardware.neuralnetworks@1.0",
"android.hardware.neuralnetworks@1.1",
"libgmock",
- "libneuralnetworks_common_hidl",
+ "libneuralnetworks_common",
"neuralnetworks_types",
"neuralnetworks_utils_hal_common",
"neuralnetworks_utils_hal_1_0",
diff --git a/neuralnetworks/1.1/vts/functional/Android.bp b/neuralnetworks/1.1/vts/functional/Android.bp
index 4c57788..c001112 100644
--- a/neuralnetworks/1.1/vts/functional/Android.bp
+++ b/neuralnetworks/1.1/vts/functional/Android.bp
@@ -48,7 +48,7 @@
"libgmock",
"libhidlmemory",
"libneuralnetworks_generated_test_harness",
- "libneuralnetworks_common_hidl",
+ "libneuralnetworks_utils",
],
whole_static_libs: [
"neuralnetworks_generated_V1_0_example",
diff --git a/neuralnetworks/1.2/utils/Android.bp b/neuralnetworks/1.2/utils/Android.bp
index 2a86a00..4eefb0f 100644
--- a/neuralnetworks/1.2/utils/Android.bp
+++ b/neuralnetworks/1.2/utils/Android.bp
@@ -71,7 +71,7 @@
"android.hardware.neuralnetworks@1.1",
"android.hardware.neuralnetworks@1.2",
"libgmock",
- "libneuralnetworks_common_hidl",
+ "libneuralnetworks_common",
"neuralnetworks_types",
"neuralnetworks_utils_hal_common",
"neuralnetworks_utils_hal_1_0",
diff --git a/neuralnetworks/1.2/vts/functional/Android.bp b/neuralnetworks/1.2/vts/functional/Android.bp
index 15a5d2f..e313b47 100644
--- a/neuralnetworks/1.2/vts/functional/Android.bp
+++ b/neuralnetworks/1.2/vts/functional/Android.bp
@@ -71,7 +71,7 @@
"libgmock",
"libhidlmemory",
"libneuralnetworks_generated_test_harness",
- "libneuralnetworks_common_hidl",
+ "libneuralnetworks_utils",
],
whole_static_libs: [
"neuralnetworks_generated_V1_0_example",
diff --git a/neuralnetworks/1.3/utils/Android.bp b/neuralnetworks/1.3/utils/Android.bp
index 8ae509f..7acb4fc 100644
--- a/neuralnetworks/1.3/utils/Android.bp
+++ b/neuralnetworks/1.3/utils/Android.bp
@@ -69,7 +69,7 @@
"android.hardware.neuralnetworks@1.2",
"android.hardware.neuralnetworks@1.3",
"libgmock",
- "libneuralnetworks_common_hidl",
+ "libneuralnetworks_common",
"neuralnetworks_types",
"neuralnetworks_utils_hal_common",
"neuralnetworks_utils_hal_1_0",
diff --git a/neuralnetworks/1.3/vts/functional/Android.bp b/neuralnetworks/1.3/vts/functional/Android.bp
index ca59cc2..ab0a018 100644
--- a/neuralnetworks/1.3/vts/functional/Android.bp
+++ b/neuralnetworks/1.3/vts/functional/Android.bp
@@ -66,6 +66,7 @@
"VtsHalNeuralNetworksV1_0_utils",
"VtsHalNeuralNetworksV1_2_utils",
"VtsHalNeuralNetworksV1_3_utils",
+ "android.hardware.neuralnetworks-V2-ndk",
"android.hardware.neuralnetworks@1.0",
"android.hardware.neuralnetworks@1.1",
"android.hardware.neuralnetworks@1.2",
@@ -75,7 +76,7 @@
"libgmock",
"libhidlmemory",
"libneuralnetworks_generated_test_harness",
- "libneuralnetworks_common_hidl",
+ "libneuralnetworks_utils",
"libsync",
],
whole_static_libs: [
diff --git a/neuralnetworks/aidl/utils/Android.bp b/neuralnetworks/aidl/utils/Android.bp
index 2c2419b..63cf45d 100644
--- a/neuralnetworks/aidl/utils/Android.bp
+++ b/neuralnetworks/aidl/utils/Android.bp
@@ -23,8 +23,8 @@
default_applicable_licenses: ["hardware_interfaces_license"],
}
-cc_defaults {
- name: "neuralnetworks_utils_hal_aidl_defaults",
+cc_library_static {
+ name: "neuralnetworks_utils_hal_aidl",
defaults: ["neuralnetworks_utils_defaults"],
srcs: ["src/*"],
local_include_dirs: ["include/nnapi/hal/aidl/"],
@@ -38,6 +38,7 @@
"neuralnetworks_utils_hal_common",
],
shared_libs: [
+ "android.hardware.neuralnetworks-V2-ndk",
"libbinder_ndk",
"libhidlbase",
],
@@ -48,49 +49,21 @@
},
}
-cc_library_static {
- name: "neuralnetworks_utils_hal_aidl_v1",
- defaults: ["neuralnetworks_utils_hal_aidl_defaults"],
- shared_libs: [
- "android.hardware.neuralnetworks-V1-ndk",
- ],
-}
-
-cc_library_static {
- name: "neuralnetworks_utils_hal_aidl_v2",
- defaults: ["neuralnetworks_utils_hal_aidl_defaults"],
- shared_libs: [
- "android.hardware.neuralnetworks-V2-ndk",
- ],
-}
-
-// A cc_defaults that includes the latest non-experimental AIDL utilities and other AIDL libraries
-// that are commonly used together. Modules that always depend on the latest non-experimental
-// AIDL features can include this cc_defaults to avoid managing dependency versions explicitly.
-cc_defaults {
- name: "neuralnetworks_use_latest_utils_hal_aidl",
- static_libs: [
- "android.hardware.common-V2-ndk",
- "android.hardware.graphics.common-V3-ndk",
- "android.hardware.neuralnetworks-V2-ndk",
- "neuralnetworks_utils_hal_aidl_v2",
- ],
-}
-
cc_test {
name: "neuralnetworks_utils_hal_aidl_test",
- defaults: [
- "neuralnetworks_use_latest_utils_hal_aidl",
- "neuralnetworks_utils_defaults",
- ],
+ defaults: ["neuralnetworks_utils_defaults"],
srcs: [
"test/*.cpp",
],
static_libs: [
+ "android.hardware.common-V2-ndk",
+ "android.hardware.graphics.common-V3-ndk",
+ "android.hardware.neuralnetworks-V2-ndk",
"libaidlcommonsupport",
"libgmock",
"libneuralnetworks_common",
"neuralnetworks_types",
+ "neuralnetworks_utils_hal_aidl",
"neuralnetworks_utils_hal_common",
],
shared_libs: [
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Device.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Device.h
index d558f66..1457646 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Device.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Device.h
@@ -43,12 +43,11 @@
public:
static nn::GeneralResult<std::shared_ptr<const Device>> create(
- std::string name, std::shared_ptr<aidl_hal::IDevice> device, nn::Version featureLevel);
+ std::string name, std::shared_ptr<aidl_hal::IDevice> device);
Device(PrivateConstructorTag tag, std::string name, std::string versionString,
- nn::Version featureLevel, nn::DeviceType deviceType,
- std::vector<nn::Extension> extensions, nn::Capabilities capabilities,
- std::pair<uint32_t, uint32_t> numberOfCacheFilesNeeded,
+ nn::DeviceType deviceType, std::vector<nn::Extension> extensions,
+ nn::Capabilities capabilities, std::pair<uint32_t, uint32_t> numberOfCacheFilesNeeded,
std::shared_ptr<aidl_hal::IDevice> device, DeathHandler deathHandler);
const std::string& getName() const override;
@@ -85,7 +84,6 @@
private:
const std::string kName;
const std::string kVersionString;
- const nn::Version kFeatureLevel;
const nn::DeviceType kDeviceType;
const std::vector<nn::Extension> kExtensions;
const nn::Capabilities kCapabilities;
diff --git a/neuralnetworks/aidl/utils/src/Device.cpp b/neuralnetworks/aidl/utils/src/Device.cpp
index 5b7ec4e..e80de0b 100644
--- a/neuralnetworks/aidl/utils/src/Device.cpp
+++ b/neuralnetworks/aidl/utils/src/Device.cpp
@@ -125,7 +125,7 @@
} // namespace
nn::GeneralResult<std::shared_ptr<const Device>> Device::create(
- std::string name, std::shared_ptr<aidl_hal::IDevice> device, nn::Version featureLevel) {
+ std::string name, std::shared_ptr<aidl_hal::IDevice> device) {
if (name.empty()) {
return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
<< "aidl_hal::utils::Device::create must have non-empty name";
@@ -143,19 +143,18 @@
auto deathHandler = NN_TRY(DeathHandler::create(device));
return std::make_shared<const Device>(
- PrivateConstructorTag{}, std::move(name), std::move(versionString), featureLevel,
- deviceType, std::move(extensions), std::move(capabilities), numberOfCacheFilesNeeded,
+ PrivateConstructorTag{}, std::move(name), std::move(versionString), deviceType,
+ std::move(extensions), std::move(capabilities), numberOfCacheFilesNeeded,
std::move(device), std::move(deathHandler));
}
Device::Device(PrivateConstructorTag /*tag*/, std::string name, std::string versionString,
- nn::Version featureLevel, nn::DeviceType deviceType,
- std::vector<nn::Extension> extensions, nn::Capabilities capabilities,
+ nn::DeviceType deviceType, std::vector<nn::Extension> extensions,
+ nn::Capabilities capabilities,
std::pair<uint32_t, uint32_t> numberOfCacheFilesNeeded,
std::shared_ptr<aidl_hal::IDevice> device, DeathHandler deathHandler)
: kName(std::move(name)),
kVersionString(std::move(versionString)),
- kFeatureLevel(featureLevel),
kDeviceType(deviceType),
kExtensions(std::move(extensions)),
kCapabilities(std::move(capabilities)),
@@ -172,7 +171,7 @@
}
nn::Version Device::getFeatureLevel() const {
- return kFeatureLevel;
+ return nn::Version::ANDROID_S;
}
nn::DeviceType Device::getType() const {
diff --git a/neuralnetworks/aidl/utils/src/Service.cpp b/neuralnetworks/aidl/utils/src/Service.cpp
index 01772ee..ac182a2 100644
--- a/neuralnetworks/aidl/utils/src/Service.cpp
+++ b/neuralnetworks/aidl/utils/src/Service.cpp
@@ -17,7 +17,6 @@
#include "Service.h"
#include <AndroidVersionUtil.h>
-#include <aidl/android/hardware/neuralnetworks/IDevice.h>
#include <android/binder_auto_utils.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
@@ -29,33 +28,8 @@
#include <string>
#include "Device.h"
-#include "Utils.h"
namespace aidl::android::hardware::neuralnetworks::utils {
-namespace {
-
-// Map the AIDL version of an IDevice to NNAPI canonical feature level.
-nn::GeneralResult<nn::Version> getAidlServiceFeatureLevel(IDevice* service) {
- CHECK(service != nullptr);
- int aidlVersion;
- const auto ret = service->getInterfaceVersion(&aidlVersion);
- HANDLE_ASTATUS(ret) << "getInterfaceVersion failed";
-
- // For service AIDL versions greater than or equal to the AIDL library version that the runtime
- // was built against, clamp it to the runtime AIDL library version.
- aidlVersion = std::min(aidlVersion, IDevice::version);
-
- // Map stable AIDL versions to canonical versions.
- switch (aidlVersion) {
- case 1:
- return nn::Version::ANDROID_S;
- case 2:
- return nn::Version::FEATURE_LEVEL_6;
- }
- return NN_ERROR() << "Unknown AIDL service version: " << aidlVersion;
-}
-
-} // namespace
nn::GeneralResult<nn::SharedDevice> getDevice(const std::string& instanceName) {
auto fullName = std::string(IDevice::descriptor) + "/" + instanceName;
@@ -81,8 +55,7 @@
<< " returned nullptr";
}
ABinderProcess_startThreadPool();
- const auto featureLevel = NN_TRY(getAidlServiceFeatureLevel(service.get()));
- return Device::create(instanceName, std::move(service), featureLevel);
+ return Device::create(instanceName, std::move(service));
};
return hal::utils::ResilientDevice::create(std::move(makeDevice));
diff --git a/neuralnetworks/aidl/utils/test/DeviceTest.cpp b/neuralnetworks/aidl/utils/test/DeviceTest.cpp
index 79abe1b..f121aca 100644
--- a/neuralnetworks/aidl/utils/test/DeviceTest.cpp
+++ b/neuralnetworks/aidl/utils/test/DeviceTest.cpp
@@ -146,45 +146,28 @@
return ndk::ScopedAStatus::fromStatus(STATUS_DEAD_OBJECT);
};
-class DeviceTest : public ::testing::TestWithParam<nn::Version> {
- protected:
- const nn::Version kVersion = GetParam();
-};
-
-std::string printDeviceTest(const testing::TestParamInfo<nn::Version>& info) {
- switch (info.param) {
- case nn::Version::ANDROID_S:
- return "v1";
- case nn::Version::FEATURE_LEVEL_6:
- return "v2";
- default:
- LOG(FATAL) << "Invalid AIDL version: " << info.param;
- return "invalid";
- }
-}
-
} // namespace
-TEST_P(DeviceTest, invalidName) {
+TEST(DeviceTest, invalidName) {
// run test
const auto device = MockDevice::create();
- const auto result = Device::create(kInvalidName, device, kVersion);
+ const auto result = Device::create(kInvalidName, device);
// verify result
ASSERT_FALSE(result.has_value());
EXPECT_EQ(result.error().code, nn::ErrorStatus::INVALID_ARGUMENT);
}
-TEST_P(DeviceTest, invalidDevice) {
+TEST(DeviceTest, invalidDevice) {
// run test
- const auto result = Device::create(kName, kInvalidDevice, kVersion);
+ const auto result = Device::create(kName, kInvalidDevice);
// verify result
ASSERT_FALSE(result.has_value());
EXPECT_EQ(result.error().code, nn::ErrorStatus::INVALID_ARGUMENT);
}
-TEST_P(DeviceTest, getVersionStringError) {
+TEST(DeviceTest, getVersionStringError) {
// setup call
const auto mockDevice = createMockDevice();
EXPECT_CALL(*mockDevice, getVersionString(_))
@@ -192,14 +175,14 @@
.WillOnce(InvokeWithoutArgs(makeGeneralFailure));
// run test
- const auto result = Device::create(kName, mockDevice, kVersion);
+ const auto result = Device::create(kName, mockDevice);
// verify result
ASSERT_FALSE(result.has_value());
EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST_P(DeviceTest, getVersionStringTransportFailure) {
+TEST(DeviceTest, getVersionStringTransportFailure) {
// setup call
const auto mockDevice = createMockDevice();
EXPECT_CALL(*mockDevice, getVersionString(_))
@@ -207,14 +190,14 @@
.WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
// run test
- const auto result = Device::create(kName, mockDevice, kVersion);
+ const auto result = Device::create(kName, mockDevice);
// verify result
ASSERT_FALSE(result.has_value());
EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST_P(DeviceTest, getVersionStringDeadObject) {
+TEST(DeviceTest, getVersionStringDeadObject) {
// setup call
const auto mockDevice = createMockDevice();
EXPECT_CALL(*mockDevice, getVersionString(_))
@@ -222,27 +205,27 @@
.WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
// run test
- const auto result = Device::create(kName, mockDevice, kVersion);
+ const auto result = Device::create(kName, mockDevice);
// verify result
ASSERT_FALSE(result.has_value());
EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
}
-TEST_P(DeviceTest, getTypeError) {
+TEST(DeviceTest, getTypeError) {
// setup call
const auto mockDevice = createMockDevice();
EXPECT_CALL(*mockDevice, getType(_)).Times(1).WillOnce(InvokeWithoutArgs(makeGeneralFailure));
// run test
- const auto result = Device::create(kName, mockDevice, kVersion);
+ const auto result = Device::create(kName, mockDevice);
// verify result
ASSERT_FALSE(result.has_value());
EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST_P(DeviceTest, getTypeTransportFailure) {
+TEST(DeviceTest, getTypeTransportFailure) {
// setup call
const auto mockDevice = createMockDevice();
EXPECT_CALL(*mockDevice, getType(_))
@@ -250,14 +233,14 @@
.WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
// run test
- const auto result = Device::create(kName, mockDevice, kVersion);
+ const auto result = Device::create(kName, mockDevice);
// verify result
ASSERT_FALSE(result.has_value());
EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST_P(DeviceTest, getTypeDeadObject) {
+TEST(DeviceTest, getTypeDeadObject) {
// setup call
const auto mockDevice = createMockDevice();
EXPECT_CALL(*mockDevice, getType(_))
@@ -265,14 +248,14 @@
.WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
// run test
- const auto result = Device::create(kName, mockDevice, kVersion);
+ const auto result = Device::create(kName, mockDevice);
// verify result
ASSERT_FALSE(result.has_value());
EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
}
-TEST_P(DeviceTest, getSupportedExtensionsError) {
+TEST(DeviceTest, getSupportedExtensionsError) {
// setup call
const auto mockDevice = createMockDevice();
EXPECT_CALL(*mockDevice, getSupportedExtensions(_))
@@ -280,14 +263,14 @@
.WillOnce(InvokeWithoutArgs(makeGeneralFailure));
// run test
- const auto result = Device::create(kName, mockDevice, kVersion);
+ const auto result = Device::create(kName, mockDevice);
// verify result
ASSERT_FALSE(result.has_value());
EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST_P(DeviceTest, getSupportedExtensionsTransportFailure) {
+TEST(DeviceTest, getSupportedExtensionsTransportFailure) {
// setup call
const auto mockDevice = createMockDevice();
EXPECT_CALL(*mockDevice, getSupportedExtensions(_))
@@ -295,14 +278,14 @@
.WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
// run test
- const auto result = Device::create(kName, mockDevice, kVersion);
+ const auto result = Device::create(kName, mockDevice);
// verify result
ASSERT_FALSE(result.has_value());
EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST_P(DeviceTest, getSupportedExtensionsDeadObject) {
+TEST(DeviceTest, getSupportedExtensionsDeadObject) {
// setup call
const auto mockDevice = createMockDevice();
EXPECT_CALL(*mockDevice, getSupportedExtensions(_))
@@ -310,20 +293,20 @@
.WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
// run test
- const auto result = Device::create(kName, mockDevice, kVersion);
+ const auto result = Device::create(kName, mockDevice);
// verify result
ASSERT_FALSE(result.has_value());
EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
}
-TEST_P(DeviceTest, getNumberOfCacheFilesNeeded) {
+TEST(DeviceTest, getNumberOfCacheFilesNeeded) {
// setup call
const auto mockDevice = createMockDevice();
EXPECT_CALL(*mockDevice, getNumberOfCacheFilesNeeded(_)).Times(1);
// run test
- const auto result = Device::create(kName, mockDevice, kVersion);
+ const auto result = Device::create(kName, mockDevice);
// verify result
ASSERT_TRUE(result.has_value());
@@ -332,7 +315,7 @@
EXPECT_EQ(result.value()->getNumberOfCacheFilesNeeded(), kNumberOfCacheFilesPair);
}
-TEST_P(DeviceTest, getNumberOfCacheFilesNeededError) {
+TEST(DeviceTest, getNumberOfCacheFilesNeededError) {
// setup call
const auto mockDevice = createMockDevice();
EXPECT_CALL(*mockDevice, getNumberOfCacheFilesNeeded(_))
@@ -340,14 +323,14 @@
.WillOnce(InvokeWithoutArgs(makeGeneralFailure));
// run test
- const auto result = Device::create(kName, mockDevice, kVersion);
+ const auto result = Device::create(kName, mockDevice);
// verify result
ASSERT_FALSE(result.has_value());
EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST_P(DeviceTest, dataCacheFilesExceedsSpecifiedMax) {
+TEST(DeviceTest, dataCacheFilesExceedsSpecifiedMax) {
// setup test
const auto mockDevice = createMockDevice();
EXPECT_CALL(*mockDevice, getNumberOfCacheFilesNeeded(_))
@@ -358,14 +341,14 @@
InvokeWithoutArgs(makeStatusOk)));
// run test
- const auto result = Device::create(kName, mockDevice, kVersion);
+ const auto result = Device::create(kName, mockDevice);
// verify result
ASSERT_FALSE(result.has_value());
EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST_P(DeviceTest, modelCacheFilesExceedsSpecifiedMax) {
+TEST(DeviceTest, modelCacheFilesExceedsSpecifiedMax) {
// setup test
const auto mockDevice = createMockDevice();
EXPECT_CALL(*mockDevice, getNumberOfCacheFilesNeeded(_))
@@ -376,14 +359,14 @@
InvokeWithoutArgs(makeStatusOk)));
// run test
- const auto result = Device::create(kName, mockDevice, kVersion);
+ const auto result = Device::create(kName, mockDevice);
// verify result
ASSERT_FALSE(result.has_value());
EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST_P(DeviceTest, getNumberOfCacheFilesNeededTransportFailure) {
+TEST(DeviceTest, getNumberOfCacheFilesNeededTransportFailure) {
// setup call
const auto mockDevice = createMockDevice();
EXPECT_CALL(*mockDevice, getNumberOfCacheFilesNeeded(_))
@@ -391,14 +374,14 @@
.WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
// run test
- const auto result = Device::create(kName, mockDevice, kVersion);
+ const auto result = Device::create(kName, mockDevice);
// verify result
ASSERT_FALSE(result.has_value());
EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST_P(DeviceTest, getNumberOfCacheFilesNeededDeadObject) {
+TEST(DeviceTest, getNumberOfCacheFilesNeededDeadObject) {
// setup call
const auto mockDevice = createMockDevice();
EXPECT_CALL(*mockDevice, getNumberOfCacheFilesNeeded(_))
@@ -406,14 +389,14 @@
.WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
// run test
- const auto result = Device::create(kName, mockDevice, kVersion);
+ const auto result = Device::create(kName, mockDevice);
// verify result
ASSERT_FALSE(result.has_value());
EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
}
-TEST_P(DeviceTest, getCapabilitiesError) {
+TEST(DeviceTest, getCapabilitiesError) {
// setup call
const auto mockDevice = createMockDevice();
EXPECT_CALL(*mockDevice, getCapabilities(_))
@@ -421,14 +404,14 @@
.WillOnce(InvokeWithoutArgs(makeGeneralFailure));
// run test
- const auto result = Device::create(kName, mockDevice, kVersion);
+ const auto result = Device::create(kName, mockDevice);
// verify result
ASSERT_FALSE(result.has_value());
EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST_P(DeviceTest, getCapabilitiesTransportFailure) {
+TEST(DeviceTest, getCapabilitiesTransportFailure) {
// setup call
const auto mockDevice = createMockDevice();
EXPECT_CALL(*mockDevice, getCapabilities(_))
@@ -436,14 +419,14 @@
.WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
// run test
- const auto result = Device::create(kName, mockDevice, kVersion);
+ const auto result = Device::create(kName, mockDevice);
// verify result
ASSERT_FALSE(result.has_value());
EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST_P(DeviceTest, getCapabilitiesDeadObject) {
+TEST(DeviceTest, getCapabilitiesDeadObject) {
// setup call
const auto mockDevice = createMockDevice();
EXPECT_CALL(*mockDevice, getCapabilities(_))
@@ -451,17 +434,17 @@
.WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
// run test
- const auto result = Device::create(kName, mockDevice, kVersion);
+ const auto result = Device::create(kName, mockDevice);
// verify result
ASSERT_FALSE(result.has_value());
EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
}
-TEST_P(DeviceTest, getName) {
+TEST(DeviceTest, getName) {
// setup call
const auto mockDevice = createMockDevice();
- const auto device = Device::create(kName, mockDevice, kVersion).value();
+ const auto device = Device::create(kName, mockDevice).value();
// run test
const auto& name = device->getName();
@@ -470,19 +453,19 @@
EXPECT_EQ(name, kName);
}
-TEST_P(DeviceTest, getFeatureLevel) {
+TEST(DeviceTest, getFeatureLevel) {
// setup call
const auto mockDevice = createMockDevice();
- const auto device = Device::create(kName, mockDevice, kVersion).value();
+ const auto device = Device::create(kName, mockDevice).value();
// run test
const auto featureLevel = device->getFeatureLevel();
// verify result
- EXPECT_EQ(featureLevel, kVersion);
+ EXPECT_EQ(featureLevel, nn::Version::ANDROID_S);
}
-TEST_P(DeviceTest, getCachedData) {
+TEST(DeviceTest, getCachedData) {
// setup call
const auto mockDevice = createMockDevice();
EXPECT_CALL(*mockDevice, getVersionString(_)).Times(1);
@@ -491,7 +474,7 @@
EXPECT_CALL(*mockDevice, getNumberOfCacheFilesNeeded(_)).Times(1);
EXPECT_CALL(*mockDevice, getCapabilities(_)).Times(1);
- const auto result = Device::create(kName, mockDevice, kVersion);
+ const auto result = Device::create(kName, mockDevice);
ASSERT_TRUE(result.has_value())
<< "Failed with " << result.error().code << ": " << result.error().message;
const auto& device = result.value();
@@ -504,10 +487,10 @@
EXPECT_EQ(device->getCapabilities(), device->getCapabilities());
}
-TEST_P(DeviceTest, getSupportedOperations) {
+TEST(DeviceTest, getSupportedOperations) {
// setup call
const auto mockDevice = createMockDevice();
- const auto device = Device::create(kName, mockDevice, kVersion).value();
+ const auto device = Device::create(kName, mockDevice).value();
EXPECT_CALL(*mockDevice, getSupportedOperations(_, _))
.Times(1)
.WillOnce(DoAll(
@@ -525,10 +508,10 @@
EXPECT_THAT(supportedOperations, Each(testing::IsTrue()));
}
-TEST_P(DeviceTest, getSupportedOperationsError) {
+TEST(DeviceTest, getSupportedOperationsError) {
// setup call
const auto mockDevice = createMockDevice();
- const auto device = Device::create(kName, mockDevice, kVersion).value();
+ const auto device = Device::create(kName, mockDevice).value();
EXPECT_CALL(*mockDevice, getSupportedOperations(_, _))
.Times(1)
.WillOnce(InvokeWithoutArgs(makeGeneralFailure));
@@ -541,10 +524,10 @@
EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST_P(DeviceTest, getSupportedOperationsTransportFailure) {
+TEST(DeviceTest, getSupportedOperationsTransportFailure) {
// setup call
const auto mockDevice = createMockDevice();
- const auto device = Device::create(kName, mockDevice, kVersion).value();
+ const auto device = Device::create(kName, mockDevice).value();
EXPECT_CALL(*mockDevice, getSupportedOperations(_, _))
.Times(1)
.WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
@@ -557,10 +540,10 @@
EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST_P(DeviceTest, getSupportedOperationsDeadObject) {
+TEST(DeviceTest, getSupportedOperationsDeadObject) {
// setup call
const auto mockDevice = createMockDevice();
- const auto device = Device::create(kName, mockDevice, kVersion).value();
+ const auto device = Device::create(kName, mockDevice).value();
EXPECT_CALL(*mockDevice, getSupportedOperations(_, _))
.Times(1)
.WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
@@ -573,10 +556,10 @@
EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
}
-TEST_P(DeviceTest, prepareModel) {
+TEST(DeviceTest, prepareModel) {
// setup call
const auto mockDevice = createMockDevice();
- const auto device = Device::create(kName, mockDevice, kVersion).value();
+ const auto device = Device::create(kName, mockDevice).value();
const auto mockPreparedModel = MockPreparedModel::create();
EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _, _))
.Times(1)
@@ -593,10 +576,10 @@
EXPECT_NE(result.value(), nullptr);
}
-TEST_P(DeviceTest, prepareModelLaunchError) {
+TEST(DeviceTest, prepareModelLaunchError) {
// setup call
const auto mockDevice = createMockDevice();
- const auto device = Device::create(kName, mockDevice, kVersion).value();
+ const auto device = Device::create(kName, mockDevice).value();
EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _, _))
.Times(1)
.WillOnce(Invoke(makePreparedModelReturn(ErrorStatus::GENERAL_FAILURE,
@@ -611,10 +594,10 @@
EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST_P(DeviceTest, prepareModelReturnError) {
+TEST(DeviceTest, prepareModelReturnError) {
// setup call
const auto mockDevice = createMockDevice();
- const auto device = Device::create(kName, mockDevice, kVersion).value();
+ const auto device = Device::create(kName, mockDevice).value();
EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _, _))
.Times(1)
.WillOnce(Invoke(makePreparedModelReturn(ErrorStatus::NONE,
@@ -629,10 +612,10 @@
EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST_P(DeviceTest, prepareModelNullptrError) {
+TEST(DeviceTest, prepareModelNullptrError) {
// setup call
const auto mockDevice = createMockDevice();
- const auto device = Device::create(kName, mockDevice, kVersion).value();
+ const auto device = Device::create(kName, mockDevice).value();
EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _, _))
.Times(1)
.WillOnce(
@@ -647,10 +630,10 @@
EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST_P(DeviceTest, prepareModelTransportFailure) {
+TEST(DeviceTest, prepareModelTransportFailure) {
// setup call
const auto mockDevice = createMockDevice();
- const auto device = Device::create(kName, mockDevice, kVersion).value();
+ const auto device = Device::create(kName, mockDevice).value();
EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _, _))
.Times(1)
.WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
@@ -664,10 +647,10 @@
EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST_P(DeviceTest, prepareModelDeadObject) {
+TEST(DeviceTest, prepareModelDeadObject) {
// setup call
const auto mockDevice = createMockDevice();
- const auto device = Device::create(kName, mockDevice, kVersion).value();
+ const auto device = Device::create(kName, mockDevice).value();
EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _, _))
.Times(1)
.WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
@@ -681,10 +664,10 @@
EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
}
-TEST_P(DeviceTest, prepareModelAsyncCrash) {
+TEST(DeviceTest, prepareModelAsyncCrash) {
// setup test
const auto mockDevice = createMockDevice();
- const auto device = Device::create(kName, mockDevice, kVersion).value();
+ const auto device = Device::create(kName, mockDevice).value();
const auto ret = [&device]() {
DeathMonitor::serviceDied(device->getDeathMonitor());
return ndk::ScopedAStatus::ok();
@@ -702,10 +685,10 @@
EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
}
-TEST_P(DeviceTest, prepareModelFromCache) {
+TEST(DeviceTest, prepareModelFromCache) {
// setup call
const auto mockDevice = createMockDevice();
- const auto device = Device::create(kName, mockDevice, kVersion).value();
+ const auto device = Device::create(kName, mockDevice).value();
const auto mockPreparedModel = MockPreparedModel::create();
EXPECT_CALL(*mockDevice, prepareModelFromCache(_, _, _, _, _))
.Times(1)
@@ -721,10 +704,10 @@
EXPECT_NE(result.value(), nullptr);
}
-TEST_P(DeviceTest, prepareModelFromCacheLaunchError) {
+TEST(DeviceTest, prepareModelFromCacheLaunchError) {
// setup call
const auto mockDevice = createMockDevice();
- const auto device = Device::create(kName, mockDevice, kVersion).value();
+ const auto device = Device::create(kName, mockDevice).value();
EXPECT_CALL(*mockDevice, prepareModelFromCache(_, _, _, _, _))
.Times(1)
.WillOnce(Invoke(makePreparedModelFromCacheReturn(
@@ -738,10 +721,10 @@
EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST_P(DeviceTest, prepareModelFromCacheReturnError) {
+TEST(DeviceTest, prepareModelFromCacheReturnError) {
// setup call
const auto mockDevice = createMockDevice();
- const auto device = Device::create(kName, mockDevice, kVersion).value();
+ const auto device = Device::create(kName, mockDevice).value();
EXPECT_CALL(*mockDevice, prepareModelFromCache(_, _, _, _, _))
.Times(1)
.WillOnce(Invoke(makePreparedModelFromCacheReturn(
@@ -755,10 +738,10 @@
EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST_P(DeviceTest, prepareModelFromCacheNullptrError) {
+TEST(DeviceTest, prepareModelFromCacheNullptrError) {
// setup call
const auto mockDevice = createMockDevice();
- const auto device = Device::create(kName, mockDevice, kVersion).value();
+ const auto device = Device::create(kName, mockDevice).value();
EXPECT_CALL(*mockDevice, prepareModelFromCache(_, _, _, _, _))
.Times(1)
.WillOnce(Invoke(makePreparedModelFromCacheReturn(ErrorStatus::NONE, ErrorStatus::NONE,
@@ -772,10 +755,10 @@
EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST_P(DeviceTest, prepareModelFromCacheTransportFailure) {
+TEST(DeviceTest, prepareModelFromCacheTransportFailure) {
// setup call
const auto mockDevice = createMockDevice();
- const auto device = Device::create(kName, mockDevice, kVersion).value();
+ const auto device = Device::create(kName, mockDevice).value();
EXPECT_CALL(*mockDevice, prepareModelFromCache(_, _, _, _, _))
.Times(1)
.WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
@@ -788,10 +771,10 @@
EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST_P(DeviceTest, prepareModelFromCacheDeadObject) {
+TEST(DeviceTest, prepareModelFromCacheDeadObject) {
// setup call
const auto mockDevice = createMockDevice();
- const auto device = Device::create(kName, mockDevice, kVersion).value();
+ const auto device = Device::create(kName, mockDevice).value();
EXPECT_CALL(*mockDevice, prepareModelFromCache(_, _, _, _, _))
.Times(1)
.WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
@@ -804,10 +787,10 @@
EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
}
-TEST_P(DeviceTest, prepareModelFromCacheAsyncCrash) {
+TEST(DeviceTest, prepareModelFromCacheAsyncCrash) {
// setup test
const auto mockDevice = createMockDevice();
- const auto device = Device::create(kName, mockDevice, kVersion).value();
+ const auto device = Device::create(kName, mockDevice).value();
const auto ret = [&device]() {
DeathMonitor::serviceDied(device->getDeathMonitor());
return ndk::ScopedAStatus::ok();
@@ -824,10 +807,10 @@
EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
}
-TEST_P(DeviceTest, allocate) {
+TEST(DeviceTest, allocate) {
// setup call
const auto mockDevice = createMockDevice();
- const auto device = Device::create(kName, mockDevice, kVersion).value();
+ const auto device = Device::create(kName, mockDevice).value();
const auto mockBuffer = DeviceBuffer{.buffer = MockBuffer::create(), .token = 1};
EXPECT_CALL(*mockDevice, allocate(_, _, _, _, _))
.Times(1)
@@ -842,10 +825,10 @@
EXPECT_NE(result.value(), nullptr);
}
-TEST_P(DeviceTest, allocateError) {
+TEST(DeviceTest, allocateError) {
// setup call
const auto mockDevice = createMockDevice();
- const auto device = Device::create(kName, mockDevice, kVersion).value();
+ const auto device = Device::create(kName, mockDevice).value();
EXPECT_CALL(*mockDevice, allocate(_, _, _, _, _))
.Times(1)
.WillOnce(InvokeWithoutArgs(makeGeneralFailure));
@@ -858,10 +841,10 @@
EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST_P(DeviceTest, allocateTransportFailure) {
+TEST(DeviceTest, allocateTransportFailure) {
// setup call
const auto mockDevice = createMockDevice();
- const auto device = Device::create(kName, mockDevice, kVersion).value();
+ const auto device = Device::create(kName, mockDevice).value();
EXPECT_CALL(*mockDevice, allocate(_, _, _, _, _))
.Times(1)
.WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
@@ -874,10 +857,10 @@
EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
}
-TEST_P(DeviceTest, allocateDeadObject) {
+TEST(DeviceTest, allocateDeadObject) {
// setup call
const auto mockDevice = createMockDevice();
- const auto device = Device::create(kName, mockDevice, kVersion).value();
+ const auto device = Device::create(kName, mockDevice).value();
EXPECT_CALL(*mockDevice, allocate(_, _, _, _, _))
.Times(1)
.WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
@@ -890,8 +873,4 @@
EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
}
-INSTANTIATE_TEST_SUITE_P(TestDevice, DeviceTest,
- ::testing::Values(nn::Version::ANDROID_S, nn::Version::FEATURE_LEVEL_6),
- printDeviceTest);
-
} // namespace aidl::android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/aidl/vts/functional/Android.bp b/neuralnetworks/aidl/vts/functional/Android.bp
index 8fd8f4f..f3404a9 100644
--- a/neuralnetworks/aidl/vts/functional/Android.bp
+++ b/neuralnetworks/aidl/vts/functional/Android.bp
@@ -26,7 +26,6 @@
cc_test {
name: "VtsHalNeuralnetworksTargetTest",
defaults: [
- "neuralnetworks_use_latest_utils_hal_aidl",
"neuralnetworks_vts_functional_defaults",
"use_libaidlvintf_gtest_helper_static",
],
@@ -52,14 +51,16 @@
static_libs: [
"android.hardware.common-V2-ndk",
"android.hardware.graphics.common-V3-ndk",
+ "android.hardware.neuralnetworks-V2-ndk",
"android.hidl.allocator@1.0",
"android.hidl.memory@1.0",
"libaidlcommonsupport",
"libgmock",
"libhidlmemory",
- "libneuralnetworks_common",
"libneuralnetworks_generated_test_harness",
+ "libneuralnetworks_utils",
"libsync",
+ "neuralnetworks_utils_hal_aidl",
],
whole_static_libs: [
"neuralnetworks_generated_V1_0_example",
diff --git a/neuralnetworks/utils/common/Android.bp b/neuralnetworks/utils/common/Android.bp
index c0645b0..f88e407 100644
--- a/neuralnetworks/utils/common/Android.bp
+++ b/neuralnetworks/utils/common/Android.bp
@@ -35,6 +35,7 @@
"neuralnetworks_types",
],
shared_libs: [
+ "android.hardware.neuralnetworks-V2-ndk",
"libhidlbase",
"libbinder_ndk",
],
@@ -52,7 +53,7 @@
static_libs: [
"android.hardware.neuralnetworks@1.0",
"libgmock",
- "libneuralnetworks_common_hidl",
+ "libneuralnetworks_common",
"neuralnetworks_types",
"neuralnetworks_utils_hal_common",
],
diff --git a/neuralnetworks/utils/service/Android.bp b/neuralnetworks/utils/service/Android.bp
index 3288d05..fbb8679 100644
--- a/neuralnetworks/utils/service/Android.bp
+++ b/neuralnetworks/utils/service/Android.bp
@@ -25,10 +25,7 @@
cc_library_static {
name: "neuralnetworks_utils_hal_service",
- defaults: [
- "neuralnetworks_use_latest_utils_hal_aidl",
- "neuralnetworks_utils_defaults",
- ],
+ defaults: ["neuralnetworks_utils_defaults"],
srcs: ["src/*"],
local_include_dirs: ["include/nnapi/hal"],
export_include_dirs: ["include"],
@@ -38,9 +35,11 @@
"neuralnetworks_utils_hal_1_1",
"neuralnetworks_utils_hal_1_2",
"neuralnetworks_utils_hal_1_3",
+ "neuralnetworks_utils_hal_aidl",
"neuralnetworks_utils_hal_common",
],
shared_libs: [
+ "android.hardware.neuralnetworks-V2-ndk",
"android.hardware.neuralnetworks@1.0",
"android.hardware.neuralnetworks@1.1",
"android.hardware.neuralnetworks@1.2",
diff --git a/security/keymint/support/Android.bp b/security/keymint/support/Android.bp
index bdb4cdf..e162934 100644
--- a/security/keymint/support/Android.bp
+++ b/security/keymint/support/Android.bp
@@ -25,6 +25,7 @@
cc_library {
name: "libkeymint_support",
+ vendor_available: true,
cflags: [
"-Wall",
"-Wextra",
@@ -44,6 +45,7 @@
"libbase",
"libcrypto",
"libutils",
+ "libhardware",
],
}
diff --git a/uwb/aidl/android/hardware/uwb/IUwbChip.aidl b/uwb/aidl/android/hardware/uwb/IUwbChip.aidl
index 5f1a59e..9530af4 100755
--- a/uwb/aidl/android/hardware/uwb/IUwbChip.aidl
+++ b/uwb/aidl/android/hardware/uwb/IUwbChip.aidl
@@ -51,6 +51,10 @@
/**
* Supported version of vendor UCI specification.
+ *
+ * This corresponds to the version of the "android.hardware.uwb.fira_android" types-only
+ * package included in the HAL implementation. This vendor params/commands package will be
+ * updated on a different cadence to the main UWB HAL interface package.
*/
int getSupportedVendorUciVersion();