xref: /aosp_15_r20/hardware/interfaces/automotive/evs/aidl/impl/default/src/ConfigManager.cpp (revision 4d7e907c777eeecc4c5bd7cf640a754fac206ff7)
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