1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "IvnAndroidDeviceService.h"
18 
19 #include <aidl/android/hardware/automotive/ivn/ConnectProtocol.h>
20 #include <aidl/android/hardware/automotive/ivn/HardwareIdentifiers.h>
21 #include <aidl/android/hardware/automotive/ivn/OccupantType.h>
22 #include <android-base/logging.h>
23 #include <android/binder_status.h>
24 #include <json/json.h>
25 
26 #include <fstream>
27 
28 namespace android {
29 namespace hardware {
30 namespace automotive {
31 namespace ivn {
32 
33 namespace {
34 
35 using ::aidl::android::hardware::automotive::ivn::ConnectProtocol;
36 using ::aidl::android::hardware::automotive::ivn::EndpointInfo;
37 using ::aidl::android::hardware::automotive::ivn::HardwareIdentifiers;
38 using ::aidl::android::hardware::automotive::ivn::OccupantType;
39 using ::aidl::android::hardware::automotive::ivn::OccupantZoneInfo;
40 using ::ndk::ScopedAStatus;
41 
42 constexpr int IVN_ERROR_GENERIC = -1;
43 
44 }  // namespace
45 
IvnAndroidDeviceService(std::string_view configPath)46 IvnAndroidDeviceService::IvnAndroidDeviceService(std::string_view configPath) {
47     mConfigPath = configPath;
48 }
49 
init()50 bool IvnAndroidDeviceService::init() {
51     std::ifstream configStream(mConfigPath);
52     if (!configStream) {
53         LOG(ERROR) << "couldn't open " << mConfigPath << " for parsing.";
54         return false;
55     }
56     Json::CharReaderBuilder builder;
57     std::string errs;
58     if (!Json::parseFromStream(builder, configStream, &mConfigRootNode, &errs)) {
59         LOG(ERROR) << "Failed to parse config JSON stream, error: " << errs;
60         return false;
61     }
62     if (!mConfigRootNode.isObject()) {
63         LOG(ERROR) << "Root must be an object";
64         return false;
65     }
66     if (!mConfigRootNode.isMember("MyDeviceId")) {
67         LOG(ERROR) << "Must contain 'MyDeviceId' field";
68         return false;
69     }
70     mMyDeviceId = mConfigRootNode["MyDeviceId"].asInt();
71     if (!mConfigRootNode.isMember("Devices") || !mConfigRootNode["Devices"].isArray()) {
72         LOG(ERROR) << "Must contain 'Devices' field as array";
73         return false;
74     }
75     Json::Value& devices = mConfigRootNode["Devices"];
76     for (unsigned int i = 0; i < devices.size(); i++) {
77         Json::Value& device = devices[i];
78         int deviceId = device["DeviceId"].asInt();
79         DeviceInfo deviceInfo = {};
80         Json::Value& occupantZones = device["OccupantZones"];
81         for (unsigned int j = 0; j < occupantZones.size(); j++) {
82             Json::Value& occupantZone = occupantZones[j];
83             int zoneId = occupantZone["ZoneId"].asInt();
84             std::string occupantTypeStr = occupantZone["OccupantType"].asString();
85             int seat = occupantZone["Seat"].asInt();
86             OccupantType occupantType;
87             if (occupantTypeStr == "DRIVER") {
88                 occupantType = OccupantType::DRIVER;
89             } else if (occupantTypeStr == "FRONT_PASSENGER") {
90                 occupantType = OccupantType::FRONT_PASSENGER;
91             } else if (occupantTypeStr == "REAR_PASSENGER") {
92                 occupantType = OccupantType::REAR_PASSENGER;
93             } else {
94                 LOG(ERROR) << "Unknown occupant type: " << occupantTypeStr;
95                 return false;
96             }
97             OccupantZoneInfo occupantZoneInfo = {
98                     .zoneId = zoneId, .occupantType = occupantType, .seat = seat};
99             deviceInfo.occupantZones.push_back(std::move(occupantZoneInfo));
100         }
101         Json::Value& ep = device["EndpointInfo"];
102         EndpointInfo endpointInfo = {};
103         endpointInfo.connectProtocol = ConnectProtocol::TCP_IP;
104         endpointInfo.ipAddress = ep["IpAddress"].asString();
105         endpointInfo.portNumber = ep["PortNumber"].asInt();
106         HardwareIdentifiers hardwareId = {};
107         if (ep.isMember("BrandName")) {
108             hardwareId.brandName = ep["BrandName"].asString();
109         }
110         if (ep.isMember("DeviceName")) {
111             hardwareId.deviceName = ep["DeviceName"].asString();
112         }
113         if (ep.isMember("ProductName")) {
114             hardwareId.productName = ep["ProductName"].asString();
115         }
116         if (ep.isMember("ManufacturerName")) {
117             hardwareId.manufacturerName = ep["ManufacturerName"].asString();
118         }
119         if (ep.isMember("ModelName")) {
120             hardwareId.modelName = ep["ModelName"].asString();
121         }
122         if (ep.isMember("SerialNumber")) {
123             hardwareId.serialNumber = ep["SerialNumber"].asString();
124         }
125         endpointInfo.hardwareId = hardwareId;
126         deviceInfo.endpointInfo = endpointInfo;
127         mDeviceInfoById[deviceId] = deviceInfo;
128     }
129     if (mDeviceInfoById.find(mMyDeviceId) == mDeviceInfoById.end()) {
130         LOG(ERROR) << "My device ID is not in the device info list";
131         return false;
132     }
133     return true;
134 }
135 
getMyDeviceId(int * deviceId)136 ScopedAStatus IvnAndroidDeviceService::getMyDeviceId(int* deviceId) {
137     *deviceId = mMyDeviceId;
138     return ScopedAStatus::ok();
139 }
140 
getOtherDeviceIds(std::vector<int> * deviceIds)141 ScopedAStatus IvnAndroidDeviceService::getOtherDeviceIds(std::vector<int>* deviceIds) {
142     deviceIds->clear();
143     for (const auto& [deviceId, _] : mDeviceInfoById) {
144         if (deviceId == mMyDeviceId) {
145             continue;
146         }
147         deviceIds->push_back(deviceId);
148     }
149     return ScopedAStatus::ok();
150 }
151 
getDeviceIdForOccupantZone(int zoneId,int * outDeviceId)152 ScopedAStatus IvnAndroidDeviceService::getDeviceIdForOccupantZone(int zoneId, int* outDeviceId) {
153     for (const auto& [deviceId, deviceInfo] : mDeviceInfoById) {
154         for (const auto& occupantZoneInfo : deviceInfo.occupantZones) {
155             if (occupantZoneInfo.zoneId == zoneId) {
156                 *outDeviceId = deviceId;
157                 return ScopedAStatus::ok();
158             }
159         }
160     }
161     return ScopedAStatus::fromServiceSpecificErrorWithMessage(IVN_ERROR_GENERIC,
162                                                               "Occupant zone not found");
163 }
164 
getOccupantZonesForDevice(int androidDeviceId,std::vector<OccupantZoneInfo> * occupantZones)165 ScopedAStatus IvnAndroidDeviceService::getOccupantZonesForDevice(
166         int androidDeviceId, std::vector<OccupantZoneInfo>* occupantZones) {
167     if (mDeviceInfoById.find(androidDeviceId) == mDeviceInfoById.end()) {
168         return ScopedAStatus::fromServiceSpecificErrorWithMessage(IVN_ERROR_GENERIC,
169                                                                   "Android device ID not found");
170     }
171     for (const auto& occupantZoneInfo : mDeviceInfoById[androidDeviceId].occupantZones) {
172         occupantZones->push_back(occupantZoneInfo);
173     }
174     return ScopedAStatus::ok();
175 }
176 
getMyEndpointInfo(EndpointInfo * endpointInfo)177 ScopedAStatus IvnAndroidDeviceService::getMyEndpointInfo(EndpointInfo* endpointInfo) {
178     *endpointInfo = mDeviceInfoById[mMyDeviceId].endpointInfo;
179     return ScopedAStatus::ok();
180 }
181 
getEndpointInfoForDevice(int androidDeviceId,EndpointInfo * endpointInfo)182 ScopedAStatus IvnAndroidDeviceService::getEndpointInfoForDevice(int androidDeviceId,
183                                                                 EndpointInfo* endpointInfo) {
184     if (mDeviceInfoById.find(androidDeviceId) == mDeviceInfoById.end()) {
185         return ScopedAStatus::fromServiceSpecificErrorWithMessage(IVN_ERROR_GENERIC,
186                                                                   "Android device ID not found");
187     }
188     *endpointInfo = mDeviceInfoById[androidDeviceId].endpointInfo;
189     return ScopedAStatus::ok();
190 }
191 
dump(int fd,const char ** args,uint32_t numArgs)192 binder_status_t IvnAndroidDeviceService::dump(int fd, [[maybe_unused]] const char** args,
193                                               [[maybe_unused]] uint32_t numArgs) {
194     dprintf(fd, "IVN Android Device debug interface, Config: \n%s\n",
195             mConfigRootNode.toStyledString().c_str());
196     return STATUS_OK;
197 }
198 
199 }  // namespace ivn
200 }  // namespace automotive
201 }  // namespace hardware
202 }  // namespace android
203