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