blob: ca8cfae150265612ca0697ad568920868adb8199 [file] [log] [blame]
Changyeon Joc6fa0ab2019-10-12 05:25:44 -07001/*
2 * Copyright (C) 2019 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
Changyeon Joc6fa0ab2019-10-12 05:25:44 -070017#include "ConfigManager.h"
18
Changyeon Jo33ba66b2022-01-16 16:33:52 -080019#include <android/hardware/camera/device/3.2/ICameraDevice.h>
20#include <hardware/gralloc.h>
21#include <utils/SystemClock.h>
Changyeon Joc6fa0ab2019-10-12 05:25:44 -070022
Changyeon Jo33ba66b2022-01-16 16:33:52 -080023#include <fstream>
24#include <sstream>
25#include <thread>
26
27namespace android::hardware::automotive::evs::V1_1::implementation {
28
29using namespace std;
30using namespace tinyxml2;
31using hardware::camera::device::V3_2::StreamRotation;
Changyeon Joc6fa0ab2019-10-12 05:25:44 -070032
33ConfigManager::~ConfigManager() {
34 /* Nothing to do */
35}
36
Changyeon Jo33ba66b2022-01-16 16:33:52 -080037void ConfigManager::readCameraInfo(const XMLElement* const aCameraElem) {
Changyeon Joc6fa0ab2019-10-12 05:25:44 -070038 if (aCameraElem == nullptr) {
39 ALOGW("XML file does not have required camera element");
40 return;
41 }
42
Changyeon Jo33ba66b2022-01-16 16:33:52 -080043 const XMLElement* curElem = aCameraElem->FirstChildElement();
Changyeon Joc6fa0ab2019-10-12 05:25:44 -070044 while (curElem != nullptr) {
45 if (!strcmp(curElem->Name(), "group")) {
46 /* camera group identifier */
Changyeon Jo33ba66b2022-01-16 16:33:52 -080047 const char* id = curElem->FindAttribute("id")->Value();
Changyeon Joc6fa0ab2019-10-12 05:25:44 -070048
Changyeon Jo56c9b372019-10-09 14:04:31 -070049 /* create a camera group to be filled */
Changyeon Jo33ba66b2022-01-16 16:33:52 -080050 CameraGroupInfo* aCamera = new CameraGroupInfo();
Changyeon Joc6fa0ab2019-10-12 05:25:44 -070051
Changyeon Jo56c9b372019-10-09 14:04:31 -070052 /* read camera device information */
53 if (!readCameraDeviceInfo(aCamera, curElem)) {
54 ALOGW("Failed to read a camera information of %s", id);
55 delete aCamera;
56 continue;
Changyeon Joc6fa0ab2019-10-12 05:25:44 -070057 }
58
59 /* camera group synchronization */
Changyeon Jo33ba66b2022-01-16 16:33:52 -080060 const char* sync = curElem->FindAttribute("synchronized")->Value();
Changyeon Jo56c9b372019-10-09 14:04:31 -070061 if (!strcmp(sync, "CALIBRATED")) {
Changyeon Jo33ba66b2022-01-16 16:33:52 -080062 aCamera->synchronized = ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE_CALIBRATED;
Changyeon Jo56c9b372019-10-09 14:04:31 -070063 } else if (!strcmp(sync, "APPROXIMATE")) {
Changyeon Jo33ba66b2022-01-16 16:33:52 -080064 aCamera->synchronized = ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE_APPROXIMATE;
Changyeon Jo56c9b372019-10-09 14:04:31 -070065 } else {
Changyeon Jo33ba66b2022-01-16 16:33:52 -080066 aCamera->synchronized = 0; // Not synchronized
Changyeon Jo56c9b372019-10-09 14:04:31 -070067 }
Changyeon Joc6fa0ab2019-10-12 05:25:44 -070068
69 /* add a group to hash map */
Changyeon Jo56c9b372019-10-09 14:04:31 -070070 mCameraGroupInfos.insert_or_assign(id, unique_ptr<CameraGroupInfo>(aCamera));
Changyeon Joc6fa0ab2019-10-12 05:25:44 -070071 } else if (!strcmp(curElem->Name(), "device")) {
72 /* camera unique identifier */
Changyeon Jo33ba66b2022-01-16 16:33:52 -080073 const char* id = curElem->FindAttribute("id")->Value();
Changyeon Joc6fa0ab2019-10-12 05:25:44 -070074
75 /* camera mount location */
Changyeon Jo33ba66b2022-01-16 16:33:52 -080076 const char* pos = curElem->FindAttribute("position")->Value();
Changyeon Joc6fa0ab2019-10-12 05:25:44 -070077
Changyeon Jo56c9b372019-10-09 14:04:31 -070078 /* create a camera device to be filled */
Changyeon Jo33ba66b2022-01-16 16:33:52 -080079 CameraInfo* aCamera = new CameraInfo();
Changyeon Jo56c9b372019-10-09 14:04:31 -070080
81 /* read camera device information */
82 if (!readCameraDeviceInfo(aCamera, curElem)) {
83 ALOGW("Failed to read a camera information of %s", id);
84 delete aCamera;
85 continue;
86 }
87
Changyeon Joc6fa0ab2019-10-12 05:25:44 -070088 /* store read camera module information */
Changyeon Jo56c9b372019-10-09 14:04:31 -070089 mCameraInfo.insert_or_assign(id, unique_ptr<CameraInfo>(aCamera));
Changyeon Joc6fa0ab2019-10-12 05:25:44 -070090
91 /* assign a camera device to a position group */
92 mCameraPosition[pos].emplace(id);
93 } else {
94 /* ignore other device types */
95 ALOGD("Unknown element %s is ignored", curElem->Name());
96 }
97
98 curElem = curElem->NextSiblingElement();
99 }
100}
101
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800102bool ConfigManager::readCameraDeviceInfo(CameraInfo* aCamera, const XMLElement* aDeviceElem) {
Changyeon Jo56c9b372019-10-09 14:04:31 -0700103 if (aCamera == nullptr || aDeviceElem == nullptr) {
104 return false;
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700105 }
106
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700107 /* size information to allocate camera_metadata_t */
108 size_t totalEntries = 0;
109 size_t totalDataSize = 0;
110
111 /* read device capabilities */
112 totalEntries +=
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800113 readCameraCapabilities(aDeviceElem->FirstChildElement("caps"), aCamera, totalDataSize);
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700114
115 /* read camera metadata */
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800116 totalEntries += readCameraMetadata(aDeviceElem->FirstChildElement("characteristics"), aCamera,
117 totalDataSize);
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700118
119 /* construct camera_metadata_t */
120 if (!constructCameraMetadata(aCamera, totalEntries, totalDataSize)) {
121 ALOGW("Either failed to allocate memory or "
122 "allocated memory was not large enough");
123 }
124
Changyeon Jo56c9b372019-10-09 14:04:31 -0700125 return true;
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700126}
127
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800128size_t ConfigManager::readCameraCapabilities(const XMLElement* const aCapElem, CameraInfo* aCamera,
129 size_t& dataSize) {
Changyeon Jo56c9b372019-10-09 14:04:31 -0700130 if (aCapElem == nullptr || aCamera == nullptr) {
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700131 return 0;
132 }
133
134 string token;
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800135 const XMLElement* curElem = nullptr;
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700136
137 /* a list of supported camera parameters/controls */
138 curElem = aCapElem->FirstChildElement("supported_controls");
139 if (curElem != nullptr) {
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800140 const XMLElement* ctrlElem = curElem->FirstChildElement("control");
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700141 while (ctrlElem != nullptr) {
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800142 const char* nameAttr = ctrlElem->FindAttribute("name")->Value();
143 ;
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700144 const int32_t minVal = stoi(ctrlElem->FindAttribute("min")->Value());
145 const int32_t maxVal = stoi(ctrlElem->FindAttribute("max")->Value());
146
147 int32_t stepVal = 1;
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800148 const XMLAttribute* stepAttr = ctrlElem->FindAttribute("step");
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700149 if (stepAttr != nullptr) {
150 stepVal = stoi(stepAttr->Value());
151 }
152
153 CameraParam aParam;
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800154 if (ConfigManagerUtil::convertToEvsCameraParam(nameAttr, aParam)) {
155 aCamera->controls.emplace(aParam, make_tuple(minVal, maxVal, stepVal));
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700156 }
157
158 ctrlElem = ctrlElem->NextSiblingElement("control");
159 }
160 }
161
162 /* a list of camera stream configurations */
163 curElem = aCapElem->FirstChildElement("stream");
164 while (curElem != nullptr) {
165 /* read 5 attributes */
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800166 const XMLAttribute* idAttr = curElem->FindAttribute("id");
167 const XMLAttribute* widthAttr = curElem->FindAttribute("width");
168 const XMLAttribute* heightAttr = curElem->FindAttribute("height");
169 const XMLAttribute* fmtAttr = curElem->FindAttribute("format");
170 const XMLAttribute* fpsAttr = curElem->FindAttribute("framerate");
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700171
172 const int32_t id = stoi(idAttr->Value());
173 int32_t framerate = 0;
174 if (fpsAttr != nullptr) {
175 framerate = stoi(fpsAttr->Value());
176 }
177
178 int32_t pixFormat;
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800179 if (ConfigManagerUtil::convertToPixelFormat(fmtAttr->Value(), pixFormat)) {
180 RawStreamConfiguration cfg = {id,
181 stoi(widthAttr->Value()),
182 stoi(heightAttr->Value()),
183 pixFormat,
184 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
185 framerate};
Changyeon Jo56c9b372019-10-09 14:04:31 -0700186 aCamera->streamConfigurations.insert_or_assign(id, cfg);
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700187 }
188
189 curElem = curElem->NextSiblingElement("stream");
190 }
191
192 dataSize = calculate_camera_metadata_entry_data_size(
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800193 get_camera_metadata_tag_type(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS),
194 aCamera->streamConfigurations.size() * kStreamCfgSz);
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700195
196 /* a single camera metadata entry contains multiple stream configurations */
197 return dataSize > 0 ? 1 : 0;
198}
199
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800200size_t ConfigManager::readCameraMetadata(const XMLElement* const aParamElem, CameraInfo* aCamera,
201 size_t& dataSize) {
Changyeon Jo56c9b372019-10-09 14:04:31 -0700202 if (aParamElem == nullptr || aCamera == nullptr) {
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700203 return 0;
204 }
205
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800206 const XMLElement* curElem = aParamElem->FirstChildElement("parameter");
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700207 size_t numEntries = 0;
208 camera_metadata_tag_t tag;
209 while (curElem != nullptr) {
210 if (!ConfigManagerUtil::convertToMetadataTag(curElem->FindAttribute("name")->Value(),
211 tag)) {
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800212 switch (tag) {
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700213 case ANDROID_LENS_DISTORTION:
214 case ANDROID_LENS_POSE_ROTATION:
215 case ANDROID_LENS_POSE_TRANSLATION:
216 case ANDROID_LENS_INTRINSIC_CALIBRATION: {
217 /* float[] */
218 size_t count = 0;
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800219 void* data = ConfigManagerUtil::convertFloatArray(
220 curElem->FindAttribute("size")->Value(),
221 curElem->FindAttribute("value")->Value(), count);
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700222
Changyeon Jo56c9b372019-10-09 14:04:31 -0700223 aCamera->cameraMetadata.insert_or_assign(
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800224 tag, make_pair(make_unique<void*>(data), count));
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700225
226 ++numEntries;
227 dataSize += calculate_camera_metadata_entry_data_size(
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800228 get_camera_metadata_tag_type(tag), count);
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700229
230 break;
231 }
232
Changyeon Jo56c9b372019-10-09 14:04:31 -0700233 case ANDROID_REQUEST_AVAILABLE_CAPABILITIES: {
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800234 camera_metadata_enum_android_request_available_capabilities_t* data =
235 new camera_metadata_enum_android_request_available_capabilities_t[1];
Changyeon Jo56c9b372019-10-09 14:04:31 -0700236 if (ConfigManagerUtil::convertToCameraCapability(
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800237 curElem->FindAttribute("value")->Value(), *data)) {
238 curElem->FindAttribute("value")->Value(),
239 aCamera->cameraMetadata.insert_or_assign(
240 tag, make_pair(make_unique<void*>(data), 1));
Changyeon Jo56c9b372019-10-09 14:04:31 -0700241
242 ++numEntries;
243 dataSize += calculate_camera_metadata_entry_data_size(
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800244 get_camera_metadata_tag_type(tag), 1);
Changyeon Jo56c9b372019-10-09 14:04:31 -0700245 }
246 break;
247 }
248
249 case ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS: {
250 /* a comma-separated list of physical camera devices */
251 size_t len = strlen(curElem->FindAttribute("value")->Value());
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800252 char* data = new char[len + 1];
253 memcpy(data, curElem->FindAttribute("value")->Value(), len * sizeof(char));
Changyeon Jo56c9b372019-10-09 14:04:31 -0700254
255 /* replace commas with null char */
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800256 char* p = data;
Changyeon Jo56c9b372019-10-09 14:04:31 -0700257 while (*p != '\0') {
258 if (*p == ',') {
259 *p = '\0';
260 }
261 ++p;
262 }
263
264 aCamera->cameraMetadata.insert_or_assign(
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800265 tag, make_pair(make_unique<void*>(data), len));
Changyeon Jo56c9b372019-10-09 14:04:31 -0700266
267 ++numEntries;
268 dataSize += calculate_camera_metadata_entry_data_size(
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800269 get_camera_metadata_tag_type(tag), len);
Changyeon Jo56c9b372019-10-09 14:04:31 -0700270 break;
271 }
272
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700273 default:
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800274 ALOGW("Parameter %s is not supported", curElem->FindAttribute("name")->Value());
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700275 break;
276 }
277 }
278
279 curElem = curElem->NextSiblingElement("parameter");
280 }
281
282 return numEntries;
283}
284
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800285bool ConfigManager::constructCameraMetadata(CameraInfo* aCamera, const size_t totalEntries,
286 const size_t totalDataSize) {
Changyeon Jo56c9b372019-10-09 14:04:31 -0700287 if (aCamera == nullptr || !aCamera->allocate(totalEntries, totalDataSize)) {
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700288 ALOGE("Failed to allocate memory for camera metadata");
289 return false;
290 }
291
292 const size_t numStreamConfigs = aCamera->streamConfigurations.size();
293 unique_ptr<int32_t[]> data(new int32_t[kStreamCfgSz * numStreamConfigs]);
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800294 int32_t* ptr = data.get();
295 for (auto& cfg : aCamera->streamConfigurations) {
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700296 for (auto i = 0; i < kStreamCfgSz; ++i) {
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800297 *ptr++ = cfg.second[i];
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700298 }
299 }
300 int32_t err = add_camera_metadata_entry(aCamera->characteristics,
301 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800302 data.get(), numStreamConfigs * kStreamCfgSz);
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700303
304 if (err) {
305 ALOGE("Failed to add stream configurations to metadata, ignored");
306 return false;
307 }
308
309 bool success = true;
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800310 for (auto& [tag, entry] : aCamera->cameraMetadata) {
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700311 /* try to add new camera metadata entry */
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800312 int32_t err = add_camera_metadata_entry(aCamera->characteristics, tag, entry.first.get(),
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700313 entry.second);
314 if (err) {
315 ALOGE("Failed to add an entry with a tag 0x%X", tag);
316
317 /* may exceed preallocated capacity */
318 ALOGE("Camera metadata has %ld / %ld entries and %ld / %ld bytes are filled",
Changyeon Jo63cddfc2019-10-12 05:27:34 -0700319 (long)get_camera_metadata_entry_count(aCamera->characteristics),
320 (long)get_camera_metadata_entry_capacity(aCamera->characteristics),
321 (long)get_camera_metadata_data_count(aCamera->characteristics),
322 (long)get_camera_metadata_data_capacity(aCamera->characteristics));
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700323 ALOGE("\tCurrent metadata entry requires %ld bytes",
Changyeon Jo63cddfc2019-10-12 05:27:34 -0700324 (long)calculate_camera_metadata_entry_data_size(tag, entry.second));
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700325
326 success = false;
327 }
328 }
329
330 ALOGV("Camera metadata has %ld / %ld entries and %ld / %ld bytes are filled",
Changyeon Jo63cddfc2019-10-12 05:27:34 -0700331 (long)get_camera_metadata_entry_count(aCamera->characteristics),
332 (long)get_camera_metadata_entry_capacity(aCamera->characteristics),
333 (long)get_camera_metadata_data_count(aCamera->characteristics),
334 (long)get_camera_metadata_data_capacity(aCamera->characteristics));
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700335
336 return success;
337}
338
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800339void ConfigManager::readSystemInfo(const XMLElement* const aSysElem) {
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700340 if (aSysElem == nullptr) {
341 return;
342 }
343
344 /*
345 * Please note that this function assumes that a given system XML element
346 * and its child elements follow DTD. If it does not, it will cause a
347 * segmentation fault due to the failure of finding expected attributes.
348 */
349
350 /* read number of cameras available in the system */
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800351 const XMLElement* xmlElem = aSysElem->FirstChildElement("num_cameras");
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700352 if (xmlElem != nullptr) {
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800353 mSystemInfo.numCameras = stoi(xmlElem->FindAttribute("value")->Value());
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700354 }
355}
356
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800357void ConfigManager::readDisplayInfo(const XMLElement* const aDisplayElem) {
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700358 if (aDisplayElem == nullptr) {
359 ALOGW("XML file does not have required camera element");
360 return;
361 }
362
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800363 const XMLElement* curDev = aDisplayElem->FirstChildElement("device");
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700364 while (curDev != nullptr) {
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800365 const char* id = curDev->FindAttribute("id")->Value();
366 // const char *pos = curDev->FirstAttribute("position")->Value();
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700367
368 unique_ptr<DisplayInfo> dpy(new DisplayInfo());
369 if (dpy == nullptr) {
370 ALOGE("Failed to allocate memory for DisplayInfo");
371 return;
372 }
373
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800374 const XMLElement* cap = curDev->FirstChildElement("caps");
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700375 if (cap != nullptr) {
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800376 const XMLElement* curStream = cap->FirstChildElement("stream");
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700377 while (curStream != nullptr) {
378 /* read 4 attributes */
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800379 const XMLAttribute* idAttr = curStream->FindAttribute("id");
380 const XMLAttribute* widthAttr = curStream->FindAttribute("width");
381 const XMLAttribute* heightAttr = curStream->FindAttribute("height");
382 const XMLAttribute* fmtAttr = curStream->FindAttribute("format");
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700383
384 const int32_t id = stoi(idAttr->Value());
385 int32_t pixFormat;
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800386 if (ConfigManagerUtil::convertToPixelFormat(fmtAttr->Value(), pixFormat)) {
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700387 RawStreamConfiguration cfg = {
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800388 id,
389 stoi(widthAttr->Value()),
390 stoi(heightAttr->Value()),
391 pixFormat,
392 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT,
393 0 // unused
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700394 };
Changyeon Jo56c9b372019-10-09 14:04:31 -0700395 dpy->streamConfigurations.insert_or_assign(id, cfg);
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700396 }
397
398 curStream = curStream->NextSiblingElement("stream");
399 }
400 }
401
Changyeon Jo56c9b372019-10-09 14:04:31 -0700402 mDisplayInfo.insert_or_assign(id, std::move(dpy));
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700403 curDev = curDev->NextSiblingElement("device");
404 }
405
406 return;
407}
408
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700409bool ConfigManager::readConfigDataFromXML() noexcept {
410 XMLDocument xmlDoc;
411
412 const int64_t parsingStart = android::elapsedRealtimeNano();
413
414 /* load and parse a configuration file */
415 xmlDoc.LoadFile(mConfigFilePath);
416 if (xmlDoc.ErrorID() != XML_SUCCESS) {
417 ALOGE("Failed to load and/or parse a configuration file, %s", xmlDoc.ErrorStr());
418 return false;
419 }
420
421 /* retrieve the root element */
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800422 const XMLElement* rootElem = xmlDoc.RootElement();
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700423 if (strcmp(rootElem->Name(), "configuration")) {
424 ALOGE("A configuration file is not in the required format. "
425 "See /etc/automotive/evs/evs_configuration.dtd");
426 return false;
427 }
428
429 /*
430 * parse camera information; this needs to be done before reading system
431 * information
432 */
433 readCameraInfo(rootElem->FirstChildElement("camera"));
434
435 /* parse system information */
436 readSystemInfo(rootElem->FirstChildElement("system"));
437
438 /* parse display information */
439 readDisplayInfo(rootElem->FirstChildElement("display"));
440
441 const int64_t parsingEnd = android::elapsedRealtimeNano();
442 ALOGI("Parsing configuration file takes %lf (ms)",
443 (double)(parsingEnd - parsingStart) / 1000000.0);
444
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700445 return true;
446}
447
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800448std::unique_ptr<ConfigManager> ConfigManager::Create(const char* path) {
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700449 unique_ptr<ConfigManager> cfgMgr(new ConfigManager(path));
450
451 /*
452 * Read a configuration from XML file
453 *
454 * If this is too slow, ConfigManager::readConfigDataFromBinary() and
455 * ConfigManager::writeConfigDataToBinary()can serialize CameraInfo object
456 * to the filesystem and construct CameraInfo instead; this was
457 * evaluated as 10x faster.
458 */
459 if (!cfgMgr->readConfigDataFromXML()) {
460 return nullptr;
461 } else {
462 return cfgMgr;
463 }
464}
465
Changyeon Jo33ba66b2022-01-16 16:33:52 -0800466} // namespace android::hardware::automotive::evs::V1_1::implementation