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