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; "
616 << "data may be corrupted.";
617 break;
618 }
619 }
620
621 mCameraInfo.insert_or_assign(cameraId, std::move(aCamera));
622 }
623
624 /* read number of camera information entries */
625 const size_t ncams = *(reinterpret_cast<size_t*>(p));
626 p += sizeof(size_t);
627
628 /* read each camera information entry */
629 for (size_t cidx = 0; cidx < ncams; ++cidx) {
630 /* read camera identifier */
631 std::string cameraId = *(reinterpret_cast<std::string*>(p));
632 p += sizeof(std::string);
633
634 /* size of camera_metadata_t */
635 const size_t num_entry = *(reinterpret_cast<size_t*>(p));
636 p += sizeof(size_t);
637 const size_t num_data = *(reinterpret_cast<size_t*>(p));
638 p += sizeof(size_t);
639
640 /* create CameraInfo and add it to hash map */
641 std::unique_ptr<ConfigManager::CameraInfo> aCamera;
642 if (aCamera == nullptr || !aCamera->allocate(num_entry, num_data)) {
643 LOG(ERROR) << "Failed to create new CameraInfo object";
644 mCameraInfo.clear();
645 return false;
646 }
647
648 /* controls */
649 typedef struct {
650 CameraParam cid;
651 int32_t min;
652 int32_t max;
653 int32_t step;
654 } CameraCtrl;
655 sz = *(reinterpret_cast<size_t*>(p));
656 p += sizeof(size_t);
657 CameraCtrl* ptr = reinterpret_cast<CameraCtrl*>(p);
658 for (size_t idx = 0; idx < sz; ++idx) {
659 CameraCtrl temp = *ptr++;
660 aCamera->controls.insert_or_assign(temp.cid,
661 std::move(std::make_tuple(temp.min, temp.max,
662 temp.step)));
663 }
664 p = reinterpret_cast<char*>(ptr);
665
666 /* stream configurations */
667 sz = *(reinterpret_cast<size_t*>(p));
668 p += sizeof(size_t);
669 int32_t* i32_ptr = reinterpret_cast<int32_t*>(p);
670 for (size_t idx = 0; idx < sz; ++idx) {
671 const int32_t id = *i32_ptr++;
672
673 StreamConfiguration temp;
674 memcpy(&temp, i32_ptr, sizeof(StreamConfiguration));
675 i32_ptr += sizeof(StreamConfiguration);
676 aCamera->streamConfigurations.insert_or_assign(id, temp);
677 }
678 p = reinterpret_cast<char*>(i32_ptr);
679
680 for (size_t idx = 0; idx < num_entry; ++idx) {
681 /* Read camera metadata entries */
682 camera_metadata_tag_t tag = *reinterpret_cast<camera_metadata_tag_t*>(p);
683 p += sizeof(camera_metadata_tag_t);
684 const size_t count = *reinterpret_cast<size_t*>(p);
685 p += sizeof(size_t);
686
687 const int32_t type = get_camera_metadata_tag_type(tag);
688 switch (type) {
689 case TYPE_BYTE: {
690 add_camera_metadata_entry(aCamera->characteristics, tag, p, count);
691 p += count * sizeof(uint8_t);
692 break;
693 }
694 case TYPE_INT32: {
695 add_camera_metadata_entry(aCamera->characteristics, tag, p, count);
696 p += count * sizeof(int32_t);
697 break;
698 }
699 case TYPE_FLOAT: {
700 add_camera_metadata_entry(aCamera->characteristics, tag, p, count);
701 p += count * sizeof(float);
702 break;
703 }
704 case TYPE_INT64: {
705 add_camera_metadata_entry(aCamera->characteristics, tag, p, count);
706 p += count * sizeof(int64_t);
707 break;
708 }
709 case TYPE_DOUBLE: {
710 add_camera_metadata_entry(aCamera->characteristics, tag, p, count);
711 p += count * sizeof(double);
712 break;
713 }
714 case TYPE_RATIONAL:
715 p += count * sizeof(camera_metadata_rational_t);
716 break;
717 default:
718 LOG(WARNING) << "Type " << type << " is unknown; "
719 << "data may be corrupted.";
720 break;
721 }
722 }
723
724 mCameraInfo.insert_or_assign(cameraId, std::move(aCamera));
725 }
726
727 mIsReady = true;
728
729 /* notify that configuration data is ready */
730 lock.unlock();
731 mConfigCond.notify_all();
732
733 int64_t readEnd = android::elapsedRealtimeNano();
734 LOG(INFO) << __FUNCTION__ << " takes " << std::scientific
735 << (double)(readEnd - readStart) / 1000000.0 << " ms.";
736
737 return true;
738 }
739
writeConfigDataToBinary()740 bool ConfigManager::writeConfigDataToBinary() {
741 std::fstream outFile;
742
743 const int64_t writeStart = android::elapsedRealtimeNano();
744
745 outFile.open(mBinaryFilePath, std::fstream::out | std::fstream::binary);
746 if (!outFile) {
747 LOG(ERROR) << "Failed to open a destination binary file, " << mBinaryFilePath;
748 return false;
749 }
750
751 /* lock a configuration data while it's being written to the filesystem */
752 std::lock_guard<std::mutex> lock(mConfigLock);
753
754 /* write camera group information */
755 size_t sz = mCameraGroups.size();
756 outFile.write(reinterpret_cast<const char*>(&sz), sizeof(size_t));
757 for (auto&& [camId, camInfo] : mCameraGroups) {
758 LOG(INFO) << "Storing camera group " << camId;
759
760 /* write a camera identifier string */
761 outFile.write(reinterpret_cast<const char*>(&camId), sizeof(std::string));
762
763 /* controls */
764 sz = camInfo->controls.size();
765 outFile.write(reinterpret_cast<const char*>(&sz), sizeof(size_t));
766 for (auto&& [ctrl, range] : camInfo->controls) {
767 outFile.write(reinterpret_cast<const char*>(&ctrl), sizeof(CameraParam));
768 outFile.write(reinterpret_cast<const char*>(&std::get<0>(range)), sizeof(int32_t));
769 outFile.write(reinterpret_cast<const char*>(&std::get<1>(range)), sizeof(int32_t));
770 outFile.write(reinterpret_cast<const char*>(&std::get<2>(range)), sizeof(int32_t));
771 }
772
773 /* stream configurations */
774 sz = camInfo->streamConfigurations.size();
775 outFile.write(reinterpret_cast<const char*>(&sz), sizeof(size_t));
776 for (auto&& [sid, cfg] : camInfo->streamConfigurations) {
777 outFile.write(reinterpret_cast<const char*>(sid), sizeof(int32_t));
778 outFile.write(reinterpret_cast<const char*>(&cfg), sizeof(cfg));
779 }
780
781 /* synchronization */
782 outFile.write(reinterpret_cast<const char*>(&camInfo->synchronized), sizeof(int32_t));
783
784 /* size of camera_metadata_t */
785 size_t num_entry = 0;
786 size_t num_data = 0;
787 if (camInfo->characteristics != nullptr) {
788 num_entry = get_camera_metadata_entry_count(camInfo->characteristics);
789 num_data = get_camera_metadata_data_count(camInfo->characteristics);
790 }
791 outFile.write(reinterpret_cast<const char*>(&num_entry), sizeof(size_t));
792 outFile.write(reinterpret_cast<const char*>(&num_data), sizeof(size_t));
793
794 /* write each camera metadata entry */
795 if (num_entry > 0) {
796 camera_metadata_entry_t entry;
797 for (size_t idx = 0; idx < num_entry; ++idx) {
798 if (get_camera_metadata_entry(camInfo->characteristics, idx, &entry)) {
799 LOG(ERROR) << "Failed to retrieve camera metadata entry " << idx;
800 outFile.close();
801 return false;
802 }
803
804 outFile.write(reinterpret_cast<const char*>(&entry.tag), sizeof(entry.tag));
805 outFile.write(reinterpret_cast<const char*>(&entry.count), sizeof(entry.count));
806
807 int32_t type = get_camera_metadata_tag_type(entry.tag);
808 switch (type) {
809 case TYPE_BYTE:
810 outFile.write(reinterpret_cast<const char*>(entry.data.u8),
811 sizeof(uint8_t) * entry.count);
812 break;
813 case TYPE_INT32:
814 outFile.write(reinterpret_cast<const char*>(entry.data.i32),
815 sizeof(int32_t) * entry.count);
816 break;
817 case TYPE_FLOAT:
818 outFile.write(reinterpret_cast<const char*>(entry.data.f),
819 sizeof(float) * entry.count);
820 break;
821 case TYPE_INT64:
822 outFile.write(reinterpret_cast<const char*>(entry.data.i64),
823 sizeof(int64_t) * entry.count);
824 break;
825 case TYPE_DOUBLE:
826 outFile.write(reinterpret_cast<const char*>(entry.data.d),
827 sizeof(double) * entry.count);
828 break;
829 case TYPE_RATIONAL:
830 [[fallthrough]];
831 default:
832 LOG(WARNING) << "Type " << type << " is not supported.";
833 break;
834 }
835 }
836 }
837 }
838
839 /* write camera device information */
840 sz = mCameraInfo.size();
841 outFile.write(reinterpret_cast<const char*>(&sz), sizeof(size_t));
842 for (auto&& [camId, camInfo] : mCameraInfo) {
843 LOG(INFO) << "Storing camera " << camId;
844
845 /* write a camera identifier string */
846 outFile.write(reinterpret_cast<const char*>(&camId), sizeof(std::string));
847
848 /* controls */
849 sz = camInfo->controls.size();
850 outFile.write(reinterpret_cast<const char*>(&sz), sizeof(size_t));
851 for (auto& [ctrl, range] : camInfo->controls) {
852 outFile.write(reinterpret_cast<const char*>(&ctrl), sizeof(CameraParam));
853 outFile.write(reinterpret_cast<const char*>(&std::get<0>(range)), sizeof(int32_t));
854 outFile.write(reinterpret_cast<const char*>(&std::get<1>(range)), sizeof(int32_t));
855 outFile.write(reinterpret_cast<const char*>(&std::get<2>(range)), sizeof(int32_t));
856 }
857
858 /* stream configurations */
859 sz = camInfo->streamConfigurations.size();
860 outFile.write(reinterpret_cast<const char*>(&sz), sizeof(size_t));
861 for (auto&& [sid, cfg] : camInfo->streamConfigurations) {
862 outFile.write(reinterpret_cast<const char*>(sid), sizeof(int32_t));
863 outFile.write(reinterpret_cast<const char*>(&cfg), sizeof(cfg));
864 }
865
866 /* size of camera_metadata_t */
867 size_t num_entry = 0;
868 size_t num_data = 0;
869 if (camInfo->characteristics != nullptr) {
870 num_entry = get_camera_metadata_entry_count(camInfo->characteristics);
871 num_data = get_camera_metadata_data_count(camInfo->characteristics);
872 }
873 outFile.write(reinterpret_cast<const char*>(&num_entry), sizeof(size_t));
874 outFile.write(reinterpret_cast<const char*>(&num_data), sizeof(size_t));
875
876 /* write each camera metadata entry */
877 if (num_entry > 0) {
878 camera_metadata_entry_t entry;
879 for (size_t idx = 0; idx < num_entry; ++idx) {
880 if (get_camera_metadata_entry(camInfo->characteristics, idx, &entry)) {
881 LOG(ERROR) << "Failed to retrieve camera metadata entry " << idx;
882 outFile.close();
883 return false;
884 }
885
886 outFile.write(reinterpret_cast<const char*>(&entry.tag), sizeof(entry.tag));
887 outFile.write(reinterpret_cast<const char*>(&entry.count), sizeof(entry.count));
888
889 int32_t type = get_camera_metadata_tag_type(entry.tag);
890 switch (type) {
891 case TYPE_BYTE:
892 outFile.write(reinterpret_cast<const char*>(entry.data.u8),
893 sizeof(uint8_t) * entry.count);
894 break;
895 case TYPE_INT32:
896 outFile.write(reinterpret_cast<const char*>(entry.data.i32),
897 sizeof(int32_t) * entry.count);
898 break;
899 case TYPE_FLOAT:
900 outFile.write(reinterpret_cast<const char*>(entry.data.f),
901 sizeof(float) * entry.count);
902 break;
903 case TYPE_INT64:
904 outFile.write(reinterpret_cast<const char*>(entry.data.i64),
905 sizeof(int64_t) * entry.count);
906 break;
907 case TYPE_DOUBLE:
908 outFile.write(reinterpret_cast<const char*>(entry.data.d),
909 sizeof(double) * entry.count);
910 break;
911 case TYPE_RATIONAL:
912 [[fallthrough]];
913 default:
914 LOG(WARNING) << "Type " << type << " is not supported.";
915 break;
916 }
917 }
918 }
919 }
920
921 outFile.close();
922 int64_t writeEnd = android::elapsedRealtimeNano();
923 LOG(INFO) << __FUNCTION__ << " takes " << std::scientific
924 << (double)(writeEnd - writeStart) / 1000000.0 << " ms.";
925
926 return true;
927 }
928
Create()929 std::unique_ptr<ConfigManager> ConfigManager::Create() {
930 std::unique_ptr<ConfigManager> cfgMgr(new ConfigManager());
931
932 /*
933 * Read a configuration from XML file
934 *
935 * If this is too slow, ConfigManager::readConfigDataFromBinary() and
936 * ConfigManager::writeConfigDataToBinary()can serialize CameraInfo object
937 * to the filesystem and construct CameraInfo instead; this was
938 * evaluated as 10x faster.
939 */
940 if (!cfgMgr->readConfigDataFromXML()) {
941 return nullptr;
942 } else {
943 return cfgMgr;
944 }
945 }
946
~CameraInfo()947 ConfigManager::CameraInfo::~CameraInfo() {
948 free_camera_metadata(characteristics);
949
950 for (auto&& [tag, val] : cameraMetadata) {
951 switch (tag) {
952 case ANDROID_LENS_DISTORTION:
953 case ANDROID_LENS_POSE_ROTATION:
954 case ANDROID_LENS_POSE_TRANSLATION:
955 case ANDROID_LENS_INTRINSIC_CALIBRATION: {
956 delete[] reinterpret_cast<float*>(val.first);
957 break;
958 }
959
960 case ANDROID_REQUEST_AVAILABLE_CAPABILITIES: {
961 delete[] reinterpret_cast<
962 camera_metadata_enum_android_request_available_capabilities_t*>(val.first);
963 break;
964 }
965
966 case ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS: {
967 delete[] reinterpret_cast<char*>(val.first);
968 break;
969 }
970
971 default:
972 LOG(WARNING) << "Tag " << std::hex << tag << " is not supported. "
973 << "Data may be corrupted?";
974 break;
975 }
976 }
977 }
978