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