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 "ConfigManager.h"
18
19 #include <android-base/parseint.h>
20 #include <hardware/gralloc.h>
21 #include <utils/SystemClock.h>
22
23 #include <fstream>
24 #include <sstream>
25 #include <string_view>
26 #include <thread>
27
28 namespace {
29
30 using ::aidl::android::hardware::automotive::evs::CameraParam;
31 using ::aidl::android::hardware::graphics::common::PixelFormat;
32 using ::tinyxml2::XMLAttribute;
33 using ::tinyxml2::XMLDocument;
34 using ::tinyxml2::XMLElement;
35
36 } // namespace
37
38 std::string_view ConfigManager::sConfigDefaultPath =
39 "/vendor/etc/automotive/evs/evs_mock_hal_configuration.xml";
40 std::string_view ConfigManager::sConfigOverridePath =
41 "/vendor/etc/automotive/evs/evs_configuration_override.xml";
42
deviceTypeFromSV(const std::string_view sv)43 ConfigManager::CameraInfo::DeviceType ConfigManager::CameraInfo::deviceTypeFromSV(
44 const std::string_view sv) {
45 using namespace std::string_view_literals;
46 static const std::unordered_map<std::string_view, DeviceType> nameToType = {
47 {"mock"sv, DeviceType::MOCK},
48 {"v4l2"sv, DeviceType::V4L2},
49 {"video"sv, DeviceType::VIDEO},
50 };
51 const auto search = nameToType.find(sv);
52 return search == nameToType.end() ? DeviceType::UNKNOWN : search->second;
53 }
54
pixelFormatFromSV(const std::string_view sv)55 ConfigManager::CameraInfo::PixelFormat ConfigManager::CameraInfo::pixelFormatFromSV(
56 const std::string_view sv) {
57 using namespace std::string_view_literals;
58 static const std::unordered_map<std::string_view, PixelFormat> nameToFormat = {
59 // Full resolution Y plane followed by 2x2 subsampled U/V
60 // interleaved plane.
61 {"NV12"sv, PixelFormat::NV12},
62 // Full resolution Y plane followed by 2x2 subsampled V/U
63 // interleaved plane.
64 {"NV21"sv, PixelFormat::NV21},
65 // Full resolution Y plane followed by 2x2 subsampled V plane and then U plane.
66 {"YV12"sv, PixelFormat::YV12},
67 // Full resolution Y plane followed by 2x2 subsampled U plane and then V plane.
68 {"I420"sv, PixelFormat::I420},
69 };
70 const auto search = nameToFormat.find(sv);
71 return search == nameToFormat.end() ? PixelFormat::UNKNOWN : search->second;
72 }
73
printElementNames(const XMLElement * rootElem,const std::string & prefix) const74 void ConfigManager::printElementNames(const XMLElement* rootElem, const std::string& prefix) const {
75 const XMLElement* curElem = rootElem;
76
77 while (curElem != nullptr) {
78 LOG(VERBOSE) << "[ELEM] " << prefix << curElem->Name();
79 const XMLAttribute* curAttr = curElem->FirstAttribute();
80 while (curAttr) {
81 LOG(VERBOSE) << "[ATTR] " << prefix << curAttr->Name() << ": " << curAttr->Value();
82 curAttr = curAttr->Next();
83 }
84
85 /* recursively go down to descendants */
86 printElementNames(curElem->FirstChildElement(), prefix + "\t");
87
88 curElem = curElem->NextSiblingElement();
89 }
90 }
91
readCameraInfo(const XMLElement * const aCameraElem)92 void ConfigManager::readCameraInfo(const XMLElement* const aCameraElem) {
93 if (aCameraElem == nullptr) {
94 LOG(WARNING) << "XML file does not have required camera element";
95 return;
96 }
97
98 const XMLElement* curElem = aCameraElem->FirstChildElement();
99 while (curElem != nullptr) {
100 if (!strcmp(curElem->Name(), "group")) {
101 /* camera group identifier */
102 const char* id = curElem->FindAttribute("id")->Value();
103
104 /* create a camera group to be filled */
105 CameraGroupInfo* aCamera = new CameraGroupInfo();
106
107 /* read camera device information */
108 if (!readCameraDeviceInfo(aCamera, curElem)) {
109 LOG(WARNING) << "Failed to read a camera information of " << id;
110 delete aCamera;
111 continue;
112 }
113
114 /* camera group synchronization */
115 const char* sync = curElem->FindAttribute("synchronized")->Value();
116 if (!strcmp(sync, "CALIBRATED")) {
117 aCamera->synchronized = ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE_CALIBRATED;
118 } else if (!strcmp(sync, "APPROXIMATE")) {
119 aCamera->synchronized = ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE_APPROXIMATE;
120 } else {
121 aCamera->synchronized = 0; // Not synchronized
122 }
123
124 /* add a group to hash map */
125 mCameraGroups.insert_or_assign(id, std::unique_ptr<CameraGroupInfo>(aCamera));
126 } else if (!std::strcmp(curElem->Name(), "device")) {
127 /* camera unique identifier */
128 const char* id = curElem->FindAttribute("id")->Value();
129
130 /* camera mount location */
131 const char* pos = curElem->FindAttribute("position")->Value();
132
133 /* create a camera device to be filled */
134 CameraInfo* aCamera = new CameraInfo();
135
136 /* read camera device information */
137 if (!readCameraDeviceInfo(aCamera, curElem)) {
138 LOG(WARNING) << "Failed to read a camera information of " << id;
139 delete aCamera;
140 continue;
141 }
142
143 /* store read camera module information */
144 mCameraInfo.insert_or_assign(id, std::unique_ptr<CameraInfo>(aCamera));
145
146 /* assign a camera device to a position group */
147 mCameraPosition[pos].insert(id);
148 } else {
149 /* ignore other device types */
150 LOG(DEBUG) << "Unknown element " << curElem->Name() << " is ignored";
151 }
152
153 curElem = curElem->NextSiblingElement();
154 }
155 }
156
readCameraDeviceInfo(CameraInfo * aCamera,const XMLElement * aDeviceElem)157 bool ConfigManager::readCameraDeviceInfo(CameraInfo* aCamera, const XMLElement* aDeviceElem) {
158 if (aCamera == nullptr || aDeviceElem == nullptr) {
159 return false;
160 }
161
162 if (const auto typeAttr = aDeviceElem->FindAttribute("type")) {
163 aCamera->deviceType = CameraInfo::deviceTypeFromSV(typeAttr->Value());
164 }
165
166 if (const auto formatAttr = aDeviceElem->FindAttribute("format")) {
167 aCamera->format = CameraInfo::pixelFormatFromSV(formatAttr->Value());
168 }
169
170 /* size information to allocate camera_metadata_t */
171 size_t totalEntries = 0;
172 size_t totalDataSize = 0;
173
174 /* read device capabilities */
175 totalEntries +=
176 readCameraCapabilities(aDeviceElem->FirstChildElement("caps"), aCamera, totalDataSize);
177
178 /* read camera metadata */
179 totalEntries += readCameraMetadata(aDeviceElem->FirstChildElement("characteristics"), aCamera,
180 totalDataSize);
181
182 /* construct camera_metadata_t */
183 if (!constructCameraMetadata(aCamera, totalEntries, totalDataSize)) {
184 LOG(WARNING) << "Either failed to allocate memory or "
185 << "allocated memory was not large enough";
186 }
187
188 return true;
189 }
190
readCameraCapabilities(const XMLElement * const aCapElem,CameraInfo * aCamera,size_t & dataSize)191 size_t ConfigManager::readCameraCapabilities(const XMLElement* const aCapElem, CameraInfo* aCamera,
192 size_t& dataSize) {
193 if (aCapElem == nullptr || aCamera == nullptr) {
194 return 0;
195 }
196
197 std::string token;
198 const XMLElement* curElem = nullptr;
199
200 /* a list of supported camera parameters/controls */
201 curElem = aCapElem->FirstChildElement("supported_controls");
202 if (curElem != nullptr) {
203 const XMLElement* ctrlElem = curElem->FirstChildElement("control");
204 while (ctrlElem != nullptr) {
205 const char* nameAttr = ctrlElem->FindAttribute("name")->Value();
206 int32_t minVal = INT32_MIN, maxVal = INT32_MAX;
207 if (!android::base::ParseInt(ctrlElem->FindAttribute("min")->Value(), &minVal)) {
208 LOG(WARNING) << "Failed to parse " << ctrlElem->FindAttribute("min")->Value();
209 }
210
211 if (!android::base::ParseInt(ctrlElem->FindAttribute("max")->Value(), &maxVal)) {
212 LOG(WARNING) << "Failed to parse " << ctrlElem->FindAttribute("max")->Value();
213 }
214
215 int32_t stepVal = 1;
216 const XMLAttribute* stepAttr = ctrlElem->FindAttribute("step");
217 if (stepAttr != nullptr) {
218 if (!android::base::ParseInt(stepAttr->Value(), &stepVal)) {
219 LOG(WARNING) << "Failed to parse " << stepAttr->Value();
220 }
221 }
222
223 CameraParam aParam;
224 if (ConfigManagerUtil::convertToEvsCameraParam(nameAttr, aParam)) {
225 aCamera->controls.insert_or_assign(aParam,
226 std::make_tuple(minVal, maxVal, stepVal));
227 }
228
229 ctrlElem = ctrlElem->NextSiblingElement("control");
230 }
231 }
232
233 /* a list of camera stream configurations */
234 curElem = aCapElem->FirstChildElement("stream");
235 while (curElem != nullptr) {
236 /* read 5 attributes */
237 const XMLAttribute* idAttr = curElem->FindAttribute("id");
238 const XMLAttribute* widthAttr = curElem->FindAttribute("width");
239 const XMLAttribute* heightAttr = curElem->FindAttribute("height");
240 const XMLAttribute* fmtAttr = curElem->FindAttribute("format");
241 const XMLAttribute* fpsAttr = curElem->FindAttribute("framerate");
242
243 int32_t id = -1;
244 int32_t framerate = 0;
245 if (!android::base::ParseInt(idAttr->Value(), &id)) {
246 LOG(WARNING) << "Failed to parse " << idAttr->Value();
247 }
248 if (fpsAttr != nullptr) {
249 if (!android::base::ParseInt(fpsAttr->Value(), &framerate)) {
250 LOG(WARNING) << "Failed to parse " << fpsAttr->Value();
251 }
252 }
253
254 PixelFormat format = PixelFormat::UNSPECIFIED;
255 if (ConfigManagerUtil::convertToPixelFormat(fmtAttr->Value(), format)) {
256 StreamConfiguration cfg = {
257 .id = id,
258 .format = format,
259 .type = ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
260 .framerate = framerate,
261 };
262
263 if (!android::base::ParseInt(widthAttr->Value(), &cfg.width) ||
264 !android::base::ParseInt(heightAttr->Value(), &cfg.height)) {
265 LOG(WARNING) << "Failed to parse " << widthAttr->Value() << " and "
266 << heightAttr->Value();
267 }
268 aCamera->streamConfigurations.insert_or_assign(id, cfg);
269 }
270
271 curElem = curElem->NextSiblingElement("stream");
272 }
273
274 dataSize = calculate_camera_metadata_entry_data_size(
275 get_camera_metadata_tag_type(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS),
276 aCamera->streamConfigurations.size() * sizeof(StreamConfiguration));
277
278 /* a single camera metadata entry contains multiple stream configurations */
279 return dataSize > 0 ? 1 : 0;
280 }
281
readCameraMetadata(const XMLElement * const aParamElem,CameraInfo * aCamera,size_t & dataSize)282 size_t ConfigManager::readCameraMetadata(const XMLElement* const aParamElem, CameraInfo* aCamera,
283 size_t& dataSize) {
284 if (aParamElem == nullptr || aCamera == nullptr) {
285 return 0;
286 }
287
288 const XMLElement* curElem = aParamElem->FirstChildElement("parameter");
289 size_t numEntries = 0;
290 camera_metadata_tag_t tag;
291 while (curElem != nullptr) {
292 if (ConfigManagerUtil::convertToMetadataTag(curElem->FindAttribute("name")->Value(), tag)) {
293 switch (tag) {
294 case ANDROID_LENS_DISTORTION:
295 case ANDROID_LENS_POSE_ROTATION:
296 case ANDROID_LENS_POSE_TRANSLATION:
297 case ANDROID_LENS_INTRINSIC_CALIBRATION: {
298 /* float[] */
299 size_t count = 0;
300 void* data = ConfigManagerUtil::convertFloatArray(
301 curElem->FindAttribute("size")->Value(),
302 curElem->FindAttribute("value")->Value(), count);
303
304 aCamera->cameraMetadata.insert_or_assign(tag, std::make_pair(data, count));
305
306 ++numEntries;
307 dataSize += calculate_camera_metadata_entry_data_size(
308 get_camera_metadata_tag_type(tag), count);
309
310 break;
311 }
312
313 case ANDROID_REQUEST_AVAILABLE_CAPABILITIES: {
314 camera_metadata_enum_android_request_available_capabilities_t* data =
315 new camera_metadata_enum_android_request_available_capabilities_t[1];
316 if (ConfigManagerUtil::convertToCameraCapability(
317 curElem->FindAttribute("value")->Value(), *data)) {
318 aCamera->cameraMetadata.insert_or_assign(tag,
319 std::make_pair((void*)data, 1));
320
321 ++numEntries;
322 dataSize += calculate_camera_metadata_entry_data_size(
323 get_camera_metadata_tag_type(tag), 1);
324 }
325 break;
326 }
327
328 case ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS: {
329 /* a comma-separated list of physical camera devices */
330 size_t len = strlen(curElem->FindAttribute("value")->Value());
331 char* data = new char[len + 1];
332 memcpy(data, curElem->FindAttribute("value")->Value(), len * sizeof(char));
333
334 /* replace commas with null char */
335 char* p = data;
336 while (*p != '\0') {
337 if (*p == ',') {
338 *p = '\0';
339 }
340 ++p;
341 }
342
343 aCamera->cameraMetadata.insert_or_assign(tag,
344 std::make_pair((void*)data, len + 1));
345
346 ++numEntries;
347 dataSize += calculate_camera_metadata_entry_data_size(
348 get_camera_metadata_tag_type(tag), len);
349 break;
350 }
351
352 /* TODO(b/140416878): add vendor-defined/custom tag support */
353 default:
354 LOG(WARNING) << "Parameter " << curElem->FindAttribute("name")->Value()
355 << " is not supported";
356 break;
357 }
358 } else {
359 LOG(WARNING) << "Unsupported metadata tag " << curElem->FindAttribute("name")->Value()
360 << " is found.";
361 }
362
363 curElem = curElem->NextSiblingElement("parameter");
364 }
365
366 return numEntries;
367 }
368
constructCameraMetadata(CameraInfo * aCamera,size_t totalEntries,size_t totalDataSize)369 bool ConfigManager::constructCameraMetadata(CameraInfo* aCamera, size_t totalEntries,
370 size_t totalDataSize) {
371 if (aCamera == nullptr || !aCamera->allocate(totalEntries, totalDataSize)) {
372 LOG(ERROR) << "Failed to allocate memory for camera metadata";
373 return false;
374 }
375
376 const size_t numStreamConfigs = aCamera->streamConfigurations.size();
377 std::unique_ptr<int32_t[]> data(new int32_t[sizeof(StreamConfiguration) * numStreamConfigs]);
378 int32_t* ptr = data.get();
379 for (auto& cfg : aCamera->streamConfigurations) {
380 memcpy(ptr, &cfg.second, sizeof(StreamConfiguration));
381 ptr += sizeof(StreamConfiguration);
382 }
383 int32_t err = add_camera_metadata_entry(
384 aCamera->characteristics, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, data.get(),
385 numStreamConfigs * sizeof(StreamConfiguration));
386
387 if (err) {
388 LOG(ERROR) << "Failed to add stream configurations to metadata, ignored";
389 return false;
390 }
391
392 bool success = true;
393 for (auto& [tag, entry] : aCamera->cameraMetadata) {
394 /* try to add new camera metadata entry */
395 int32_t err =
396 add_camera_metadata_entry(aCamera->characteristics, tag, entry.first, entry.second);
397 if (err) {
398 LOG(ERROR) << "Failed to add an entry with a tag, " << std::hex << tag;
399
400 /* may exceed preallocated capacity */
401 LOG(ERROR) << "Camera metadata has "
402 << get_camera_metadata_entry_count(aCamera->characteristics) << " / "
403 << get_camera_metadata_entry_capacity(aCamera->characteristics)
404 << " entries and "
405 << get_camera_metadata_data_count(aCamera->characteristics) << " / "
406 << get_camera_metadata_data_capacity(aCamera->characteristics)
407 << " bytes are filled.";
408 LOG(ERROR) << "\tCurrent metadata entry requires "
409 << calculate_camera_metadata_entry_data_size(tag, entry.second) << " bytes.";
410
411 success = false;
412 }
413 }
414
415 LOG(VERBOSE) << "Camera metadata has "
416 << get_camera_metadata_entry_count(aCamera->characteristics) << " / "
417 << get_camera_metadata_entry_capacity(aCamera->characteristics) << " entries and "
418 << get_camera_metadata_data_count(aCamera->characteristics) << " / "
419 << get_camera_metadata_data_capacity(aCamera->characteristics)
420 << " bytes are filled.";
421 return success;
422 }
423
readSystemInfo(const XMLElement * const aSysElem)424 void ConfigManager::readSystemInfo(const XMLElement* const aSysElem) {
425 if (aSysElem == nullptr) {
426 return;
427 }
428
429 /*
430 * Please note that this function assumes that a given system XML element
431 * and its child elements follow DTD. If it does not, it will cause a
432 * segmentation fault due to the failure of finding expected attributes.
433 */
434
435 /* read number of cameras available in the system */
436 const XMLElement* xmlElem = aSysElem->FirstChildElement("num_cameras");
437 if (xmlElem != nullptr) {
438 if (!android::base::ParseInt(xmlElem->FindAttribute("value")->Value(),
439 &mSystemInfo.numCameras)) {
440 LOG(WARNING) << "Failed to parse " << xmlElem->FindAttribute("value")->Value();
441 }
442 }
443 }
444
readDisplayInfo(const XMLElement * const aDisplayElem)445 void ConfigManager::readDisplayInfo(const XMLElement* const aDisplayElem) {
446 if (aDisplayElem == nullptr) {
447 LOG(WARNING) << "XML file does not have required camera element";
448 return;
449 }
450
451 const XMLElement* curDev = aDisplayElem->FirstChildElement("device");
452 while (curDev != nullptr) {
453 const char* id = curDev->FindAttribute("id")->Value();
454 std::unique_ptr<DisplayInfo> dpy(new DisplayInfo());
455 if (dpy == nullptr) {
456 LOG(ERROR) << "Failed to allocate memory for DisplayInfo";
457 return;
458 }
459
460 const XMLElement* cap = curDev->FirstChildElement("caps");
461 if (cap != nullptr) {
462 const XMLElement* curStream = cap->FirstChildElement("stream");
463 while (curStream != nullptr) {
464 /* read 4 attributes */
465 const XMLAttribute* idAttr = curStream->FindAttribute("id");
466 const XMLAttribute* widthAttr = curStream->FindAttribute("width");
467 const XMLAttribute* heightAttr = curStream->FindAttribute("height");
468 const XMLAttribute* fmtAttr = curStream->FindAttribute("format");
469
470 int32_t id = -1;
471 if (!android::base::ParseInt(idAttr->Value(), &id)) {
472 LOG(WARNING) << "Failed to parse " << idAttr->Value();
473 }
474 PixelFormat format = PixelFormat::UNSPECIFIED;
475 if (ConfigManagerUtil::convertToPixelFormat(fmtAttr->Value(), format)) {
476 StreamConfiguration cfg = {
477 .id = id,
478 .format = format,
479 .type = ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT,
480 };
481 if (!android::base::ParseInt(widthAttr->Value(), &cfg.width) ||
482 !android::base::ParseInt(heightAttr->Value(), &cfg.height)) {
483 LOG(WARNING) << "Failed to parse " << widthAttr->Value() << " and "
484 << heightAttr->Value();
485 }
486 dpy->streamConfigurations.insert_or_assign(id, cfg);
487 }
488
489 curStream = curStream->NextSiblingElement("stream");
490 }
491 }
492
493 mDisplayInfo.insert_or_assign(id, std::move(dpy));
494 curDev = curDev->NextSiblingElement("device");
495 }
496
497 return;
498 }
499
readConfigDataFromXML(const std::string path)500 bool ConfigManager::readConfigDataFromXML(const std::string path) noexcept {
501 XMLDocument xmlDoc;
502
503 const int64_t parsingStart = android::elapsedRealtimeNano();
504
505 /* load and parse a configuration file */
506 xmlDoc.LoadFile(path.c_str());
507 if (xmlDoc.ErrorID() != tinyxml2::XML_SUCCESS) {
508 LOG(ERROR) << "Failed to load and/or parse a configuration file, " << xmlDoc.ErrorStr();
509 return false;
510 }
511
512 /* retrieve the root element */
513 const XMLElement* rootElem = xmlDoc.RootElement();
514 if (std::strcmp(rootElem->Name(), "configuration") != 0) {
515 LOG(ERROR) << "A configuration file is not in the required format. "
516 << "See /etc/automotive/evs/evs_configuration.dtd";
517 return false;
518 }
519
520 std::unique_lock<std::mutex> lock(mConfigLock);
521
522 /*
523 * parse camera information; this needs to be done before reading system
524 * information
525 */
526 readCameraInfo(rootElem->FirstChildElement("camera"));
527
528 /* parse system information */
529 readSystemInfo(rootElem->FirstChildElement("system"));
530
531 /* parse display information */
532 readDisplayInfo(rootElem->FirstChildElement("display"));
533
534 /* configuration data is ready to be consumed */
535 mIsReady = true;
536
537 /* notify that configuration data is ready */
538 lock.unlock();
539 mConfigCond.notify_all();
540
541 const int64_t parsingEnd = android::elapsedRealtimeNano();
542 LOG(INFO) << "Parsing configuration file takes " << std::scientific
543 << (double)(parsingEnd - parsingStart) / 1000000.0 << " ms.";
544
545 return true;
546 }
547
readConfigDataFromBinary()548 bool ConfigManager::readConfigDataFromBinary() {
549 /* Temporary buffer to hold configuration data read from a binary file */
550 char mBuffer[1024];
551
552 std::fstream srcFile;
553 const int64_t readStart = android::elapsedRealtimeNano();
554
555 srcFile.open(mBinaryFilePath, std::fstream::in | std::fstream::binary);
556 if (!srcFile) {
557 LOG(ERROR) << "Failed to open a source binary file, " << mBinaryFilePath;
558 return false;
559 }
560
561 std::unique_lock<std::mutex> lock(mConfigLock);
562 mIsReady = false;
563
564 /* read configuration data into the internal buffer */
565 srcFile.read(mBuffer, sizeof(mBuffer));
566 LOG(VERBOSE) << __FUNCTION__ << ": " << srcFile.gcount() << " bytes are read.";
567 char* p = mBuffer;
568 size_t sz = 0;
569
570 /* read number of camera group information entries */
571 const size_t ngrps = *(reinterpret_cast<size_t*>(p));
572 p += sizeof(size_t);
573
574 /* read each camera information entry */
575 for (size_t cidx = 0; cidx < ngrps; ++cidx) {
576 /* read camera identifier */
577 std::string cameraId = *(reinterpret_cast<std::string*>(p));
578 p += sizeof(std::string);
579
580 /* size of camera_metadata_t */
581 const size_t num_entry = *(reinterpret_cast<size_t*>(p));
582 p += sizeof(size_t);
583 const size_t num_data = *(reinterpret_cast<size_t*>(p));
584 p += sizeof(size_t);
585
586 /* create CameraInfo and add it to hash map */
587 std::unique_ptr<ConfigManager::CameraGroupInfo> aCamera;
588 if (aCamera == nullptr || !aCamera->allocate(num_entry, num_data)) {
589 LOG(ERROR) << "Failed to create new CameraInfo object";
590 mCameraInfo.clear();
591 return false;
592 }
593
594 /* controls */
595 typedef struct {
596 CameraParam cid;
597 int32_t min;
598 int32_t max;
599 int32_t step;
600 } CameraCtrl;
601 sz = *(reinterpret_cast<size_t*>(p));
602 p += sizeof(size_t);
603 CameraCtrl* ptr = reinterpret_cast<CameraCtrl*>(p);
604 for (size_t idx = 0; idx < sz; ++idx) {
605 CameraCtrl temp = *ptr++;
606 aCamera->controls.insert_or_assign(temp.cid,
607 std::make_tuple(temp.min, temp.max, temp.step));
608 }
609 p = reinterpret_cast<char*>(ptr);
610
611 /* stream configurations */
612 sz = *(reinterpret_cast<size_t*>(p));
613 p += sizeof(size_t);
614 int32_t* i32_ptr = reinterpret_cast<int32_t*>(p);
615 for (size_t idx = 0; idx < sz; ++idx) {
616 const int32_t id = *i32_ptr++;
617
618 StreamConfiguration temp;
619 memcpy(&temp, i32_ptr, sizeof(StreamConfiguration));
620 i32_ptr += sizeof(StreamConfiguration);
621 aCamera->streamConfigurations.insert_or_assign(id, temp);
622 }
623 p = reinterpret_cast<char*>(i32_ptr);
624
625 /* synchronization */
626 aCamera->synchronized = *(reinterpret_cast<int32_t*>(p));
627 p += sizeof(int32_t);
628
629 for (size_t idx = 0; idx < num_entry; ++idx) {
630 /* Read camera metadata entries */
631 camera_metadata_tag_t tag = *reinterpret_cast<camera_metadata_tag_t*>(p);
632 p += sizeof(camera_metadata_tag_t);
633 const size_t count = *reinterpret_cast<size_t*>(p);
634 p += sizeof(size_t);
635
636 const int32_t type = get_camera_metadata_tag_type(tag);
637 switch (type) {
638 case TYPE_BYTE: {
639 add_camera_metadata_entry(aCamera->characteristics, tag, p, count);
640 p += count * sizeof(uint8_t);
641 break;
642 }
643 case TYPE_INT32: {
644 add_camera_metadata_entry(aCamera->characteristics, tag, p, count);
645 p += count * sizeof(int32_t);
646 break;
647 }
648 case TYPE_FLOAT: {
649 add_camera_metadata_entry(aCamera->characteristics, tag, p, count);
650 p += count * sizeof(float);
651 break;
652 }
653 case TYPE_INT64: {
654 add_camera_metadata_entry(aCamera->characteristics, tag, p, count);
655 p += count * sizeof(int64_t);
656 break;
657 }
658 case TYPE_DOUBLE: {
659 add_camera_metadata_entry(aCamera->characteristics, tag, p, count);
660 p += count * sizeof(double);
661 break;
662 }
663 case TYPE_RATIONAL:
664 p += count * sizeof(camera_metadata_rational_t);
665 break;
666 default:
667 LOG(WARNING) << "Type " << type << " is unknown; " << "data may be corrupted.";
668 break;
669 }
670 }
671
672 mCameraInfo.insert_or_assign(cameraId, std::move(aCamera));
673 }
674
675 /* read number of camera information entries */
676 const size_t ncams = *(reinterpret_cast<size_t*>(p));
677 p += sizeof(size_t);
678
679 /* read each camera information entry */
680 for (size_t cidx = 0; cidx < ncams; ++cidx) {
681 /* read camera identifier */
682 std::string cameraId = *(reinterpret_cast<std::string*>(p));
683 p += sizeof(std::string);
684
685 /* size of camera_metadata_t */
686 const size_t num_entry = *(reinterpret_cast<size_t*>(p));
687 p += sizeof(size_t);
688 const size_t num_data = *(reinterpret_cast<size_t*>(p));
689 p += sizeof(size_t);
690
691 /* create CameraInfo and add it to hash map */
692 std::unique_ptr<ConfigManager::CameraInfo> aCamera;
693 if (aCamera == nullptr || !aCamera->allocate(num_entry, num_data)) {
694 LOG(ERROR) << "Failed to create new CameraInfo object";
695 mCameraInfo.clear();
696 return false;
697 }
698
699 /* controls */
700 typedef struct {
701 CameraParam cid;
702 int32_t min;
703 int32_t max;
704 int32_t step;
705 } CameraCtrl;
706 sz = *(reinterpret_cast<size_t*>(p));
707 p += sizeof(size_t);
708 CameraCtrl* ptr = reinterpret_cast<CameraCtrl*>(p);
709 for (size_t idx = 0; idx < sz; ++idx) {
710 CameraCtrl temp = *ptr++;
711 aCamera->controls.insert_or_assign(temp.cid,
712 std::make_tuple(temp.min, temp.max, temp.step));
713 }
714 p = reinterpret_cast<char*>(ptr);
715
716 /* stream configurations */
717 sz = *(reinterpret_cast<size_t*>(p));
718 p += sizeof(size_t);
719 int32_t* i32_ptr = reinterpret_cast<int32_t*>(p);
720 for (size_t idx = 0; idx < sz; ++idx) {
721 const int32_t id = *i32_ptr++;
722
723 StreamConfiguration temp;
724 memcpy(&temp, i32_ptr, sizeof(StreamConfiguration));
725 i32_ptr += sizeof(StreamConfiguration);
726 aCamera->streamConfigurations.insert_or_assign(id, temp);
727 }
728 p = reinterpret_cast<char*>(i32_ptr);
729
730 for (size_t idx = 0; idx < num_entry; ++idx) {
731 /* Read camera metadata entries */
732 camera_metadata_tag_t tag = *reinterpret_cast<camera_metadata_tag_t*>(p);
733 p += sizeof(camera_metadata_tag_t);
734 const size_t count = *reinterpret_cast<size_t*>(p);
735 p += sizeof(size_t);
736
737 const int32_t type = get_camera_metadata_tag_type(tag);
738 switch (type) {
739 case TYPE_BYTE: {
740 add_camera_metadata_entry(aCamera->characteristics, tag, p, count);
741 p += count * sizeof(uint8_t);
742 break;
743 }
744 case TYPE_INT32: {
745 add_camera_metadata_entry(aCamera->characteristics, tag, p, count);
746 p += count * sizeof(int32_t);
747 break;
748 }
749 case TYPE_FLOAT: {
750 add_camera_metadata_entry(aCamera->characteristics, tag, p, count);
751 p += count * sizeof(float);
752 break;
753 }
754 case TYPE_INT64: {
755 add_camera_metadata_entry(aCamera->characteristics, tag, p, count);
756 p += count * sizeof(int64_t);
757 break;
758 }
759 case TYPE_DOUBLE: {
760 add_camera_metadata_entry(aCamera->characteristics, tag, p, count);
761 p += count * sizeof(double);
762 break;
763 }
764 case TYPE_RATIONAL:
765 p += count * sizeof(camera_metadata_rational_t);
766 break;
767 default:
768 LOG(WARNING) << "Type " << type << " is unknown; " << "data may be corrupted.";
769 break;
770 }
771 }
772
773 mCameraInfo.insert_or_assign(cameraId, std::move(aCamera));
774 }
775
776 mIsReady = true;
777
778 /* notify that configuration data is ready */
779 lock.unlock();
780 mConfigCond.notify_all();
781
782 int64_t readEnd = android::elapsedRealtimeNano();
783 LOG(INFO) << __FUNCTION__ << " takes " << std::scientific
784 << (double)(readEnd - readStart) / 1000000.0 << " ms.";
785
786 return true;
787 }
788
writeConfigDataToBinary()789 bool ConfigManager::writeConfigDataToBinary() {
790 std::fstream outFile;
791
792 const int64_t writeStart = android::elapsedRealtimeNano();
793
794 outFile.open(mBinaryFilePath, std::fstream::out | std::fstream::binary);
795 if (!outFile) {
796 LOG(ERROR) << "Failed to open a destination binary file, " << mBinaryFilePath;
797 return false;
798 }
799
800 /* lock a configuration data while it's being written to the filesystem */
801 std::lock_guard<std::mutex> lock(mConfigLock);
802
803 /* write camera group information */
804 size_t sz = mCameraGroups.size();
805 outFile.write(reinterpret_cast<const char*>(&sz), sizeof(size_t));
806 for (auto&& [camId, camInfo] : mCameraGroups) {
807 LOG(INFO) << "Storing camera group " << camId;
808
809 /* write a camera identifier string */
810 outFile.write(reinterpret_cast<const char*>(&camId), sizeof(std::string));
811
812 /* controls */
813 sz = camInfo->controls.size();
814 outFile.write(reinterpret_cast<const char*>(&sz), sizeof(size_t));
815 for (auto&& [ctrl, range] : camInfo->controls) {
816 outFile.write(reinterpret_cast<const char*>(&ctrl), sizeof(CameraParam));
817 outFile.write(reinterpret_cast<const char*>(&std::get<0>(range)), sizeof(int32_t));
818 outFile.write(reinterpret_cast<const char*>(&std::get<1>(range)), sizeof(int32_t));
819 outFile.write(reinterpret_cast<const char*>(&std::get<2>(range)), sizeof(int32_t));
820 }
821
822 /* stream configurations */
823 sz = camInfo->streamConfigurations.size();
824 outFile.write(reinterpret_cast<const char*>(&sz), sizeof(size_t));
825 for (auto&& [sid, cfg] : camInfo->streamConfigurations) {
826 outFile.write(reinterpret_cast<const char*>(sid), sizeof(int32_t));
827 outFile.write(reinterpret_cast<const char*>(&cfg), sizeof(cfg));
828 }
829
830 /* synchronization */
831 outFile.write(reinterpret_cast<const char*>(&camInfo->synchronized), sizeof(int32_t));
832
833 /* size of camera_metadata_t */
834 size_t num_entry = 0;
835 size_t num_data = 0;
836 if (camInfo->characteristics != nullptr) {
837 num_entry = get_camera_metadata_entry_count(camInfo->characteristics);
838 num_data = get_camera_metadata_data_count(camInfo->characteristics);
839 }
840 outFile.write(reinterpret_cast<const char*>(&num_entry), sizeof(size_t));
841 outFile.write(reinterpret_cast<const char*>(&num_data), sizeof(size_t));
842
843 /* write each camera metadata entry */
844 if (num_entry > 0) {
845 camera_metadata_entry_t entry;
846 for (size_t idx = 0; idx < num_entry; ++idx) {
847 if (get_camera_metadata_entry(camInfo->characteristics, idx, &entry)) {
848 LOG(ERROR) << "Failed to retrieve camera metadata entry " << idx;
849 outFile.close();
850 return false;
851 }
852
853 outFile.write(reinterpret_cast<const char*>(&entry.tag), sizeof(entry.tag));
854 outFile.write(reinterpret_cast<const char*>(&entry.count), sizeof(entry.count));
855
856 int32_t type = get_camera_metadata_tag_type(entry.tag);
857 switch (type) {
858 case TYPE_BYTE:
859 outFile.write(reinterpret_cast<const char*>(entry.data.u8),
860 sizeof(uint8_t) * entry.count);
861 break;
862 case TYPE_INT32:
863 outFile.write(reinterpret_cast<const char*>(entry.data.i32),
864 sizeof(int32_t) * entry.count);
865 break;
866 case TYPE_FLOAT:
867 outFile.write(reinterpret_cast<const char*>(entry.data.f),
868 sizeof(float) * entry.count);
869 break;
870 case TYPE_INT64:
871 outFile.write(reinterpret_cast<const char*>(entry.data.i64),
872 sizeof(int64_t) * entry.count);
873 break;
874 case TYPE_DOUBLE:
875 outFile.write(reinterpret_cast<const char*>(entry.data.d),
876 sizeof(double) * entry.count);
877 break;
878 case TYPE_RATIONAL:
879 [[fallthrough]];
880 default:
881 LOG(WARNING) << "Type " << type << " is not supported.";
882 break;
883 }
884 }
885 }
886 }
887
888 /* write camera device information */
889 sz = mCameraInfo.size();
890 outFile.write(reinterpret_cast<const char*>(&sz), sizeof(size_t));
891 for (auto&& [camId, camInfo] : mCameraInfo) {
892 LOG(INFO) << "Storing camera " << camId;
893
894 /* write a camera identifier string */
895 outFile.write(reinterpret_cast<const char*>(&camId), sizeof(std::string));
896
897 /* controls */
898 sz = camInfo->controls.size();
899 outFile.write(reinterpret_cast<const char*>(&sz), sizeof(size_t));
900 for (auto& [ctrl, range] : camInfo->controls) {
901 outFile.write(reinterpret_cast<const char*>(&ctrl), sizeof(CameraParam));
902 outFile.write(reinterpret_cast<const char*>(&std::get<0>(range)), sizeof(int32_t));
903 outFile.write(reinterpret_cast<const char*>(&std::get<1>(range)), sizeof(int32_t));
904 outFile.write(reinterpret_cast<const char*>(&std::get<2>(range)), sizeof(int32_t));
905 }
906
907 /* stream configurations */
908 sz = camInfo->streamConfigurations.size();
909 outFile.write(reinterpret_cast<const char*>(&sz), sizeof(size_t));
910 for (auto&& [sid, cfg] : camInfo->streamConfigurations) {
911 outFile.write(reinterpret_cast<const char*>(sid), sizeof(int32_t));
912 outFile.write(reinterpret_cast<const char*>(&cfg), sizeof(cfg));
913 }
914
915 /* size of camera_metadata_t */
916 size_t num_entry = 0;
917 size_t num_data = 0;
918 if (camInfo->characteristics != nullptr) {
919 num_entry = get_camera_metadata_entry_count(camInfo->characteristics);
920 num_data = get_camera_metadata_data_count(camInfo->characteristics);
921 }
922 outFile.write(reinterpret_cast<const char*>(&num_entry), sizeof(size_t));
923 outFile.write(reinterpret_cast<const char*>(&num_data), sizeof(size_t));
924
925 /* write each camera metadata entry */
926 if (num_entry > 0) {
927 camera_metadata_entry_t entry;
928 for (size_t idx = 0; idx < num_entry; ++idx) {
929 if (get_camera_metadata_entry(camInfo->characteristics, idx, &entry)) {
930 LOG(ERROR) << "Failed to retrieve camera metadata entry " << idx;
931 outFile.close();
932 return false;
933 }
934
935 outFile.write(reinterpret_cast<const char*>(&entry.tag), sizeof(entry.tag));
936 outFile.write(reinterpret_cast<const char*>(&entry.count), sizeof(entry.count));
937
938 int32_t type = get_camera_metadata_tag_type(entry.tag);
939 switch (type) {
940 case TYPE_BYTE:
941 outFile.write(reinterpret_cast<const char*>(entry.data.u8),
942 sizeof(uint8_t) * entry.count);
943 break;
944 case TYPE_INT32:
945 outFile.write(reinterpret_cast<const char*>(entry.data.i32),
946 sizeof(int32_t) * entry.count);
947 break;
948 case TYPE_FLOAT:
949 outFile.write(reinterpret_cast<const char*>(entry.data.f),
950 sizeof(float) * entry.count);
951 break;
952 case TYPE_INT64:
953 outFile.write(reinterpret_cast<const char*>(entry.data.i64),
954 sizeof(int64_t) * entry.count);
955 break;
956 case TYPE_DOUBLE:
957 outFile.write(reinterpret_cast<const char*>(entry.data.d),
958 sizeof(double) * entry.count);
959 break;
960 case TYPE_RATIONAL:
961 [[fallthrough]];
962 default:
963 LOG(WARNING) << "Type " << type << " is not supported.";
964 break;
965 }
966 }
967 }
968 }
969
970 outFile.close();
971 int64_t writeEnd = android::elapsedRealtimeNano();
972 LOG(INFO) << __FUNCTION__ << " takes " << std::scientific
973 << (double)(writeEnd - writeStart) / 1000000.0 << " ms.";
974
975 return true;
976 }
977
Create()978 std::unique_ptr<ConfigManager> ConfigManager::Create() {
979 std::unique_ptr<ConfigManager> mgr = Create(std::string(sConfigOverridePath));
980 if (!mgr) {
981 LOG(DEBUG) << "A configuration override file does not exist. Use a default file instead.";
982 mgr = Create(std::string((sConfigDefaultPath)));
983 }
984
985 return mgr;
986 }
987
Create(const std::string path)988 std::unique_ptr<ConfigManager> ConfigManager::Create(const std::string path) {
989 std::unique_ptr<ConfigManager> cfgMgr(new ConfigManager());
990
991 /*
992 * Read a configuration from XML file
993 *
994 * If this is too slow, ConfigManager::readConfigDataFromBinary() and
995 * ConfigManager::writeConfigDataToBinary()can serialize CameraInfo object
996 * to the filesystem and construct CameraInfo instead; this was
997 * evaluated as 10x faster.
998 */
999 if (!cfgMgr->readConfigDataFromXML(path)) {
1000 return nullptr;
1001 } else {
1002 return cfgMgr;
1003 }
1004 }
1005
~CameraInfo()1006 ConfigManager::CameraInfo::~CameraInfo() {
1007 free_camera_metadata(characteristics);
1008
1009 for (auto&& [tag, val] : cameraMetadata) {
1010 switch (tag) {
1011 case ANDROID_LENS_DISTORTION:
1012 case ANDROID_LENS_POSE_ROTATION:
1013 case ANDROID_LENS_POSE_TRANSLATION:
1014 case ANDROID_LENS_INTRINSIC_CALIBRATION: {
1015 delete[] reinterpret_cast<float*>(val.first);
1016 break;
1017 }
1018
1019 case ANDROID_REQUEST_AVAILABLE_CAPABILITIES: {
1020 delete[] reinterpret_cast<
1021 camera_metadata_enum_android_request_available_capabilities_t*>(val.first);
1022 break;
1023 }
1024
1025 case ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS: {
1026 delete[] reinterpret_cast<char*>(val.first);
1027 break;
1028 }
1029
1030 default:
1031 LOG(WARNING) << "Tag " << std::hex << tag << " is not supported. "
1032 << "Data may be corrupted?";
1033 break;
1034 }
1035 }
1036 }
1037