Merge "Add reference ivn HAL impl." into udc-dev
diff --git a/automotive/ivn_android_device/impl/default/Android.bp b/automotive/ivn_android_device/impl/default/Android.bp
new file mode 100644
index 0000000..98c1f58
--- /dev/null
+++ b/automotive/ivn_android_device/impl/default/Android.bp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2023 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: "IvnAndroidDeviceService",
+ vendor_available: true,
+ local_include_dirs: ["include"],
+ export_include_dirs: ["include"],
+ srcs: [
+ "src/IvnAndroidDeviceService.cpp",
+ ],
+ whole_static_libs: [
+ "android.hardware.automotive.ivn-V1-ndk",
+ ],
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "libjsoncpp",
+ "liblog",
+ "libutils",
+ ],
+}
+
+cc_binary {
+ name: "android.hardware.automotive.ivn@V1-default-service",
+ vendor: true,
+ relative_install_path: "hw",
+ local_include_dirs: ["include"],
+ srcs: ["src/IvnAndroidDeviceImpl.cpp"],
+ whole_static_libs: ["IvnAndroidDeviceService"],
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "libjsoncpp",
+ "liblog",
+ "libutils",
+ ],
+ required: ["Prebuilt_IvnAndroidDeviceServiceDefaultConfig_JSON"],
+ vintf_fragments: ["ivn-default-service.xml"],
+ init_rc: ["ivn-default-service.rc"],
+}
diff --git a/automotive/ivn_android_device/impl/default/config/Android.bp b/automotive/ivn_android_device/impl/default/config/Android.bp
new file mode 100644
index 0000000..03c4d1b
--- /dev/null
+++ b/automotive/ivn_android_device/impl/default/config/Android.bp
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2023 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"],
+}
+
+filegroup {
+ name: "IvnAndroidDeviceServiceDefaultConfig_Json",
+ srcs: ["DefaultConfig.json"],
+}
+
+prebuilt_etc {
+ name: "Prebuilt_IvnAndroidDeviceServiceDefaultConfig_JSON",
+ filename_from_src: true,
+ src: "DefaultConfig.json",
+ sub_dir: "automotive/IvnConfig/",
+ vendor: true,
+}
diff --git a/automotive/ivn_android_device/impl/default/config/DefaultConfig.json b/automotive/ivn_android_device/impl/default/config/DefaultConfig.json
new file mode 100644
index 0000000..45663e2
--- /dev/null
+++ b/automotive/ivn_android_device/impl/default/config/DefaultConfig.json
@@ -0,0 +1,61 @@
+{
+ "MyDeviceId": 0,
+ "Devices": [
+ {
+ "DeviceId": 0,
+ "OccupantZones": [
+ {
+ "ZoneId": 0,
+ "OccupantType": "DRIVER",
+ "Seat": 1,
+ "Comments": "Occupant zone for driver and FRONT_LEFT seat"
+ },
+ {
+ "ZoneId": 1,
+ "OccupantType": "FRONT_PASSENGER",
+ "Seat": 4,
+ "Comments": "Occupant zone for FRONT_RIGHT passenger"
+ }
+ ],
+ "EndpointInfo": {
+ "IpAddress": "10.10.10.1",
+ "PortNumber": 1234,
+ "BrandName": "MyBrand",
+ "DeviceName": "MyDevice",
+ "ProductName": "MyProduct",
+ "ManufacturerName": "MyCompany",
+ "ModelName": "MyModel",
+ "SerialNumber": "Serial1234"
+ },
+ "Comments": "Device for front row"
+ },
+ {
+ "DeviceId": 1,
+ "OccupantZones": [
+ {
+ "ZoneId": 2,
+ "OccupantType": "REAR_PASSENGER",
+ "Seat": 16
+ },
+ {
+ "ZoneId": 3,
+ "OccupantType": "REAR_PASSENGER",
+ "Seat": 64
+ }
+ ],
+ "EndpointInfo": {
+ "IpAddress": "10.10.10.2",
+ "PortNumber": 2345,
+ "BrandName": "MyBrand",
+ "DeviceName": "MyDevice",
+ "ProductName": "MyProduct",
+ "ManufacturerName": "MyCompany",
+ "ModelName": "MyModel",
+ "SerialNumber": "Serial2345"
+ },
+ "Comments": "Device for back row"
+ }
+ ],
+ "Comment":
+ "This simulates a vehicle with two Android devices, one for front row, one for back row"
+}
diff --git a/automotive/ivn_android_device/impl/default/include/IvnAndroidDeviceService.h b/automotive/ivn_android_device/impl/default/include/IvnAndroidDeviceService.h
new file mode 100644
index 0000000..c0cc9fe
--- /dev/null
+++ b/automotive/ivn_android_device/impl/default/include/IvnAndroidDeviceService.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/automotive/ivn/BnIvnAndroidDevice.h>
+#include <aidl/android/hardware/automotive/ivn/EndpointInfo.h>
+#include <aidl/android/hardware/automotive/ivn/OccupantZoneInfo.h>
+#include <android/binder_auto_utils.h>
+#include <vector>
+
+#include <unordered_map>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace ivn {
+
+struct DeviceInfo {
+ std::vector<aidl::android::hardware::automotive::ivn::OccupantZoneInfo> occupantZones;
+ aidl::android::hardware::automotive::ivn::EndpointInfo endpointInfo;
+};
+
+class IvnAndroidDeviceService
+ : public aidl::android::hardware::automotive::ivn::BnIvnAndroidDevice {
+ public:
+ explicit IvnAndroidDeviceService(std::string_view configPath);
+
+ // Initialize the service, returns true on success.
+ bool init();
+
+ ndk::ScopedAStatus getMyDeviceId(int* deviceId) override;
+
+ ndk::ScopedAStatus getOtherDeviceIds(std::vector<int>* deviceIds) override;
+
+ ndk::ScopedAStatus getDeviceIdForOccupantZone(int zoneId, int* deviceId) override;
+
+ ndk::ScopedAStatus getOccupantZonesForDevice(
+ int androidDeviceId,
+ std::vector<aidl::android::hardware::automotive::ivn::OccupantZoneInfo>* occupantZones)
+ override;
+
+ ndk::ScopedAStatus getMyEndpointInfo(
+ aidl::android::hardware::automotive::ivn::EndpointInfo* endpointInfo) override;
+
+ ndk::ScopedAStatus getEndpointInfoForDevice(
+ int androidDeviceId,
+ aidl::android::hardware::automotive::ivn::EndpointInfo* endpointInfo) override;
+
+ private:
+ int mMyDeviceId;
+ std::unordered_map<int, DeviceInfo> mDeviceInfoById;
+ std::string_view mConfigPath;
+};
+
+} // namespace ivn
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/ivn_android_device/impl/default/ivn-default-service.rc b/automotive/ivn_android_device/impl/default/ivn-default-service.rc
new file mode 100644
index 0000000..070b259
--- /dev/null
+++ b/automotive/ivn_android_device/impl/default/ivn-default-service.rc
@@ -0,0 +1,4 @@
+service vendor.ivn-default /vendor/bin/hw/android.hardware.automotive.ivn@V1-default-service
+ class hal
+ user vehicle_network
+ group system inet
diff --git a/automotive/ivn_android_device/impl/default/ivn-default-service.xml b/automotive/ivn_android_device/impl/default/ivn-default-service.xml
new file mode 100644
index 0000000..481bc0a
--- /dev/null
+++ b/automotive/ivn_android_device/impl/default/ivn-default-service.xml
@@ -0,0 +1,7 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.automotive.ivn</name>
+ <version>1</version>
+ <fqname>IIvnAndroidDevice/default</fqname>
+ </hal>
+</manifest>
diff --git a/automotive/ivn_android_device/impl/default/src/IvnAndroidDeviceImpl.cpp b/automotive/ivn_android_device/impl/default/src/IvnAndroidDeviceImpl.cpp
new file mode 100644
index 0000000..fdf6776
--- /dev/null
+++ b/automotive/ivn_android_device/impl/default/src/IvnAndroidDeviceImpl.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2023 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 "IvnAndroidDeviceImpl"
+
+#include "IvnAndroidDeviceService.h"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <stdlib.h>
+
+constexpr char SERVICE_NAME[] = "android.hardware.automotive.ivn.IIvnAndroidDevice/default";
+constexpr char DEFAULT_CONFIG_DIR[] = "/vendor/etc/automotive/IvnConfig/DefaultConfig.json";
+
+int main(int /* argc */, char* /* argv */[]) {
+ LOG(INFO) << "Registering IvnAndroidDeviceService as service...";
+ auto service =
+ ndk::SharedRefBase::make<android::hardware::automotive::ivn::IvnAndroidDeviceService>(
+ DEFAULT_CONFIG_DIR);
+ if (!service->init()) {
+ LOG(ERROR) << "Failed to init IvnAndroidDeviceService";
+ exit(1);
+ }
+
+ binder_exception_t err = AServiceManager_addService(service->asBinder().get(), SERVICE_NAME);
+ if (err != EX_NONE) {
+ LOG(ERROR) << "Failed to register IvnAndroidDeviceService service, exception: " << err;
+ exit(1);
+ }
+
+ if (!ABinderProcess_setThreadPoolMaxThreadCount(1)) {
+ LOG(ERROR) << "Failed to set thread pool max thread count";
+ exit(1);
+ }
+ ABinderProcess_startThreadPool();
+
+ LOG(INFO) << "IvnAndroidDeviceService Ready";
+
+ ABinderProcess_joinThreadPool();
+
+ LOG(ERROR) << "IvnAndroidDeviceService init failed! Should not reach here";
+
+ return 0;
+}
diff --git a/automotive/ivn_android_device/impl/default/src/IvnAndroidDeviceService.cpp b/automotive/ivn_android_device/impl/default/src/IvnAndroidDeviceService.cpp
new file mode 100644
index 0000000..71454d5
--- /dev/null
+++ b/automotive/ivn_android_device/impl/default/src/IvnAndroidDeviceService.cpp
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2023 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 "IvnAndroidDeviceService.h"
+
+#include <aidl/android/hardware/automotive/ivn/ConnectProtocol.h>
+#include <aidl/android/hardware/automotive/ivn/HardwareIdentifiers.h>
+#include <aidl/android/hardware/automotive/ivn/OccupantType.h>
+#include <android-base/logging.h>
+#include <android/binder_status.h>
+#include <json/json.h>
+
+#include <fstream>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace ivn {
+
+namespace {
+
+using ::aidl::android::hardware::automotive::ivn::ConnectProtocol;
+using ::aidl::android::hardware::automotive::ivn::EndpointInfo;
+using ::aidl::android::hardware::automotive::ivn::HardwareIdentifiers;
+using ::aidl::android::hardware::automotive::ivn::OccupantType;
+using ::aidl::android::hardware::automotive::ivn::OccupantZoneInfo;
+using ::ndk::ScopedAStatus;
+
+constexpr int IVN_ERROR_GENERIC = -1;
+
+} // namespace
+
+IvnAndroidDeviceService::IvnAndroidDeviceService(std::string_view configPath) {
+ mConfigPath = configPath;
+}
+
+bool IvnAndroidDeviceService::init() {
+ std::ifstream configStream(mConfigPath);
+ if (!configStream) {
+ LOG(ERROR) << "couldn't open " << mConfigPath << " for parsing.";
+ return false;
+ }
+ Json::CharReaderBuilder builder;
+ Json::Value root;
+ std::string errs;
+ if (!Json::parseFromStream(builder, configStream, &root, &errs)) {
+ LOG(ERROR) << "Failed to parse config JSON stream, error: " << errs;
+ return false;
+ }
+ if (!root.isObject()) {
+ LOG(ERROR) << "Root must be an object";
+ return false;
+ }
+ if (!root.isMember("MyDeviceId")) {
+ LOG(ERROR) << "Must contain 'MyDeviceId' field";
+ return false;
+ }
+ mMyDeviceId = root["MyDeviceId"].asInt();
+ if (!root.isMember("Devices") || !root["Devices"].isArray()) {
+ LOG(ERROR) << "Must contain 'Devices' field as array";
+ return false;
+ }
+ Json::Value& devices = root["Devices"];
+ for (unsigned int i = 0; i < devices.size(); i++) {
+ Json::Value& device = devices[i];
+ int deviceId = device["DeviceId"].asInt();
+ DeviceInfo deviceInfo = {};
+ Json::Value& occupantZones = device["OccupantZones"];
+ for (unsigned int j = 0; j < occupantZones.size(); j++) {
+ Json::Value& occupantZone = occupantZones[j];
+ int zoneId = occupantZone["ZoneId"].asInt();
+ std::string occupantTypeStr = occupantZone["OccupantType"].asString();
+ int seat = occupantZone["Seat"].asInt();
+ OccupantType occupantType;
+ if (occupantTypeStr == "DRIVER") {
+ occupantType = OccupantType::DRIVER;
+ } else if (occupantTypeStr == "FRONT_PASSENGER") {
+ occupantType = OccupantType::FRONT_PASSENGER;
+ } else if (occupantTypeStr == "REAR_PASSENGER") {
+ occupantType = OccupantType::REAR_PASSENGER;
+ } else {
+ LOG(ERROR) << "Unknown occupant type: " << occupantTypeStr;
+ return false;
+ }
+ OccupantZoneInfo occupantZoneInfo = {
+ .zoneId = zoneId, .occupantType = occupantType, .seat = seat};
+ deviceInfo.occupantZones.push_back(std::move(occupantZoneInfo));
+ }
+ Json::Value& ep = device["EndpointInfo"];
+ EndpointInfo endpointInfo = {};
+ endpointInfo.connectProtocol = ConnectProtocol::TCP_IP;
+ endpointInfo.ipAddress = ep["IpAddress"].asString();
+ endpointInfo.portNumber = ep["PortNumber"].asInt();
+ HardwareIdentifiers hardwareId = {};
+ if (ep.isMember("BrandName")) {
+ hardwareId.brandName = ep["BrandName"].asString();
+ }
+ if (ep.isMember("DeviceName")) {
+ hardwareId.deviceName = ep["DeviceName"].asString();
+ }
+ if (ep.isMember("ProductName")) {
+ hardwareId.productName = ep["ProductName"].asString();
+ }
+ if (ep.isMember("ManufacturerName")) {
+ hardwareId.manufacturerName = ep["ManufacturerName"].asString();
+ }
+ if (ep.isMember("ModelName")) {
+ hardwareId.modelName = ep["ModelName"].asString();
+ }
+ if (ep.isMember("SerialNumber")) {
+ hardwareId.serialNumber = ep["SerialNumber"].asString();
+ }
+ endpointInfo.hardwareId = hardwareId;
+ deviceInfo.endpointInfo = endpointInfo;
+ mDeviceInfoById[deviceId] = deviceInfo;
+ }
+ if (mDeviceInfoById.find(mMyDeviceId) == mDeviceInfoById.end()) {
+ LOG(ERROR) << "My device ID is not in the device info list";
+ return false;
+ }
+ return true;
+}
+
+ScopedAStatus IvnAndroidDeviceService::getMyDeviceId(int* deviceId) {
+ *deviceId = mMyDeviceId;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus IvnAndroidDeviceService::getOtherDeviceIds(std::vector<int>* deviceIds) {
+ deviceIds->clear();
+ for (const auto& [deviceId, _] : mDeviceInfoById) {
+ if (deviceId == mMyDeviceId) {
+ continue;
+ }
+ deviceIds->push_back(deviceId);
+ }
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus IvnAndroidDeviceService::getDeviceIdForOccupantZone(int zoneId, int* outDeviceId) {
+ for (const auto& [deviceId, deviceInfo] : mDeviceInfoById) {
+ for (const auto& occupantZoneInfo : deviceInfo.occupantZones) {
+ if (occupantZoneInfo.zoneId == zoneId) {
+ *outDeviceId = deviceId;
+ return ScopedAStatus::ok();
+ }
+ }
+ }
+ return ScopedAStatus::fromServiceSpecificErrorWithMessage(IVN_ERROR_GENERIC,
+ "Occupant zone not found");
+}
+
+ScopedAStatus IvnAndroidDeviceService::getOccupantZonesForDevice(
+ int androidDeviceId, std::vector<OccupantZoneInfo>* occupantZones) {
+ if (mDeviceInfoById.find(androidDeviceId) == mDeviceInfoById.end()) {
+ return ScopedAStatus::fromServiceSpecificErrorWithMessage(IVN_ERROR_GENERIC,
+ "Android device ID not found");
+ }
+ for (const auto& occupantZoneInfo : mDeviceInfoById[androidDeviceId].occupantZones) {
+ occupantZones->push_back(occupantZoneInfo);
+ }
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus IvnAndroidDeviceService::getMyEndpointInfo(EndpointInfo* endpointInfo) {
+ *endpointInfo = mDeviceInfoById[mMyDeviceId].endpointInfo;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus IvnAndroidDeviceService::getEndpointInfoForDevice(int androidDeviceId,
+ EndpointInfo* endpointInfo) {
+ if (mDeviceInfoById.find(androidDeviceId) == mDeviceInfoById.end()) {
+ return ScopedAStatus::fromServiceSpecificErrorWithMessage(IVN_ERROR_GENERIC,
+ "Android device ID not found");
+ }
+ *endpointInfo = mDeviceInfoById[androidDeviceId].endpointInfo;
+ return ScopedAStatus::ok();
+}
+
+} // namespace ivn
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/ivn_android_device/impl/default/test/Android.bp b/automotive/ivn_android_device/impl/default/test/Android.bp
new file mode 100644
index 0000000..a100575
--- /dev/null
+++ b/automotive/ivn_android_device/impl/default/test/Android.bp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2023 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: "IvnAndroidDeviceServiceUnitTest",
+ vendor: true,
+ srcs: ["*.cpp"],
+ whole_static_libs: [
+ "IvnAndroidDeviceService",
+ ],
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "libjsoncpp",
+ "liblog",
+ "libutils",
+ ],
+ static_libs: [
+ "libgtest",
+ ],
+ data: [
+ ":IvnAndroidDeviceServiceDefaultConfig_Json",
+ ],
+ test_suites: ["device-tests"],
+}
diff --git a/automotive/ivn_android_device/impl/default/test/IvnAndroidDeviceServiceUnittest.cpp b/automotive/ivn_android_device/impl/default/test/IvnAndroidDeviceServiceUnittest.cpp
new file mode 100644
index 0000000..bc8e69f
--- /dev/null
+++ b/automotive/ivn_android_device/impl/default/test/IvnAndroidDeviceServiceUnittest.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2023 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 "IvnAndroidDeviceService.h"
+
+#include <aidl/android/hardware/automotive/ivn/OccupantType.h>
+#include <aidl/android/hardware/automotive/ivn/OccupantZoneInfo.h>
+#include <android-base/file.h>
+#include <gtest/gtest.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace ivn {
+
+using ::aidl::android::hardware::automotive::ivn::OccupantType;
+using ::aidl::android::hardware::automotive::ivn::OccupantZoneInfo;
+using ::ndk::ScopedAStatus;
+
+class IvnAndroidDeviceServiceUnitTest : public ::testing::Test {
+ public:
+ virtual void SetUp() override {
+ mService = ndk::SharedRefBase::make<IvnAndroidDeviceService>(
+ android::base::GetExecutableDirectory() + "/DefaultConfig.json");
+ mService->init();
+ }
+
+ std::shared_ptr<IvnAndroidDeviceService> mService;
+};
+
+TEST_F(IvnAndroidDeviceServiceUnitTest, TestGetMyDeviceId) {
+ int deviceId = -1;
+
+ ScopedAStatus status = mService->getMyDeviceId(&deviceId);
+
+ ASSERT_TRUE(status.isOk());
+ ASSERT_EQ(deviceId, 0);
+}
+
+TEST_F(IvnAndroidDeviceServiceUnitTest, TestGetOtherDeviceIds) {
+ std::vector<int> deviceIds;
+
+ ScopedAStatus status = mService->getOtherDeviceIds(&deviceIds);
+
+ ASSERT_TRUE(status.isOk());
+ ASSERT_EQ(deviceIds, std::vector<int>({1}));
+}
+
+TEST_F(IvnAndroidDeviceServiceUnitTest, TestGetDeviceIdForOccupantZone) {
+ int deviceId = -1;
+
+ ScopedAStatus status = mService->getDeviceIdForOccupantZone(/*zoneId=*/0, &deviceId);
+
+ ASSERT_TRUE(status.isOk());
+ EXPECT_EQ(deviceId, 0);
+
+ status = mService->getDeviceIdForOccupantZone(/*zoneId=*/1, &deviceId);
+
+ ASSERT_TRUE(status.isOk());
+ EXPECT_EQ(deviceId, 0);
+
+ status = mService->getDeviceIdForOccupantZone(/*zoneId=*/2, &deviceId);
+
+ ASSERT_TRUE(status.isOk());
+ EXPECT_EQ(deviceId, 1);
+
+ status = mService->getDeviceIdForOccupantZone(/*zoneId=*/3, &deviceId);
+
+ ASSERT_TRUE(status.isOk());
+ EXPECT_EQ(deviceId, 1);
+
+ status = mService->getDeviceIdForOccupantZone(/*zoneId=*/4, &deviceId);
+
+ ASSERT_FALSE(status.isOk());
+}
+
+TEST_F(IvnAndroidDeviceServiceUnitTest, TestGetOccupantZonesForDevice) {
+ std::vector<OccupantZoneInfo> occupantZones;
+
+ ScopedAStatus status =
+ mService->getOccupantZonesForDevice(/*androidDeviceId=*/0, &occupantZones);
+ ASSERT_TRUE(status.isOk());
+ EXPECT_EQ(occupantZones.size(), 2);
+ if (occupantZones.size() == 2) {
+ EXPECT_EQ(occupantZones[0].zoneId, 0);
+ EXPECT_EQ(occupantZones[0].occupantType, OccupantType::DRIVER);
+ EXPECT_EQ(occupantZones[0].seat, 1);
+ EXPECT_EQ(occupantZones[1].zoneId, 1);
+ EXPECT_EQ(occupantZones[1].occupantType, OccupantType::FRONT_PASSENGER);
+ EXPECT_EQ(occupantZones[1].seat, 4);
+ }
+}
+
+} // namespace ivn
+} // namespace automotive
+} // namespace hardware
+} // namespace android