blob: 4f46f9dbca9fba788b2d39e0959d914aea12b797 [file] [log] [blame]
Changyeon Joc6fa0ab2019-10-12 05:25:44 -07001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <sstream>
18#include <fstream>
19#include <thread>
20
21#include <hardware/gralloc.h>
22#include <utils/SystemClock.h>
23#include <android/hardware/camera/device/3.2/ICameraDevice.h>
24
25#include "ConfigManager.h"
26
27using ::android::hardware::camera::device::V3_2::StreamRotation;
28
29
30ConfigManager::~ConfigManager() {
31 /* Nothing to do */
32}
33
34
35void ConfigManager::readCameraInfo(const XMLElement * const aCameraElem) {
36 if (aCameraElem == nullptr) {
37 ALOGW("XML file does not have required camera element");
38 return;
39 }
40
41 const XMLElement *curElem = aCameraElem->FirstChildElement();
42 while (curElem != nullptr) {
43 if (!strcmp(curElem->Name(), "group")) {
44 /* camera group identifier */
45 const char *group_id = curElem->FindAttribute("group_id")->Value();
46
47 /* create CameraGroup */
48 unique_ptr<ConfigManager::CameraGroup> aCameraGroup(new ConfigManager::CameraGroup());
49
50 /* add a camera device to its group */
51 addCameraDevices(curElem->FindAttribute("device_id")->Value(), aCameraGroup);
52
53 /* a list of camera stream configurations */
54 const XMLElement *childElem =
55 curElem->FirstChildElement("caps")->FirstChildElement("stream");
56 while (childElem != nullptr) {
57 /* read 5 attributes */
58 const XMLAttribute *idAttr = childElem->FindAttribute("id");
59 const XMLAttribute *widthAttr = childElem->FindAttribute("width");
60 const XMLAttribute *heightAttr = childElem->FindAttribute("height");
61 const XMLAttribute *fmtAttr = childElem->FindAttribute("format");
62 const XMLAttribute *fpsAttr = childElem->FindAttribute("framerate");
63
64 const int32_t id = stoi(idAttr->Value());
65 int32_t framerate = 0;
66 if (fpsAttr != nullptr) {
67 framerate = stoi(fpsAttr->Value());
68 }
69
70 int32_t pixFormat;
71 if (ConfigManagerUtil::convertToPixelFormat(fmtAttr->Value(),
72 pixFormat)) {
73 RawStreamConfiguration cfg = {
74 id,
75 stoi(widthAttr->Value()),
76 stoi(heightAttr->Value()),
77 pixFormat,
78 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
79 framerate
80 };
81 aCameraGroup->streamConfigurations[id] = cfg;
82 }
83
84 childElem = childElem->NextSiblingElement("stream");
85 }
86
87 /* camera group synchronization */
88 const char *sync = curElem->FindAttribute("synchronized")->Value();
89 aCameraGroup->synchronized =
90 static_cast<bool>(strcmp(sync, "false"));
91
92 /* add a group to hash map */
93 mCameraGroups[group_id] = std::move(aCameraGroup);
94 } else if (!strcmp(curElem->Name(), "device")) {
95 /* camera unique identifier */
96 const char *id = curElem->FindAttribute("id")->Value();
97
98 /* camera mount location */
99 const char *pos = curElem->FindAttribute("position")->Value();
100
101 /* store read camera module information */
102 mCameraInfo[id] = readCameraDeviceInfo(curElem);
103
104 /* assign a camera device to a position group */
105 mCameraPosition[pos].emplace(id);
106 } else {
107 /* ignore other device types */
108 ALOGD("Unknown element %s is ignored", curElem->Name());
109 }
110
111 curElem = curElem->NextSiblingElement();
112 }
113}
114
115
116unique_ptr<ConfigManager::CameraInfo>
117ConfigManager::readCameraDeviceInfo(const XMLElement *aDeviceElem) {
118 if (aDeviceElem == nullptr) {
119 return nullptr;
120 }
121
122 /* create a CameraInfo to be filled */
123 unique_ptr<ConfigManager::CameraInfo> aCamera(new ConfigManager::CameraInfo());
124
125 /* size information to allocate camera_metadata_t */
126 size_t totalEntries = 0;
127 size_t totalDataSize = 0;
128
129 /* read device capabilities */
130 totalEntries +=
131 readCameraCapabilities(aDeviceElem->FirstChildElement("caps"),
132 aCamera,
133 totalDataSize);
134
135
136 /* read camera metadata */
137 totalEntries +=
138 readCameraMetadata(aDeviceElem->FirstChildElement("characteristics"),
139 aCamera,
140 totalDataSize);
141
142 /* construct camera_metadata_t */
143 if (!constructCameraMetadata(aCamera, totalEntries, totalDataSize)) {
144 ALOGW("Either failed to allocate memory or "
145 "allocated memory was not large enough");
146 }
147
148 return aCamera;
149}
150
151
152size_t ConfigManager::readCameraCapabilities(const XMLElement * const aCapElem,
153 unique_ptr<ConfigManager::CameraInfo> &aCamera,
154 size_t &dataSize) {
155 if (aCapElem == nullptr) {
156 return 0;
157 }
158
159 string token;
160 const XMLElement *curElem = nullptr;
161
162 /* a list of supported camera parameters/controls */
163 curElem = aCapElem->FirstChildElement("supported_controls");
164 if (curElem != nullptr) {
165 const XMLElement *ctrlElem = curElem->FirstChildElement("control");
166 while (ctrlElem != nullptr) {
167 const char *nameAttr = ctrlElem->FindAttribute("name")->Value();;
168 const int32_t minVal = stoi(ctrlElem->FindAttribute("min")->Value());
169 const int32_t maxVal = stoi(ctrlElem->FindAttribute("max")->Value());
170
171 int32_t stepVal = 1;
172 const XMLAttribute *stepAttr = ctrlElem->FindAttribute("step");
173 if (stepAttr != nullptr) {
174 stepVal = stoi(stepAttr->Value());
175 }
176
177 CameraParam aParam;
178 if (ConfigManagerUtil::convertToEvsCameraParam(nameAttr,
179 aParam)) {
180 aCamera->controls.emplace(
181 aParam,
182 make_tuple(minVal, maxVal, stepVal)
183 );
184 }
185
186 ctrlElem = ctrlElem->NextSiblingElement("control");
187 }
188 }
189
190 /* a list of camera stream configurations */
191 curElem = aCapElem->FirstChildElement("stream");
192 while (curElem != nullptr) {
193 /* read 5 attributes */
194 const XMLAttribute *idAttr = curElem->FindAttribute("id");
195 const XMLAttribute *widthAttr = curElem->FindAttribute("width");
196 const XMLAttribute *heightAttr = curElem->FindAttribute("height");
197 const XMLAttribute *fmtAttr = curElem->FindAttribute("format");
198 const XMLAttribute *fpsAttr = curElem->FindAttribute("framerate");
199
200 const int32_t id = stoi(idAttr->Value());
201 int32_t framerate = 0;
202 if (fpsAttr != nullptr) {
203 framerate = stoi(fpsAttr->Value());
204 }
205
206 int32_t pixFormat;
207 if (ConfigManagerUtil::convertToPixelFormat(fmtAttr->Value(),
208 pixFormat)) {
209 RawStreamConfiguration cfg = {
210 id,
211 stoi(widthAttr->Value()),
212 stoi(heightAttr->Value()),
213 pixFormat,
214 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
215 framerate
216 };
217 aCamera->streamConfigurations[id] = cfg;
218 }
219
220 curElem = curElem->NextSiblingElement("stream");
221 }
222
223 dataSize = calculate_camera_metadata_entry_data_size(
224 get_camera_metadata_tag_type(
225 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS
226 ),
227 aCamera->streamConfigurations.size() * kStreamCfgSz
228 );
229
230 /* a single camera metadata entry contains multiple stream configurations */
231 return dataSize > 0 ? 1 : 0;
232}
233
234
235size_t ConfigManager::readCameraMetadata(const XMLElement * const aParamElem,
236 unique_ptr<ConfigManager::CameraInfo> &aCamera,
237 size_t &dataSize) {
238 if (aParamElem == nullptr) {
239 return 0;
240 }
241
242 const XMLElement *curElem = aParamElem->FirstChildElement("parameter");
243 size_t numEntries = 0;
244 camera_metadata_tag_t tag;
245 while (curElem != nullptr) {
246 if (!ConfigManagerUtil::convertToMetadataTag(curElem->FindAttribute("name")->Value(),
247 tag)) {
248 switch(tag) {
249 case ANDROID_LENS_DISTORTION:
250 case ANDROID_LENS_POSE_ROTATION:
251 case ANDROID_LENS_POSE_TRANSLATION:
252 case ANDROID_LENS_INTRINSIC_CALIBRATION: {
253 /* float[] */
254 size_t count = 0;
255 void *data = ConfigManagerUtil::convertFloatArray(
256 curElem->FindAttribute("size")->Value(),
257 curElem->FindAttribute("value")->Value(),
258 count
259 );
260
261 aCamera->cameraMetadata[tag] =
262 make_pair(make_unique<void *>(data), count);
263
264 ++numEntries;
265 dataSize += calculate_camera_metadata_entry_data_size(
266 get_camera_metadata_tag_type(tag), count
267 );
268
269 break;
270 }
271
272 default:
273 ALOGW("Parameter %s is not supported",
274 curElem->FindAttribute("name")->Value());
275 break;
276 }
277 }
278
279 curElem = curElem->NextSiblingElement("parameter");
280 }
281
282 return numEntries;
283}
284
285
286bool ConfigManager::constructCameraMetadata(unique_ptr<CameraInfo> &aCamera,
287 const size_t totalEntries,
288 const size_t totalDataSize) {
289 if (!aCamera->allocate(totalEntries, totalDataSize)) {
290 ALOGE("Failed to allocate memory for camera metadata");
291 return false;
292 }
293
294 const size_t numStreamConfigs = aCamera->streamConfigurations.size();
295 unique_ptr<int32_t[]> data(new int32_t[kStreamCfgSz * numStreamConfigs]);
296 int32_t *ptr = data.get();
297 for (auto &cfg : aCamera->streamConfigurations) {
298 for (auto i = 0; i < kStreamCfgSz; ++i) {
299 *ptr++ = cfg.second[i];
300 }
301 }
302 int32_t err = add_camera_metadata_entry(aCamera->characteristics,
303 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
304 data.get(),
305 numStreamConfigs * kStreamCfgSz);
306
307 if (err) {
308 ALOGE("Failed to add stream configurations to metadata, ignored");
309 return false;
310 }
311
312 bool success = true;
313 for (auto &[tag, entry] : aCamera->cameraMetadata) {
314 /* try to add new camera metadata entry */
315 int32_t err = add_camera_metadata_entry(aCamera->characteristics,
316 tag,
317 entry.first.get(),
318 entry.second);
319 if (err) {
320 ALOGE("Failed to add an entry with a tag 0x%X", tag);
321
322 /* may exceed preallocated capacity */
323 ALOGE("Camera metadata has %ld / %ld entries and %ld / %ld bytes are filled",
324 get_camera_metadata_entry_count(aCamera->characteristics),
325 get_camera_metadata_entry_capacity(aCamera->characteristics),
326 get_camera_metadata_data_count(aCamera->characteristics),
327 get_camera_metadata_data_capacity(aCamera->characteristics));
328 ALOGE("\tCurrent metadata entry requires %ld bytes",
329 calculate_camera_metadata_entry_data_size(tag, entry.second));
330
331 success = false;
332 }
333 }
334
335 ALOGV("Camera metadata has %ld / %ld entries and %ld / %ld bytes are filled",
336 get_camera_metadata_entry_count(aCamera->characteristics),
337 get_camera_metadata_entry_capacity(aCamera->characteristics),
338 get_camera_metadata_data_count(aCamera->characteristics),
339 get_camera_metadata_data_capacity(aCamera->characteristics));
340
341 return success;
342}
343
344
345void ConfigManager::readSystemInfo(const XMLElement * const aSysElem) {
346 if (aSysElem == nullptr) {
347 return;
348 }
349
350 /*
351 * Please note that this function assumes that a given system XML element
352 * and its child elements follow DTD. If it does not, it will cause a
353 * segmentation fault due to the failure of finding expected attributes.
354 */
355
356 /* read number of cameras available in the system */
357 const XMLElement *xmlElem = aSysElem->FirstChildElement("num_cameras");
358 if (xmlElem != nullptr) {
359 mSystemInfo.numCameras =
360 stoi(xmlElem->FindAttribute("value")->Value());
361 }
362}
363
364
365void ConfigManager::readDisplayInfo(const XMLElement * const aDisplayElem) {
366 if (aDisplayElem == nullptr) {
367 ALOGW("XML file does not have required camera element");
368 return;
369 }
370
371 const XMLElement *curDev = aDisplayElem->FirstChildElement("device");
372 while (curDev != nullptr) {
373 const char *id = curDev->FindAttribute("id")->Value();
374 //const char *pos = curDev->FirstAttribute("position")->Value();
375
376 unique_ptr<DisplayInfo> dpy(new DisplayInfo());
377 if (dpy == nullptr) {
378 ALOGE("Failed to allocate memory for DisplayInfo");
379 return;
380 }
381
382 const XMLElement *cap = curDev->FirstChildElement("caps");
383 if (cap != nullptr) {
384 const XMLElement *curStream = cap->FirstChildElement("stream");
385 while (curStream != nullptr) {
386 /* read 4 attributes */
387 const XMLAttribute *idAttr = curStream->FindAttribute("id");
388 const XMLAttribute *widthAttr = curStream->FindAttribute("width");
389 const XMLAttribute *heightAttr = curStream->FindAttribute("height");
390 const XMLAttribute *fmtAttr = curStream->FindAttribute("format");
391
392 const int32_t id = stoi(idAttr->Value());
393 int32_t pixFormat;
394 if (ConfigManagerUtil::convertToPixelFormat(fmtAttr->Value(),
395 pixFormat)) {
396 RawStreamConfiguration cfg = {
397 id,
398 stoi(widthAttr->Value()),
399 stoi(heightAttr->Value()),
400 pixFormat,
401 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT,
402 0 // unused
403 };
404 dpy->streamConfigurations[id] = cfg;
405 }
406
407 curStream = curStream->NextSiblingElement("stream");
408 }
409 }
410
411 mDisplayInfo[id] = std::move(dpy);
412 curDev = curDev->NextSiblingElement("device");
413 }
414
415 return;
416}
417
418
419bool ConfigManager::readConfigDataFromXML() noexcept {
420 XMLDocument xmlDoc;
421
422 const int64_t parsingStart = android::elapsedRealtimeNano();
423
424 /* load and parse a configuration file */
425 xmlDoc.LoadFile(mConfigFilePath);
426 if (xmlDoc.ErrorID() != XML_SUCCESS) {
427 ALOGE("Failed to load and/or parse a configuration file, %s", xmlDoc.ErrorStr());
428 return false;
429 }
430
431 /* retrieve the root element */
432 const XMLElement *rootElem = xmlDoc.RootElement();
433 if (strcmp(rootElem->Name(), "configuration")) {
434 ALOGE("A configuration file is not in the required format. "
435 "See /etc/automotive/evs/evs_configuration.dtd");
436 return false;
437 }
438
439 /*
440 * parse camera information; this needs to be done before reading system
441 * information
442 */
443 readCameraInfo(rootElem->FirstChildElement("camera"));
444
445 /* parse system information */
446 readSystemInfo(rootElem->FirstChildElement("system"));
447
448 /* parse display information */
449 readDisplayInfo(rootElem->FirstChildElement("display"));
450
451 const int64_t parsingEnd = android::elapsedRealtimeNano();
452 ALOGI("Parsing configuration file takes %lf (ms)",
453 (double)(parsingEnd - parsingStart) / 1000000.0);
454
455
456 return true;
457}
458
459
460void ConfigManager::addCameraDevices(const char *devices,
461 unique_ptr<CameraGroup> &aGroup) {
462 stringstream device_list(devices);
463 string token;
464 while (getline(device_list, token, ',')) {
465 aGroup->devices.emplace(token);
466 }
467}
468
469
470std::unique_ptr<ConfigManager> ConfigManager::Create(const char *path) {
471 unique_ptr<ConfigManager> cfgMgr(new ConfigManager(path));
472
473 /*
474 * Read a configuration from XML file
475 *
476 * If this is too slow, ConfigManager::readConfigDataFromBinary() and
477 * ConfigManager::writeConfigDataToBinary()can serialize CameraInfo object
478 * to the filesystem and construct CameraInfo instead; this was
479 * evaluated as 10x faster.
480 */
481 if (!cfgMgr->readConfigDataFromXML()) {
482 return nullptr;
483 } else {
484 return cfgMgr;
485 }
486}
487