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