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