• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2024 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 #define LOG_TAG "SharedSessionConfigUtils"
18 
19 #include "SharedSessionConfigUtils.h"
20 
21 #include <inttypes.h>
22 #include <sstream>
23 #include <utils/Log.h>
24 
25 namespace android {
26 
toString(ErrorCode errorCode)27 const char* SharedSessionConfigUtils::toString(ErrorCode errorCode) {
28     switch (errorCode) {
29         case ErrorCode::STATUS_OK:
30             return "STATUS_OK";
31         case ErrorCode::ERROR_READ_CONFIG_FILE:
32             return "ERROR_READ_CONFIG_FILE";
33         case ErrorCode::ERROR_CONFIG_FILE_FORMAT:
34             return "ERROR_CONFIG_FILE_FORMAT";
35         case ErrorCode::ERROR_CONFIG_READER_UNINITIALIZED:
36             return "ERROR_CONFIG_READER_UNINITIALIZED";
37         case ErrorCode::ERROR_BAD_PARAMETER:
38             return "ERROR_BAD_PARAMETER";
39         default:
40             ALOGE("%s: Called toString on an unknown ErrorCode. This should never happen",
41                   __FUNCTION__);
42             return "";
43     }
44 }
45 
getColorSpaceFromStr(const char * colorSpaceStr,int32_t * colorSpace)46 ErrorCode SharedSessionConfigUtils::getColorSpaceFromStr(const char* colorSpaceStr,
47                                                          /* out */ int32_t* colorSpace) {
48     if (colorSpaceStr == nullptr || !strcmp(colorSpaceStr, "")) {
49         *colorSpace = ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED;
50         return ErrorCode::STATUS_OK;
51     }
52 
53     int32_t colorSpaceInt = (int32_t) std::strtol(colorSpaceStr, nullptr, 0);
54     if (VALID_COLOR_SPACES.find(colorSpaceInt) == VALID_COLOR_SPACES.end()) {
55         ALOGE("%s: colorSpace %" PRId32 " is invalid: ", __FUNCTION__, colorSpaceInt);
56         ALOGE("%s: Expected one of: %s", __FUNCTION__, setToString(VALID_COLOR_SPACES).c_str());
57         return ErrorCode::ERROR_CONFIG_FILE_FORMAT;
58     }
59 
60     *colorSpace = colorSpaceInt;
61     return ErrorCode::STATUS_OK;
62 }
63 
getSurfaceTypeFromXml(const XMLElement * surfaceTypeXml,int64_t * surfaceType)64 ErrorCode SharedSessionConfigUtils::getSurfaceTypeFromXml(const XMLElement* surfaceTypeXml,
65                                                           /* out */ int64_t* surfaceType) {
66     if (surfaceTypeXml == nullptr || surfaceTypeXml->GetText() == nullptr
67             || !strcmp(surfaceTypeXml->GetText(), "")) {
68         ALOGE("%s: surface type field must be populated", __FUNCTION__);
69         return ErrorCode::ERROR_CONFIG_FILE_FORMAT;
70     }
71 
72     int64_t surfaceTypeInt = std::strtol(surfaceTypeXml->GetText(), nullptr, 0);
73     if (VALID_SURFACE_TYPES.find(surfaceTypeInt) == VALID_SURFACE_TYPES.end()) {
74         ALOGE("%s: surfaceType %" PRId64 " is invalid: ", __FUNCTION__, surfaceTypeInt);
75         ALOGE("%s: Expected one of: %s", __FUNCTION__, setToString(VALID_SURFACE_TYPES).c_str());
76         return ErrorCode::ERROR_CONFIG_FILE_FORMAT;
77     }
78 
79     *surfaceType = surfaceTypeInt;
80     return ErrorCode::STATUS_OK;
81 }
82 
getWidthFromXml(const XMLElement * widthXml,int64_t * width)83 ErrorCode SharedSessionConfigUtils::getWidthFromXml(const XMLElement* widthXml,
84                                                     /* out */ int64_t* width) {
85     if (widthXml == nullptr || widthXml->GetText() == nullptr
86             || !strcmp(widthXml->GetText(), "")) {
87         ALOGE("%s: width field must be populated", __FUNCTION__);
88         return ErrorCode::ERROR_CONFIG_FILE_FORMAT;
89     }
90 
91     const char* widthStr = widthXml->GetText();
92     *width = std::strtol(widthStr, nullptr, 0);
93     if (*width <= 0) {
94         ALOGE("%s: width value is invalid", __FUNCTION__);
95     }
96 
97     return ErrorCode::STATUS_OK;
98 }
99 
getHeightFromXml(const XMLElement * heightXml,int64_t * height)100 ErrorCode SharedSessionConfigUtils::getHeightFromXml(const XMLElement* heightXml,
101                                                      /* out */ int64_t* height) {
102     if (heightXml == nullptr || heightXml->GetText() == nullptr
103             || !strcmp(heightXml->GetText(), "")) {
104         ALOGE("%s: height field must be populated", __FUNCTION__);
105         return ErrorCode::ERROR_CONFIG_FILE_FORMAT;
106     }
107 
108     const char* heightStr = heightXml->GetText();
109     *height = std::strtol(heightStr, nullptr, 0);
110     if (*height <= 0) {
111         ALOGE("%s: height value is invalid", __FUNCTION__);
112     }
113 
114     return ErrorCode::STATUS_OK;
115 }
116 
getPhysicalCameraIdFromXml(const XMLElement * physicalCameraIdXml,std::string * physicalCameraId)117 ErrorCode SharedSessionConfigUtils::getPhysicalCameraIdFromXml(
118         const XMLElement* physicalCameraIdXml, /* out */ std::string* physicalCameraId) {
119     *physicalCameraId =
120             (physicalCameraIdXml == nullptr || physicalCameraIdXml->GetText() == nullptr)
121                     ? "": physicalCameraIdXml->GetText();
122     return ErrorCode::STATUS_OK;
123 }
124 
getStreamUseCaseFromXml(const XMLElement * streamUseCaseXml,int64_t * streamUseCase)125 ErrorCode SharedSessionConfigUtils::getStreamUseCaseFromXml(const XMLElement* streamUseCaseXml,
126                                                             /* out */ int64_t* streamUseCase) {
127     if (streamUseCaseXml == nullptr || streamUseCaseXml->GetText() == nullptr
128             || !strcmp(streamUseCaseXml->GetText(), "")) {
129         *streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT;
130         return ErrorCode::STATUS_OK;
131     }
132 
133     int64_t streamUseCaseInt = std::strtol(streamUseCaseXml->GetText(), nullptr, 0);
134     if (VALID_STREAM_USE_CASES.find(streamUseCaseInt) == VALID_STREAM_USE_CASES.end()) {
135         ALOGE("%s: streamUseCase %" PRId64 " is invalid: ", __FUNCTION__, streamUseCaseInt);
136         ALOGE("%s: Expected one of: %s", __FUNCTION__, setToString(VALID_STREAM_USE_CASES).c_str());
137         return ErrorCode::ERROR_CONFIG_FILE_FORMAT;
138     }
139 
140     *streamUseCase = streamUseCaseInt;
141     return ErrorCode::STATUS_OK;
142 }
143 
getTimestampBaseFromXml(const XMLElement * timestampBaseXml,int64_t * timestampBase)144 ErrorCode SharedSessionConfigUtils::getTimestampBaseFromXml(const XMLElement* timestampBaseXml,
145                                                             /* out */ int64_t* timestampBase) {
146     if (timestampBaseXml == nullptr || timestampBaseXml->GetText() == nullptr
147             || !strcmp(timestampBaseXml->GetText(), "")) {
148         *timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT;
149         return ErrorCode::STATUS_OK;
150     }
151 
152     int64_t timestampBaseInt = std::strtol(timestampBaseXml->GetText(), nullptr, 0);
153     if (VALID_TIMESTAMP_BASES.find(timestampBaseInt) == VALID_TIMESTAMP_BASES.end()) {
154         ALOGE("%s: timestampBase %" PRId64 " is invalid: ", __FUNCTION__, timestampBaseInt);
155         ALOGE("%s: Expected one of: %s", __FUNCTION__, setToString(VALID_TIMESTAMP_BASES).c_str());
156         return ErrorCode::ERROR_CONFIG_FILE_FORMAT;
157     }
158 
159     *timestampBase = timestampBaseInt;
160     return ErrorCode::STATUS_OK;
161 }
162 
getMirrorModeFromXml(const XMLElement * mirrorModeXml,int64_t * mirrorMode)163 ErrorCode SharedSessionConfigUtils::getMirrorModeFromXml(const XMLElement* mirrorModeXml,
164                                                          /* out */ int64_t* mirrorMode) {
165     if (mirrorModeXml == nullptr || mirrorModeXml->GetText() == nullptr
166             || !strcmp(mirrorModeXml->GetText(), "")) {
167         *mirrorMode = OutputConfiguration::MIRROR_MODE_AUTO;
168         return ErrorCode::STATUS_OK;
169     }
170 
171     int64_t mirrorModeInt = std::strtol(mirrorModeXml->GetText(), nullptr, 0);
172     if (VALID_MIRROR_MODES.find(mirrorModeInt) == VALID_MIRROR_MODES.end()) {
173         ALOGE("%s: mirrorMode %" PRId64 " is invalid: ", __FUNCTION__, mirrorModeInt);
174         ALOGE("%s: Expected one of: %s", __FUNCTION__, setToString(VALID_MIRROR_MODES).c_str());
175         return ErrorCode::ERROR_CONFIG_FILE_FORMAT;
176     }
177 
178     *mirrorMode = mirrorModeInt;
179     return ErrorCode::STATUS_OK;
180 }
181 
getUseReadoutTimestampFromXml(const XMLElement * useReadoutTimestampXml,bool * useReadoutTimestamp)182 ErrorCode SharedSessionConfigUtils::getUseReadoutTimestampFromXml(
183         const XMLElement* useReadoutTimestampXml, /* out */ bool* useReadoutTimestamp) {
184     if (useReadoutTimestampXml != nullptr && useReadoutTimestampXml->GetText() != nullptr
185             && strcmp(useReadoutTimestampXml->GetText(), "")) {
186         const char* useReadoutTimestampStr = useReadoutTimestampXml->GetText();
187         if (!strcmp(useReadoutTimestampStr, "1")) {
188             *useReadoutTimestamp = true;
189             return ErrorCode::STATUS_OK;
190         } else if (strcmp(useReadoutTimestampStr, "0")) {
191             ALOGE("%s: useReadoutTimestamp string %s is invalid: ", __FUNCTION__,
192                   useReadoutTimestampStr);
193             ALOGE("%s: Expected one of: {0, 1}", __FUNCTION__);
194             return ErrorCode::ERROR_CONFIG_FILE_FORMAT;
195         }
196     }
197 
198     *useReadoutTimestamp = false;
199     return ErrorCode::STATUS_OK;
200 }
201 
getFormatFromXml(const XMLElement * formatXml,int64_t * format,int64_t surfaceType)202 ErrorCode SharedSessionConfigUtils::getFormatFromXml(const XMLElement* formatXml,
203                                                      /* out */ int64_t* format,
204                                                      int64_t surfaceType) {
205     if (surfaceType != OutputConfiguration::SURFACE_TYPE_IMAGE_READER) {
206         // if surface type is not image reader, format must default to impl defined enum.
207         *format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
208         return ErrorCode::STATUS_OK;
209     }
210 
211     if (formatXml == nullptr || formatXml->GetText() == nullptr
212             || !strcmp(formatXml->GetText(), "")) {
213         ALOGE("%s: format field must be populated", __FUNCTION__);
214         return ErrorCode::ERROR_CONFIG_FILE_FORMAT;
215     }
216 
217     int64_t formatInt = std::strtol(formatXml->GetText(), nullptr, 0);
218     if (VALID_FORMATS.find(formatInt) == VALID_FORMATS.end()) {
219         ALOGE("%s: format %" PRId64 " is invalid: ", __FUNCTION__, formatInt);
220         ALOGE("%s: Expected one of: %s", __FUNCTION__, setToString(VALID_FORMATS).c_str());
221         return ErrorCode::ERROR_CONFIG_FILE_FORMAT;
222     }
223 
224     *format = formatInt;
225     return ErrorCode::STATUS_OK;
226 }
227 
getUsageFromXml(const XMLElement * usageXml,int64_t * usage,int64_t surfaceType)228 ErrorCode SharedSessionConfigUtils::getUsageFromXml(const XMLElement* usageXml,
229                                                     /* out */ int64_t* usage,
230                                                     int64_t surfaceType) {
231     if (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_TEXTURE) {
232         // if surface type is SURFACE_TYPE_SURFACE_TEXTURE, usage must default to
233         // AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE.
234         *usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
235         return ErrorCode::STATUS_OK;
236     }
237 
238     if (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) {
239         // if surface type is SURFACE_TYPE_SURFACE_VIEW, usage must default to
240         // AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY.
241         *usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY;
242         return ErrorCode::STATUS_OK;
243     }
244 
245     if (surfaceType == OutputConfiguration::SURFACE_TYPE_MEDIA_RECORDER
246             || surfaceType == OutputConfiguration::SURFACE_TYPE_MEDIA_CODEC) {
247         // if surface type is SURFACE_TYPE_MEDIA_RECORDER or SURFACE_TYPE_MEDIA_CODEC, usage must
248         // default to AHARDWAREBUFFER_USAGE_VIDEO_ENCODE
249         *usage = AHARDWAREBUFFER_USAGE_VIDEO_ENCODE;
250         return ErrorCode::STATUS_OK;
251     }
252 
253     if (usageXml == nullptr || usageXml->GetText() == nullptr
254             || !strcmp(usageXml->GetText(), "")) {
255         *usage = AHARDWAREBUFFER_USAGE_CPU_READ_NEVER;
256         return ErrorCode::STATUS_OK;
257     }
258 
259     const char* usageStr = usageXml->GetText();
260     std::vector<std::string> usageFlags = splitString(usageStr, '|');
261 
262     for (std::string usageFlagStr : usageFlags) {
263         int64_t usageFlag = std::strtol(usageFlagStr.c_str(), nullptr, 0);
264         if (VALID_USAGES.find(usageFlag) == VALID_USAGES.end()) {
265             ALOGE("%s: usage %" PRId64 " is invalid: ", __FUNCTION__, usageFlag);
266             ALOGE("%s: Expected one of: %s", __FUNCTION__, setToString(VALID_USAGES).c_str());
267             return ErrorCode::ERROR_CONFIG_FILE_FORMAT;
268         }
269 
270         *usage |= usageFlag;
271     }
272 
273     return ErrorCode::STATUS_OK;
274 }
275 
getDataSpaceFromXml(const XMLElement * dataSpaceXml,int64_t * dataSpace)276 ErrorCode SharedSessionConfigUtils::getDataSpaceFromXml(const XMLElement* dataSpaceXml,
277                                                         /* out */ int64_t* dataSpace) {
278     if (dataSpaceXml == nullptr || dataSpaceXml->GetText() == nullptr
279             || !strcmp(dataSpaceXml->GetText(), "")) {
280         *dataSpace = HAL_DATASPACE_UNKNOWN;
281         return ErrorCode::STATUS_OK;
282     }
283 
284     int64_t dataSpaceInt = std::strtol(dataSpaceXml->GetText(), nullptr, 0);
285     if (VALID_DATA_SPACES.find(dataSpaceInt) == VALID_DATA_SPACES.end()) {
286         ALOGE("%s: dataSpace %" PRId64 " is invalid: ", __FUNCTION__, dataSpaceInt);
287         ALOGE("%s: Expected one of: %s", __FUNCTION__, setToString(VALID_DATA_SPACES).c_str());
288         return ErrorCode::ERROR_CONFIG_FILE_FORMAT;
289     }
290 
291     *dataSpace = dataSpaceInt;
292     return ErrorCode::STATUS_OK;
293 }
294 
splitString(std::string inputString,char delimiter)295 std::vector<std::string> SharedSessionConfigUtils::splitString(std::string inputString,
296                                                                char delimiter) {
297     std::vector<std::string> tokens;
298     std::istringstream iss(inputString);
299     std::string token;
300 
301     while (std::getline(iss, token, delimiter)) {
302         tokens.push_back(token);
303     }
304 
305     return tokens;
306 }
307 
setToString(const std::set<int64_t> & s)308 std::string SharedSessionConfigUtils::setToString(const std::set<int64_t>& s) {
309     std::ostringstream oss;
310     oss << "{";
311 
312     for (auto it = s.begin(); it != s.end();) {
313         oss << *it;
314 
315         if (++it != s.end()) {
316             oss << ", ";
317         }
318     }
319 
320     oss << "}";
321     return oss.str();
322 }
323 
324 }  // namespace android
325