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