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