1 /*
2 * Copyright (C) 2022 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 <hardware/gralloc.h>
20 #include <utils/SystemClock.h>
21
22 #include <fstream>
23 #include <sstream>
24 #include <string_view>
25 #include <thread>
26
27 namespace {
28
29 using ::aidl::android::hardware::automotive::evs::CameraParam;
30 using ::aidl::android::hardware::graphics::common::PixelFormat;
31 using ::tinyxml2::XMLAttribute;
32 using ::tinyxml2::XMLDocument;
33 using ::tinyxml2::XMLElement;
34
35 } // namespace
36
37 std::string_view ConfigManager::sConfigDefaultPath =
38 "/vendor/etc/automotive/evs/evs_aidl_hal_configuration.xml";
39 std::string_view ConfigManager::sConfigOverridePath =
40 "/vendor/etc/automotive/evs/evs_configuration_override.xml";
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 (!std::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].insert(std::move(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 const int32_t minVal = std::stoi(ctrlElem->FindAttribute("min")->Value());
167 const int32_t maxVal = std::stoi(ctrlElem->FindAttribute("max")->Value());
168
169 int32_t stepVal = 1;
170 const XMLAttribute* stepAttr = ctrlElem->FindAttribute("step");
171 if (stepAttr != nullptr) {
172 stepVal = std::stoi(stepAttr->Value());
173 }
174
175 CameraParam aParam;
176 if (ConfigManagerUtil::convertToEvsCameraParam(nameAttr, aParam)) {
177 aCamera->controls.insert_or_assign(aParam,
178 std::move(std::make_tuple(minVal, maxVal,
179 stepVal)));
180 }
181
182 ctrlElem = ctrlElem->NextSiblingElement("control");
183 }
184 }
185
186 /* a list of camera stream configurations */
187 curElem = aCapElem->FirstChildElement("stream");
188 while (curElem != nullptr) {
189 /* read 5 attributes */
190 const XMLAttribute* idAttr = curElem->FindAttribute("id");
191 const XMLAttribute* widthAttr = curElem->FindAttribute("width");
192 const XMLAttribute* heightAttr = curElem->FindAttribute("height");
193 const XMLAttribute* fmtAttr = curElem->FindAttribute("format");
194 const XMLAttribute* fpsAttr = curElem->FindAttribute("framerate");
195
196 const int32_t id = std::stoi(idAttr->Value());
197 int32_t framerate = 0;
198 if (fpsAttr != nullptr) {
199 framerate = std::stoi(fpsAttr->Value());
200 }
201
202 PixelFormat format = PixelFormat::UNSPECIFIED;
203 if (ConfigManagerUtil::convertToPixelFormat(fmtAttr->Value(), format)) {
204 StreamConfiguration cfg = {
205 .id = id,
206 .width = std::stoi(widthAttr->Value()),
207 .height = std::stoi(heightAttr->Value()),
208 .format = format,
209 .type = ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
210 .framerate = framerate,
211 };
212 aCamera->streamConfigurations.insert_or_assign(id, cfg);
213 }
214
215 curElem = curElem->NextSiblingElement("stream");
216 }
217
218 dataSize = calculate_camera_metadata_entry_data_size(
219 get_camera_metadata_tag_type(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS),
220 aCamera->streamConfigurations.size() * sizeof(StreamConfiguration));
221
222 /* a single camera metadata entry contains multiple stream configurations */
223 return dataSize > 0 ? 1 : 0;
224 }
225
readCameraMetadata(const XMLElement * const aParamElem,CameraInfo * aCamera,size_t & dataSize)226 size_t ConfigManager::readCameraMetadata(const XMLElement* const aParamElem, CameraInfo* aCamera,
227 size_t& dataSize) {
228 if (aParamElem == nullptr || aCamera == nullptr) {
229 return 0;
230 }
231
232 const XMLElement* curElem = aParamElem->FirstChildElement("parameter");
233 size_t numEntries = 0;
234 camera_metadata_tag_t tag;
235 while (curElem != nullptr) {
236 if (ConfigManagerUtil::convertToMetadataTag(curElem->FindAttribute("name")->Value(), tag)) {
237 switch (tag) {
238 case ANDROID_LENS_DISTORTION:
239 case ANDROID_LENS_POSE_ROTATION:
240 case ANDROID_LENS_POSE_TRANSLATION:
241 case ANDROID_LENS_INTRINSIC_CALIBRATION: {
242 /* float[] */
243 size_t count = 0;
244 void* data =
245 ConfigManagerUtil::convertFloatArray(curElem->FindAttribute("size")
246 ->Value(),
247 curElem->FindAttribute("value")
248 ->Value(),
249 count);
250
251 aCamera->cameraMetadata.insert_or_assign(tag, std::make_pair(data, count));
252
253 ++numEntries;
254 dataSize +=
255 calculate_camera_metadata_entry_data_size(get_camera_metadata_tag_type(
256 tag),
257 count);
258
259 break;
260 }
261
262 case ANDROID_REQUEST_AVAILABLE_CAPABILITIES: {
263 camera_metadata_enum_android_request_available_capabilities_t* data =
264 new camera_metadata_enum_android_request_available_capabilities_t[1];
265 if (ConfigManagerUtil::convertToCameraCapability(curElem->FindAttribute("value")
266 ->Value(),
267 *data)) {
268 aCamera->cameraMetadata.insert_or_assign(tag,
269 std::make_pair((void*)data, 1));
270
271 ++numEntries;
272 dataSize += calculate_camera_metadata_entry_data_size(
273 get_camera_metadata_tag_type(tag), 1);
274 }
275 break;
276 }
277
278 case ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS: {
279 /* a comma-separated list of physical camera devices */
280 size_t len = strlen(curElem->FindAttribute("value")->Value());
281 char* data = new char[len + 1];
282 memcpy(data, curElem->FindAttribute("value")->Value(), len * sizeof(char));
283
284 /* replace commas with null char */
285 char* p = data;
286 while (*p != '\0') {
287 if (*p == ',') {
288 *p = '\0';
289 }
290 ++p;
291 }
292
293 aCamera->cameraMetadata.insert_or_assign(tag,
294 std::make_pair((void*)data, len + 1));
295
296 ++numEntries;
297 dataSize +=
298 calculate_camera_metadata_entry_data_size(get_camera_metadata_tag_type(
299 tag),
300 len);
301 break;
302 }
303
304 /* TODO(b/140416878): add vendor-defined/custom tag support */
305 default:
306 LOG(WARNING) << "Parameter " << curElem->FindAttribute("name")->Value()
307 << " is not supported";
308 break;
309 }
310 } else {
311 LOG(WARNING) << "Unsupported metadata tag " << curElem->FindAttribute("name")->Value()
312 << " is found.";
313 }
314
315 curElem = curElem->NextSiblingElement("parameter");
316 }
317
318 return numEntries;
319 }
320
constructCameraMetadata(CameraInfo * aCamera,size_t totalEntries,size_t totalDataSize)321 bool ConfigManager::constructCameraMetadata(CameraInfo* aCamera, size_t totalEntries,
322 size_t totalDataSize) {
323 if (aCamera == nullptr || !aCamera->allocate(totalEntries, totalDataSize)) {
324 LOG(ERROR) << "Failed to allocate memory for camera metadata";
325 return false;
326 }
327
328 const size_t numStreamConfigs = aCamera->streamConfigurations.size();
329 std::unique_ptr<int32_t[]> data(new int32_t[sizeof(StreamConfiguration) * numStreamConfigs]);
330 int32_t* ptr = data.get();
331 for (auto& cfg : aCamera->streamConfigurations) {
332 memcpy(ptr, &cfg.second, sizeof(StreamConfiguration));
333 ptr += sizeof(StreamConfiguration);
334 }
335 int32_t err =
336 add_camera_metadata_entry(aCamera->characteristics,
337 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, data.get(),
338 numStreamConfigs * sizeof(StreamConfiguration));
339
340 if (err) {
341 LOG(ERROR) << "Failed to add stream configurations to metadata, ignored";
342 return false;
343 }
344
345 bool success = true;
346 for (auto& [tag, entry] : aCamera->cameraMetadata) {
347 /* try to add new camera metadata entry */
348 int32_t err =
349 add_camera_metadata_entry(aCamera->characteristics, tag, entry.first, entry.second);
350 if (err) {
351 LOG(ERROR) << "Failed to add an entry with a tag, " << std::hex << tag;
352
353 /* may exceed preallocated capacity */
354 LOG(ERROR) << "Camera metadata has "
355 << get_camera_metadata_entry_count(aCamera->characteristics) << " / "
356 << get_camera_metadata_entry_capacity(aCamera->characteristics)
357 << " entries and "
358 << get_camera_metadata_data_count(aCamera->characteristics) << " / "
359 << get_camera_metadata_data_capacity(aCamera->characteristics)
360 << " bytes are filled.";
361 LOG(ERROR) << "\tCurrent metadata entry requires "
362 << calculate_camera_metadata_entry_data_size(tag, entry.second) << " bytes.";
363
364 success = false;
365 }
366 }
367
368 LOG(VERBOSE) << "Camera metadata has "
369 << get_camera_metadata_entry_count(aCamera->characteristics) << " / "
370 << get_camera_metadata_entry_capacity(aCamera->characteristics) << " entries and "
371 << get_camera_metadata_data_count(aCamera->characteristics) << " / "
372 << get_camera_metadata_data_capacity(aCamera->characteristics)
373 << " bytes are filled.";
374 return success;
375 }
376
readSystemInfo(const XMLElement * const aSysElem)377 void ConfigManager::readSystemInfo(const XMLElement* const aSysElem) {
378 if (aSysElem == nullptr) {
379 return;
380 }
381
382 /*
383 * Please note that this function assumes that a given system XML element
384 * and its child elements follow DTD. If it does not, it will cause a
385 * segmentation fault due to the failure of finding expected attributes.
386 */
387
388 /* read number of cameras available in the system */
389 const XMLElement* xmlElem = aSysElem->FirstChildElement("num_cameras");
390 if (xmlElem != nullptr) {
391 mSystemInfo.numCameras = std::stoi(xmlElem->FindAttribute("value")->Value());
392 }
393 }
394
readDisplayInfo(const XMLElement * const aDisplayElem)395 void ConfigManager::readDisplayInfo(const XMLElement* const aDisplayElem) {
396 if (aDisplayElem == nullptr) {
397 LOG(WARNING) << "XML file does not have required camera element";
398 return;
399 }
400
401 const XMLElement* curDev = aDisplayElem->FirstChildElement("device");
402 while (curDev != nullptr) {
403 const char* id = curDev->FindAttribute("id")->Value();
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 PixelFormat format = PixelFormat::UNSPECIFIED;
422 if (ConfigManagerUtil::convertToPixelFormat(fmtAttr->Value(), format)) {
423 StreamConfiguration cfg = {
424 .id = id,
425 .width = std::stoi(widthAttr->Value()),
426 .height = std::stoi(heightAttr->Value()),
427 .format = format,
428 .type = ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT,
429 };
430 dpy->streamConfigurations.insert_or_assign(id, cfg);
431 }
432
433 curStream = curStream->NextSiblingElement("stream");
434 }
435 }
436
437 mDisplayInfo.insert_or_assign(id, std::move(dpy));
438 curDev = curDev->NextSiblingElement("device");
439 }
440
441 return;
442 }
443
readConfigDataFromXML()444 bool ConfigManager::readConfigDataFromXML() noexcept {
445 XMLDocument xmlDoc;
446
447 const int64_t parsingStart = android::elapsedRealtimeNano();
448
449 /* load and parse a configuration file */
450 xmlDoc.LoadFile(sConfigOverridePath.data());
451 if (xmlDoc.ErrorID() != tinyxml2::XML_SUCCESS) {
452 xmlDoc.LoadFile(sConfigDefaultPath.data());
453 if (xmlDoc.ErrorID() != tinyxml2::XML_SUCCESS) {
454 LOG(ERROR) << "Failed to load and/or parse a configuration file, " << xmlDoc.ErrorStr();
455 return false;
456 }
457 }
458
459 /* retrieve the root element */
460 const XMLElement* rootElem = xmlDoc.RootElement();
461 if (std::strcmp(rootElem->Name(), "configuration")) {
462 LOG(ERROR) << "A configuration file is not in the required format. "
463 << "See /etc/automotive/evs/evs_configuration.dtd";
464 return false;
465 }
466
467 std::unique_lock<std::mutex> lock(mConfigLock);
468
469 /*
470 * parse camera information; this needs to be done before reading system
471 * information
472 */
473 readCameraInfo(rootElem->FirstChildElement("camera"));
474
475 /* parse system information */
476 readSystemInfo(rootElem->FirstChildElement("system"));
477
478 /* parse display information */
479 readDisplayInfo(rootElem->FirstChildElement("display"));
480
481 /* configuration data is ready to be consumed */
482 mIsReady = true;
483
484 /* notify that configuration data is ready */
485 lock.unlock();
486 mConfigCond.notify_all();
487
488 const int64_t parsingEnd = android::elapsedRealtimeNano();
489 LOG(INFO) << "Parsing configuration file takes " << std::scientific
490 << (double)(parsingEnd - parsingStart) / 1000000.0 << " ms.";
491
492 return true;
493 }
494
readConfigDataFromBinary()495 bool ConfigManager::readConfigDataFromBinary() {
496 /* Temporary buffer to hold configuration data read from a binary file */
497 char mBuffer[1024];
498
499 std::fstream srcFile;
500 const int64_t readStart = android::elapsedRealtimeNano();
501
502 srcFile.open(mBinaryFilePath, std::fstream::in | std::fstream::binary);
503 if (!srcFile) {
504 LOG(ERROR) << "Failed to open a source binary file, " << mBinaryFilePath;
505 return false;
506 }
507
508 std::unique_lock<std::mutex> lock(mConfigLock);
509 mIsReady = false;
510
511 /* read configuration data into the internal buffer */
512 srcFile.read(mBuffer, sizeof(mBuffer));
513 LOG(VERBOSE) << __FUNCTION__ << ": " << srcFile.gcount() << " bytes are read.";
514 char* p = mBuffer;
515 size_t sz = 0;
516
517 /* read number of camera group information entries */
518 const size_t ngrps = *(reinterpret_cast<size_t*>(p));
519 p += sizeof(size_t);
520
521 /* read each camera information entry */
522 for (size_t cidx = 0; cidx < ngrps; ++cidx) {
523 /* read camera identifier */
524 std::string cameraId = *(reinterpret_cast<std::string*>(p));
525 p += sizeof(std::string);
526
527 /* size of camera_metadata_t */
528 const size_t num_entry = *(reinterpret_cast<size_t*>(p));
529 p += sizeof(size_t);
530 const size_t num_data = *(reinterpret_cast<size_t*>(p));
531 p += sizeof(size_t);
532
533 /* create CameraInfo and add it to hash map */
534 std::unique_ptr<ConfigManager::CameraGroupInfo> aCamera;
535 if (aCamera == nullptr || !aCamera->allocate(num_entry, num_data)) {
536 LOG(ERROR) << "Failed to create new CameraInfo object";
537 mCameraInfo.clear();
538 return false;
539 }
540
541 /* controls */
542 typedef struct {
543 CameraParam cid;
544 int32_t min;
545 int32_t max;
546 int32_t step;
547 } CameraCtrl;
548 sz = *(reinterpret_cast<size_t*>(p));
549 p += sizeof(size_t);
550 CameraCtrl* ptr = reinterpret_cast<CameraCtrl*>(p);
551 for (size_t idx = 0; idx < sz; ++idx) {
552 CameraCtrl temp = *ptr++;
553 aCamera->controls.insert_or_assign(temp.cid,
554 std::move(std::make_tuple(temp.min, temp.max,
555 temp.step)));
556 }
557 p = reinterpret_cast<char*>(ptr);
558
559 /* stream configurations */
560 sz = *(reinterpret_cast<size_t*>(p));
561 p += sizeof(size_t);
562 int32_t* i32_ptr = reinterpret_cast<int32_t*>(p);
563 for (size_t idx = 0; idx < sz; ++idx) {
564 const int32_t id = *i32_ptr++;
565
566 StreamConfiguration temp;
567 memcpy(&temp, i32_ptr, sizeof(StreamConfiguration));
568 i32_ptr += sizeof(StreamConfiguration);
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 (size_t 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 const size_t count = *reinterpret_cast<size_t*>(p);
582 p += sizeof(size_t);
583
584 const 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 const size_t ncams = *(reinterpret_cast<size_t*>(p));
625 p += sizeof(size_t);
626
627 /* read each camera information entry */
628 for (size_t 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 const size_t num_entry = *(reinterpret_cast<size_t*>(p));
635 p += sizeof(size_t);
636 const 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 (size_t idx = 0; idx < sz; ++idx) {
658 CameraCtrl temp = *ptr++;
659 aCamera->controls.insert_or_assign(temp.cid,
660 std::move(std::make_tuple(temp.min, temp.max,
661 temp.step)));
662 }
663 p = reinterpret_cast<char*>(ptr);
664
665 /* stream configurations */
666 sz = *(reinterpret_cast<size_t*>(p));
667 p += sizeof(size_t);
668 int32_t* i32_ptr = reinterpret_cast<int32_t*>(p);
669 for (size_t idx = 0; idx < sz; ++idx) {
670 const int32_t id = *i32_ptr++;
671
672 StreamConfiguration temp;
673 memcpy(&temp, i32_ptr, sizeof(StreamConfiguration));
674 i32_ptr += sizeof(StreamConfiguration);
675 aCamera->streamConfigurations.insert_or_assign(id, temp);
676 }
677 p = reinterpret_cast<char*>(i32_ptr);
678
679 for (size_t idx = 0; idx < num_entry; ++idx) {
680 /* Read camera metadata entries */
681 camera_metadata_tag_t tag = *reinterpret_cast<camera_metadata_tag_t*>(p);
682 p += sizeof(camera_metadata_tag_t);
683 const size_t count = *reinterpret_cast<size_t*>(p);
684 p += sizeof(size_t);
685
686 const int32_t type = get_camera_metadata_tag_type(tag);
687 switch (type) {
688 case TYPE_BYTE: {
689 add_camera_metadata_entry(aCamera->characteristics, tag, p, count);
690 p += count * sizeof(uint8_t);
691 break;
692 }
693 case TYPE_INT32: {
694 add_camera_metadata_entry(aCamera->characteristics, tag, p, count);
695 p += count * sizeof(int32_t);
696 break;
697 }
698 case TYPE_FLOAT: {
699 add_camera_metadata_entry(aCamera->characteristics, tag, p, count);
700 p += count * sizeof(float);
701 break;
702 }
703 case TYPE_INT64: {
704 add_camera_metadata_entry(aCamera->characteristics, tag, p, count);
705 p += count * sizeof(int64_t);
706 break;
707 }
708 case TYPE_DOUBLE: {
709 add_camera_metadata_entry(aCamera->characteristics, tag, p, count);
710 p += count * sizeof(double);
711 break;
712 }
713 case TYPE_RATIONAL:
714 p += count * sizeof(camera_metadata_rational_t);
715 break;
716 default:
717 LOG(WARNING) << "Type " << type << " is unknown; " << "data may be corrupted.";
718 break;
719 }
720 }
721
722 mCameraInfo.insert_or_assign(cameraId, std::move(aCamera));
723 }
724
725 mIsReady = true;
726
727 /* notify that configuration data is ready */
728 lock.unlock();
729 mConfigCond.notify_all();
730
731 int64_t readEnd = android::elapsedRealtimeNano();
732 LOG(INFO) << __FUNCTION__ << " takes " << std::scientific
733 << (double)(readEnd - readStart) / 1000000.0 << " ms.";
734
735 return true;
736 }
737
writeConfigDataToBinary()738 bool ConfigManager::writeConfigDataToBinary() {
739 std::fstream outFile;
740
741 const int64_t writeStart = android::elapsedRealtimeNano();
742
743 outFile.open(mBinaryFilePath, std::fstream::out | std::fstream::binary);
744 if (!outFile) {
745 LOG(ERROR) << "Failed to open a destination binary file, " << mBinaryFilePath;
746 return false;
747 }
748
749 /* lock a configuration data while it's being written to the filesystem */
750 std::lock_guard<std::mutex> lock(mConfigLock);
751
752 /* write camera group information */
753 size_t sz = mCameraGroups.size();
754 outFile.write(reinterpret_cast<const char*>(&sz), sizeof(size_t));
755 for (auto&& [camId, camInfo] : mCameraGroups) {
756 LOG(INFO) << "Storing camera group " << camId;
757
758 /* write a camera identifier string */
759 outFile.write(reinterpret_cast<const char*>(&camId), sizeof(std::string));
760
761 /* controls */
762 sz = camInfo->controls.size();
763 outFile.write(reinterpret_cast<const char*>(&sz), sizeof(size_t));
764 for (auto&& [ctrl, range] : camInfo->controls) {
765 outFile.write(reinterpret_cast<const char*>(&ctrl), sizeof(CameraParam));
766 outFile.write(reinterpret_cast<const char*>(&std::get<0>(range)), sizeof(int32_t));
767 outFile.write(reinterpret_cast<const char*>(&std::get<1>(range)), sizeof(int32_t));
768 outFile.write(reinterpret_cast<const char*>(&std::get<2>(range)), sizeof(int32_t));
769 }
770
771 /* stream configurations */
772 sz = camInfo->streamConfigurations.size();
773 outFile.write(reinterpret_cast<const char*>(&sz), sizeof(size_t));
774 for (auto&& [sid, cfg] : camInfo->streamConfigurations) {
775 outFile.write(reinterpret_cast<const char*>(sid), sizeof(int32_t));
776 outFile.write(reinterpret_cast<const char*>(&cfg), sizeof(cfg));
777 }
778
779 /* synchronization */
780 outFile.write(reinterpret_cast<const char*>(&camInfo->synchronized), sizeof(int32_t));
781
782 /* size of camera_metadata_t */
783 size_t num_entry = 0;
784 size_t num_data = 0;
785 if (camInfo->characteristics != nullptr) {
786 num_entry = get_camera_metadata_entry_count(camInfo->characteristics);
787 num_data = get_camera_metadata_data_count(camInfo->characteristics);
788 }
789 outFile.write(reinterpret_cast<const char*>(&num_entry), sizeof(size_t));
790 outFile.write(reinterpret_cast<const char*>(&num_data), sizeof(size_t));
791
792 /* write each camera metadata entry */
793 if (num_entry > 0) {
794 camera_metadata_entry_t entry;
795 for (size_t idx = 0; idx < num_entry; ++idx) {
796 if (get_camera_metadata_entry(camInfo->characteristics, idx, &entry)) {
797 LOG(ERROR) << "Failed to retrieve camera metadata entry " << idx;
798 outFile.close();
799 return false;
800 }
801
802 outFile.write(reinterpret_cast<const char*>(&entry.tag), sizeof(entry.tag));
803 outFile.write(reinterpret_cast<const char*>(&entry.count), sizeof(entry.count));
804
805 int32_t type = get_camera_metadata_tag_type(entry.tag);
806 switch (type) {
807 case TYPE_BYTE:
808 outFile.write(reinterpret_cast<const char*>(entry.data.u8),
809 sizeof(uint8_t) * entry.count);
810 break;
811 case TYPE_INT32:
812 outFile.write(reinterpret_cast<const char*>(entry.data.i32),
813 sizeof(int32_t) * entry.count);
814 break;
815 case TYPE_FLOAT:
816 outFile.write(reinterpret_cast<const char*>(entry.data.f),
817 sizeof(float) * entry.count);
818 break;
819 case TYPE_INT64:
820 outFile.write(reinterpret_cast<const char*>(entry.data.i64),
821 sizeof(int64_t) * entry.count);
822 break;
823 case TYPE_DOUBLE:
824 outFile.write(reinterpret_cast<const char*>(entry.data.d),
825 sizeof(double) * entry.count);
826 break;
827 case TYPE_RATIONAL:
828 [[fallthrough]];
829 default:
830 LOG(WARNING) << "Type " << type << " is not supported.";
831 break;
832 }
833 }
834 }
835 }
836
837 /* write camera device information */
838 sz = mCameraInfo.size();
839 outFile.write(reinterpret_cast<const char*>(&sz), sizeof(size_t));
840 for (auto&& [camId, camInfo] : mCameraInfo) {
841 LOG(INFO) << "Storing camera " << camId;
842
843 /* write a camera identifier string */
844 outFile.write(reinterpret_cast<const char*>(&camId), sizeof(std::string));
845
846 /* controls */
847 sz = camInfo->controls.size();
848 outFile.write(reinterpret_cast<const char*>(&sz), sizeof(size_t));
849 for (auto& [ctrl, range] : camInfo->controls) {
850 outFile.write(reinterpret_cast<const char*>(&ctrl), sizeof(CameraParam));
851 outFile.write(reinterpret_cast<const char*>(&std::get<0>(range)), sizeof(int32_t));
852 outFile.write(reinterpret_cast<const char*>(&std::get<1>(range)), sizeof(int32_t));
853 outFile.write(reinterpret_cast<const char*>(&std::get<2>(range)), sizeof(int32_t));
854 }
855
856 /* stream configurations */
857 sz = camInfo->streamConfigurations.size();
858 outFile.write(reinterpret_cast<const char*>(&sz), sizeof(size_t));
859 for (auto&& [sid, cfg] : camInfo->streamConfigurations) {
860 outFile.write(reinterpret_cast<const char*>(sid), sizeof(int32_t));
861 outFile.write(reinterpret_cast<const char*>(&cfg), sizeof(cfg));
862 }
863
864 /* size of camera_metadata_t */
865 size_t num_entry = 0;
866 size_t num_data = 0;
867 if (camInfo->characteristics != nullptr) {
868 num_entry = get_camera_metadata_entry_count(camInfo->characteristics);
869 num_data = get_camera_metadata_data_count(camInfo->characteristics);
870 }
871 outFile.write(reinterpret_cast<const char*>(&num_entry), sizeof(size_t));
872 outFile.write(reinterpret_cast<const char*>(&num_data), sizeof(size_t));
873
874 /* write each camera metadata entry */
875 if (num_entry > 0) {
876 camera_metadata_entry_t entry;
877 for (size_t idx = 0; idx < num_entry; ++idx) {
878 if (get_camera_metadata_entry(camInfo->characteristics, idx, &entry)) {
879 LOG(ERROR) << "Failed to retrieve camera metadata entry " << idx;
880 outFile.close();
881 return false;
882 }
883
884 outFile.write(reinterpret_cast<const char*>(&entry.tag), sizeof(entry.tag));
885 outFile.write(reinterpret_cast<const char*>(&entry.count), sizeof(entry.count));
886
887 int32_t type = get_camera_metadata_tag_type(entry.tag);
888 switch (type) {
889 case TYPE_BYTE:
890 outFile.write(reinterpret_cast<const char*>(entry.data.u8),
891 sizeof(uint8_t) * entry.count);
892 break;
893 case TYPE_INT32:
894 outFile.write(reinterpret_cast<const char*>(entry.data.i32),
895 sizeof(int32_t) * entry.count);
896 break;
897 case TYPE_FLOAT:
898 outFile.write(reinterpret_cast<const char*>(entry.data.f),
899 sizeof(float) * entry.count);
900 break;
901 case TYPE_INT64:
902 outFile.write(reinterpret_cast<const char*>(entry.data.i64),
903 sizeof(int64_t) * entry.count);
904 break;
905 case TYPE_DOUBLE:
906 outFile.write(reinterpret_cast<const char*>(entry.data.d),
907 sizeof(double) * entry.count);
908 break;
909 case TYPE_RATIONAL:
910 [[fallthrough]];
911 default:
912 LOG(WARNING) << "Type " << type << " is not supported.";
913 break;
914 }
915 }
916 }
917 }
918
919 outFile.close();
920 int64_t writeEnd = android::elapsedRealtimeNano();
921 LOG(INFO) << __FUNCTION__ << " takes " << std::scientific
922 << (double)(writeEnd - writeStart) / 1000000.0 << " ms.";
923
924 return true;
925 }
926
Create()927 std::unique_ptr<ConfigManager> ConfigManager::Create() {
928 std::unique_ptr<ConfigManager> cfgMgr(new ConfigManager());
929
930 /*
931 * Read a configuration from XML file
932 *
933 * If this is too slow, ConfigManager::readConfigDataFromBinary() and
934 * ConfigManager::writeConfigDataToBinary()can serialize CameraInfo object
935 * to the filesystem and construct CameraInfo instead; this was
936 * evaluated as 10x faster.
937 */
938 if (!cfgMgr->readConfigDataFromXML()) {
939 return nullptr;
940 } else {
941 return cfgMgr;
942 }
943 }
944
~CameraInfo()945 ConfigManager::CameraInfo::~CameraInfo() {
946 free_camera_metadata(characteristics);
947
948 for (auto&& [tag, val] : cameraMetadata) {
949 switch (tag) {
950 case ANDROID_LENS_DISTORTION:
951 case ANDROID_LENS_POSE_ROTATION:
952 case ANDROID_LENS_POSE_TRANSLATION:
953 case ANDROID_LENS_INTRINSIC_CALIBRATION: {
954 delete[] reinterpret_cast<float*>(val.first);
955 break;
956 }
957
958 case ANDROID_REQUEST_AVAILABLE_CAPABILITIES: {
959 delete[] reinterpret_cast<
960 camera_metadata_enum_android_request_available_capabilities_t*>(val.first);
961 break;
962 }
963
964 case ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS: {
965 delete[] reinterpret_cast<char*>(val.first);
966 break;
967 }
968
969 default:
970 LOG(WARNING) << "Tag " << std::hex << tag << " is not supported. "
971 << "Data may be corrupted?";
972 break;
973 }
974 }
975 }
976