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