blob: 4511446bdfa0ffaeaada218243bb0cb530abd885 [file] [log] [blame]
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -08001/*
2 * Copyright (C) 2020 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 */
Austin Borgerea931242021-12-13 23:10:41 +000016
Shuzhen Wangd4abdf72021-05-28 11:22:50 -070017#include <cutils/properties.h>
18
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -080019#include "SessionConfigurationUtils.h"
Colin Crossb8a9dbb2020-08-27 04:12:26 +000020#include "../api2/DepthCompositeStream.h"
21#include "../api2/HeicCompositeStream.h"
22#include "common/CameraDeviceBase.h"
23#include "../CameraService.h"
24#include "device3/Camera3Device.h"
25#include "device3/Camera3OutputStream.h"
26
Colin Crossb8a9dbb2020-08-27 04:12:26 +000027using android::camera3::OutputStreamInfo;
28using android::camera3::OutputStreamInfo;
29using android::hardware::camera2::ICameraDeviceUser;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -080030using android::hardware::camera::metadata::V3_6::CameraMetadataEnumAndroidSensorPixelMode;
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -080031
32namespace android {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -080033namespace camera3 {
34
35void StreamConfiguration::getStreamConfigurations(
36 const CameraMetadata &staticInfo, int configuration,
37 std::unordered_map<int, std::vector<StreamConfiguration>> *scm) {
38 if (scm == nullptr) {
39 ALOGE("%s: StreamConfigurationMap nullptr", __FUNCTION__);
40 return;
41 }
42 const int STREAM_FORMAT_OFFSET = 0;
43 const int STREAM_WIDTH_OFFSET = 1;
44 const int STREAM_HEIGHT_OFFSET = 2;
45 const int STREAM_IS_INPUT_OFFSET = 3;
46
47 camera_metadata_ro_entry availableStreamConfigs = staticInfo.find(configuration);
48 for (size_t i = 0; i < availableStreamConfigs.count; i += 4) {
49 int32_t format = availableStreamConfigs.data.i32[i + STREAM_FORMAT_OFFSET];
50 int32_t width = availableStreamConfigs.data.i32[i + STREAM_WIDTH_OFFSET];
51 int32_t height = availableStreamConfigs.data.i32[i + STREAM_HEIGHT_OFFSET];
52 int32_t isInput = availableStreamConfigs.data.i32[i + STREAM_IS_INPUT_OFFSET];
53 StreamConfiguration sc = {format, width, height, isInput};
54 (*scm)[format].push_back(sc);
55 }
56}
57
58void StreamConfiguration::getStreamConfigurations(
59 const CameraMetadata &staticInfo, bool maxRes,
60 std::unordered_map<int, std::vector<StreamConfiguration>> *scm) {
61 int32_t scalerKey =
62 SessionConfigurationUtils::getAppropriateModeTag(
63 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, maxRes);
64
65 int32_t depthKey =
66 SessionConfigurationUtils::getAppropriateModeTag(
67 ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS, maxRes);
68
69 int32_t dynamicDepthKey =
70 SessionConfigurationUtils::getAppropriateModeTag(
71 ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS);
72
73 int32_t heicKey =
74 SessionConfigurationUtils::getAppropriateModeTag(
75 ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS);
76
77 getStreamConfigurations(staticInfo, scalerKey, scm);
78 getStreamConfigurations(staticInfo, depthKey, scm);
79 getStreamConfigurations(staticInfo, dynamicDepthKey, scm);
80 getStreamConfigurations(staticInfo, heicKey, scm);
81}
82
Austin Borgerea931242021-12-13 23:10:41 +000083namespace SessionConfigurationUtils {
84
85int32_t PERF_CLASS_LEVEL =
86 property_get_int32("ro.odm.build.media_performance_class", 0);
87
88bool IS_PERF_CLASS = (PERF_CLASS_LEVEL == SDK_VERSION_S);
89
90camera3::Size getMaxJpegResolution(const CameraMetadata &metadata,
91 bool ultraHighResolution) {
92 int32_t maxJpegWidth = 0, maxJpegHeight = 0;
93 const int STREAM_CONFIGURATION_SIZE = 4;
94 const int STREAM_FORMAT_OFFSET = 0;
95 const int STREAM_WIDTH_OFFSET = 1;
96 const int STREAM_HEIGHT_OFFSET = 2;
97 const int STREAM_IS_INPUT_OFFSET = 3;
98
99 int32_t scalerSizesTag = ultraHighResolution ?
100 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION :
101 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS;
102 camera_metadata_ro_entry_t availableStreamConfigs =
103 metadata.find(scalerSizesTag);
104 if (availableStreamConfigs.count == 0 ||
105 availableStreamConfigs.count % STREAM_CONFIGURATION_SIZE != 0) {
106 return camera3::Size(0, 0);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800107 }
Austin Borgerea931242021-12-13 23:10:41 +0000108
109 // Get max jpeg size (area-wise).
110 for (size_t i= 0; i < availableStreamConfigs.count; i+= STREAM_CONFIGURATION_SIZE) {
111 int32_t format = availableStreamConfigs.data.i32[i + STREAM_FORMAT_OFFSET];
112 int32_t width = availableStreamConfigs.data.i32[i + STREAM_WIDTH_OFFSET];
113 int32_t height = availableStreamConfigs.data.i32[i + STREAM_HEIGHT_OFFSET];
114 int32_t isInput = availableStreamConfigs.data.i32[i + STREAM_IS_INPUT_OFFSET];
115 if (isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT
116 && format == HAL_PIXEL_FORMAT_BLOB &&
117 (width * height > maxJpegWidth * maxJpegHeight)) {
118 maxJpegWidth = width;
119 maxJpegHeight = height;
120 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800121 }
Austin Borgerea931242021-12-13 23:10:41 +0000122
123 return camera3::Size(maxJpegWidth, maxJpegHeight);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800124}
125
Austin Borgerea931242021-12-13 23:10:41 +0000126size_t getUHRMaxJpegBufferSize(camera3::Size uhrMaxJpegSize,
127 camera3::Size defaultMaxJpegSize, size_t defaultMaxJpegBufferSize) {
128 return (uhrMaxJpegSize.width * uhrMaxJpegSize.height) /
129 (defaultMaxJpegSize.width * defaultMaxJpegSize.height) * defaultMaxJpegBufferSize;
130}
131
132bool getArrayWidthAndHeight(const CameraMetadata *deviceInfo,
Jayant Chowdhary9255ce02021-07-15 11:18:17 -0700133 int32_t arrayTag, int32_t *width, int32_t *height) {
134 if (width == nullptr || height == nullptr) {
135 ALOGE("%s: width / height nullptr", __FUNCTION__);
136 return false;
137 }
138 camera_metadata_ro_entry_t entry;
139 entry = deviceInfo->find(arrayTag);
140 if (entry.count != 4) return false;
141 *width = entry.data.i32[2];
142 *height = entry.data.i32[3];
143 return true;
144}
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800145
146StreamConfigurationPair
Austin Borgerea931242021-12-13 23:10:41 +0000147getStreamConfigurationPair(const CameraMetadata &staticInfo) {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800148 camera3::StreamConfigurationPair streamConfigurationPair;
149 camera3::StreamConfiguration::getStreamConfigurations(staticInfo, false,
150 &streamConfigurationPair.mDefaultStreamConfigurationMap);
151 camera3::StreamConfiguration::getStreamConfigurations(staticInfo, true,
152 &streamConfigurationPair.mMaximumResolutionStreamConfigurationMap);
153 return streamConfigurationPair;
154}
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800155
Austin Borgerea931242021-12-13 23:10:41 +0000156int64_t euclidDistSquare(int32_t x0, int32_t y0, int32_t x1, int32_t y1) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000157 int64_t d0 = x0 - x1;
158 int64_t d1 = y0 - y1;
159 return d0 * d0 + d1 * d1;
160}
161
Austin Borgerea931242021-12-13 23:10:41 +0000162bool roundBufferDimensionNearest(int32_t width, int32_t height,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800163 int32_t format, android_dataspace dataSpace,
164 const CameraMetadata& info, bool maxResolution, /*out*/int32_t* outWidth,
165 /*out*/int32_t* outHeight) {
166 const int32_t depthSizesTag =
167 getAppropriateModeTag(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS,
168 maxResolution);
169 const int32_t scalerSizesTag =
170 getAppropriateModeTag(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, maxResolution);
171 const int32_t heicSizesTag =
172 getAppropriateModeTag(ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS, maxResolution);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000173
174 camera_metadata_ro_entry streamConfigs =
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800175 (dataSpace == HAL_DATASPACE_DEPTH) ? info.find(depthSizesTag) :
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000176 (dataSpace == static_cast<android_dataspace>(HAL_DATASPACE_HEIF)) ?
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800177 info.find(heicSizesTag) :
178 info.find(scalerSizesTag);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000179
180 int32_t bestWidth = -1;
181 int32_t bestHeight = -1;
182
183 // Iterate through listed stream configurations and find the one with the smallest euclidean
184 // distance from the given dimensions for the given format.
185 for (size_t i = 0; i < streamConfigs.count; i += 4) {
186 int32_t fmt = streamConfigs.data.i32[i];
187 int32_t w = streamConfigs.data.i32[i + 1];
188 int32_t h = streamConfigs.data.i32[i + 2];
189
190 // Ignore input/output type for now
191 if (fmt == format) {
192 if (w == width && h == height) {
193 bestWidth = width;
194 bestHeight = height;
195 break;
196 } else if (w <= ROUNDING_WIDTH_CAP && (bestWidth == -1 ||
197 SessionConfigurationUtils::euclidDistSquare(w, h, width, height) <
198 SessionConfigurationUtils::euclidDistSquare(bestWidth, bestHeight, width,
199 height))) {
200 bestWidth = w;
201 bestHeight = h;
202 }
203 }
204 }
205
206 if (bestWidth == -1) {
207 // Return false if no configurations for this format were listed
208 return false;
209 }
210
211 // Set the outputs to the closet width/height
212 if (outWidth != NULL) {
213 *outWidth = bestWidth;
214 }
215 if (outHeight != NULL) {
216 *outHeight = bestHeight;
217 }
218
219 // Return true if at least one configuration for this format was listed
220 return true;
221}
222
Austin Borgerea931242021-12-13 23:10:41 +0000223bool isPublicFormat(int32_t format)
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000224{
225 switch(format) {
226 case HAL_PIXEL_FORMAT_RGBA_8888:
227 case HAL_PIXEL_FORMAT_RGBX_8888:
228 case HAL_PIXEL_FORMAT_RGB_888:
229 case HAL_PIXEL_FORMAT_RGB_565:
230 case HAL_PIXEL_FORMAT_BGRA_8888:
231 case HAL_PIXEL_FORMAT_YV12:
232 case HAL_PIXEL_FORMAT_Y8:
233 case HAL_PIXEL_FORMAT_Y16:
234 case HAL_PIXEL_FORMAT_RAW16:
235 case HAL_PIXEL_FORMAT_RAW10:
236 case HAL_PIXEL_FORMAT_RAW12:
237 case HAL_PIXEL_FORMAT_RAW_OPAQUE:
238 case HAL_PIXEL_FORMAT_BLOB:
239 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
240 case HAL_PIXEL_FORMAT_YCbCr_420_888:
241 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
242 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
243 case HAL_PIXEL_FORMAT_YCbCr_422_I:
244 return true;
245 default:
246 return false;
247 }
248}
249
Austin Borgerea931242021-12-13 23:10:41 +0000250binder::Status createSurfaceFromGbp(
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000251 OutputStreamInfo& streamInfo, bool isStreamInfoValid,
252 sp<Surface>& surface, const sp<IGraphicBufferProducer>& gbp,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800253 const String8 &logicalCameraId, const CameraMetadata &physicalCameraMetadata,
254 const std::vector<int32_t> &sensorPixelModesUsed){
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000255 // bufferProducer must be non-null
256 if (gbp == nullptr) {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800257 String8 msg = String8::format("Camera %s: Surface is NULL", logicalCameraId.string());
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000258 ALOGW("%s: %s", __FUNCTION__, msg.string());
259 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
260 }
261 // HACK b/10949105
262 // Query consumer usage bits to set async operation mode for
263 // GLConsumer using controlledByApp parameter.
264 bool useAsync = false;
265 uint64_t consumerUsage = 0;
266 status_t err;
267 if ((err = gbp->getConsumerUsage(&consumerUsage)) != OK) {
268 String8 msg = String8::format("Camera %s: Failed to query Surface consumer usage: %s (%d)",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800269 logicalCameraId.string(), strerror(-err), err);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000270 ALOGE("%s: %s", __FUNCTION__, msg.string());
271 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
272 }
273 if (consumerUsage & GraphicBuffer::USAGE_HW_TEXTURE) {
274 ALOGW("%s: Camera %s with consumer usage flag: %" PRIu64 ": Forcing asynchronous mode for"
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800275 "stream", __FUNCTION__, logicalCameraId.string(), consumerUsage);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000276 useAsync = true;
277 }
278
279 uint64_t disallowedFlags = GraphicBuffer::USAGE_HW_VIDEO_ENCODER |
280 GRALLOC_USAGE_RENDERSCRIPT;
281 uint64_t allowedFlags = GraphicBuffer::USAGE_SW_READ_MASK |
282 GraphicBuffer::USAGE_HW_TEXTURE |
283 GraphicBuffer::USAGE_HW_COMPOSER;
284 bool flexibleConsumer = (consumerUsage & disallowedFlags) == 0 &&
285 (consumerUsage & allowedFlags) != 0;
286
287 surface = new Surface(gbp, useAsync);
288 ANativeWindow *anw = surface.get();
289
290 int width, height, format;
291 android_dataspace dataSpace;
292 if ((err = anw->query(anw, NATIVE_WINDOW_WIDTH, &width)) != OK) {
293 String8 msg = String8::format("Camera %s: Failed to query Surface width: %s (%d)",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800294 logicalCameraId.string(), strerror(-err), err);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000295 ALOGE("%s: %s", __FUNCTION__, msg.string());
296 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
297 }
298 if ((err = anw->query(anw, NATIVE_WINDOW_HEIGHT, &height)) != OK) {
299 String8 msg = String8::format("Camera %s: Failed to query Surface height: %s (%d)",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800300 logicalCameraId.string(), strerror(-err), err);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000301 ALOGE("%s: %s", __FUNCTION__, msg.string());
302 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
303 }
304 if ((err = anw->query(anw, NATIVE_WINDOW_FORMAT, &format)) != OK) {
305 String8 msg = String8::format("Camera %s: Failed to query Surface format: %s (%d)",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800306 logicalCameraId.string(), strerror(-err), err);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000307 ALOGE("%s: %s", __FUNCTION__, msg.string());
308 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
309 }
310 if ((err = anw->query(anw, NATIVE_WINDOW_DEFAULT_DATASPACE,
311 reinterpret_cast<int*>(&dataSpace))) != OK) {
312 String8 msg = String8::format("Camera %s: Failed to query Surface dataspace: %s (%d)",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800313 logicalCameraId.string(), strerror(-err), err);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000314 ALOGE("%s: %s", __FUNCTION__, msg.string());
315 return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
316 }
317
318 // FIXME: remove this override since the default format should be
319 // IMPLEMENTATION_DEFINED. b/9487482 & b/35317944
320 if ((format >= HAL_PIXEL_FORMAT_RGBA_8888 && format <= HAL_PIXEL_FORMAT_BGRA_8888) &&
321 ((consumerUsage & GRALLOC_USAGE_HW_MASK) &&
322 ((consumerUsage & GRALLOC_USAGE_SW_READ_MASK) == 0))) {
323 ALOGW("%s: Camera %s: Overriding format %#x to IMPLEMENTATION_DEFINED",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800324 __FUNCTION__, logicalCameraId.string(), format);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000325 format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
326 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800327 std::unordered_set<int32_t> overriddenSensorPixelModes;
328 if (checkAndOverrideSensorPixelModesUsed(sensorPixelModesUsed, format, width, height,
329 physicalCameraMetadata, flexibleConsumer, &overriddenSensorPixelModes) != OK) {
330 String8 msg = String8::format("Camera %s: sensor pixel modes for stream with "
331 "format %#x are not valid",logicalCameraId.string(), format);
332 ALOGE("%s: %s", __FUNCTION__, msg.string());
333 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
334 }
335 bool foundInMaxRes = false;
336 if (overriddenSensorPixelModes.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
337 overriddenSensorPixelModes.end()) {
338 // we can use the default stream configuration map
339 foundInMaxRes = true;
340 }
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000341 // Round dimensions to the nearest dimensions available for this format
342 if (flexibleConsumer && isPublicFormat(format) &&
343 !SessionConfigurationUtils::roundBufferDimensionNearest(width, height,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800344 format, dataSpace, physicalCameraMetadata, foundInMaxRes, /*out*/&width,
345 /*out*/&height)) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000346 String8 msg = String8::format("Camera %s: No supported stream configurations with "
347 "format %#x defined, failed to create output stream",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800348 logicalCameraId.string(), format);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000349 ALOGE("%s: %s", __FUNCTION__, msg.string());
350 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
351 }
352
353 if (!isStreamInfoValid) {
354 streamInfo.width = width;
355 streamInfo.height = height;
356 streamInfo.format = format;
357 streamInfo.dataSpace = dataSpace;
358 streamInfo.consumerUsage = consumerUsage;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800359 streamInfo.sensorPixelModesUsed = overriddenSensorPixelModes;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000360 return binder::Status::ok();
361 }
362 if (width != streamInfo.width) {
363 String8 msg = String8::format("Camera %s:Surface width doesn't match: %d vs %d",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800364 logicalCameraId.string(), width, streamInfo.width);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000365 ALOGE("%s: %s", __FUNCTION__, msg.string());
366 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
367 }
368 if (height != streamInfo.height) {
369 String8 msg = String8::format("Camera %s:Surface height doesn't match: %d vs %d",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800370 logicalCameraId.string(), height, streamInfo.height);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000371 ALOGE("%s: %s", __FUNCTION__, msg.string());
372 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
373 }
374 if (format != streamInfo.format) {
375 String8 msg = String8::format("Camera %s:Surface format doesn't match: %d vs %d",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800376 logicalCameraId.string(), format, streamInfo.format);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000377 ALOGE("%s: %s", __FUNCTION__, msg.string());
378 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
379 }
380 if (format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
381 if (dataSpace != streamInfo.dataSpace) {
382 String8 msg = String8::format("Camera %s:Surface dataSpace doesn't match: %d vs %d",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800383 logicalCameraId.string(), dataSpace, streamInfo.dataSpace);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000384 ALOGE("%s: %s", __FUNCTION__, msg.string());
385 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
386 }
387 //At the native side, there isn't a way to check whether 2 surfaces come from the same
388 //surface class type. Use usage flag to approximate the comparison.
389 if (consumerUsage != streamInfo.consumerUsage) {
390 String8 msg = String8::format(
391 "Camera %s:Surface usage flag doesn't match %" PRIu64 " vs %" PRIu64 "",
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800392 logicalCameraId.string(), consumerUsage, streamInfo.consumerUsage);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000393 ALOGE("%s: %s", __FUNCTION__, msg.string());
394 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
395 }
396 }
397 return binder::Status::ok();
398}
399
Austin Borgerea931242021-12-13 23:10:41 +0000400void mapStreamInfo(const OutputStreamInfo &streamInfo,
Emilian Peevf4816702020-04-03 15:44:51 -0700401 camera3::camera_stream_rotation_t rotation, String8 physicalId,
Shuzhen Wang83bff122020-11-20 15:51:39 -0800402 int32_t groupId, hardware::camera::device::V3_7::Stream *stream /*out*/) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000403 if (stream == nullptr) {
404 return;
405 }
406
Shuzhen Wang83bff122020-11-20 15:51:39 -0800407 stream->v3_4.v3_2.streamType = hardware::camera::device::V3_2::StreamType::OUTPUT;
408 stream->v3_4.v3_2.width = streamInfo.width;
409 stream->v3_4.v3_2.height = streamInfo.height;
410 stream->v3_4.v3_2.format = Camera3Device::mapToPixelFormat(streamInfo.format);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000411 auto u = streamInfo.consumerUsage;
412 camera3::Camera3OutputStream::applyZSLUsageQuirk(streamInfo.format, &u);
Shuzhen Wang83bff122020-11-20 15:51:39 -0800413 stream->v3_4.v3_2.usage = Camera3Device::mapToConsumerUsage(u);
414 stream->v3_4.v3_2.dataSpace = Camera3Device::mapToHidlDataspace(streamInfo.dataSpace);
415 stream->v3_4.v3_2.rotation = Camera3Device::mapToStreamRotation(rotation);
416 stream->v3_4.v3_2.id = -1; // Invalid stream id
417 stream->v3_4.physicalCameraId = std::string(physicalId.string());
418 stream->v3_4.bufferSize = 0;
419 stream->groupId = groupId;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800420 stream->sensorPixelModesUsed.resize(streamInfo.sensorPixelModesUsed.size());
421 size_t idx = 0;
422 for (auto mode : streamInfo.sensorPixelModesUsed) {
423 stream->sensorPixelModesUsed[idx++] =
424 static_cast<CameraMetadataEnumAndroidSensorPixelMode>(mode);
425 }
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000426}
427
Austin Borgerea931242021-12-13 23:10:41 +0000428binder::Status checkPhysicalCameraId(
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000429 const std::vector<std::string> &physicalCameraIds, const String8 &physicalCameraId,
430 const String8 &logicalCameraId) {
431 if (physicalCameraId.size() == 0) {
432 return binder::Status::ok();
433 }
434 if (std::find(physicalCameraIds.begin(), physicalCameraIds.end(),
435 physicalCameraId.string()) == physicalCameraIds.end()) {
436 String8 msg = String8::format("Camera %s: Camera doesn't support physicalCameraId %s.",
437 logicalCameraId.string(), physicalCameraId.string());
438 ALOGE("%s: %s", __FUNCTION__, msg.string());
439 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
440 }
441 return binder::Status::ok();
442}
443
Austin Borgerea931242021-12-13 23:10:41 +0000444binder::Status checkSurfaceType(size_t numBufferProducers,
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000445 bool deferredConsumer, int surfaceType) {
446 if (numBufferProducers > MAX_SURFACES_PER_STREAM) {
447 ALOGE("%s: GraphicBufferProducer count %zu for stream exceeds limit of %d",
448 __FUNCTION__, numBufferProducers, MAX_SURFACES_PER_STREAM);
449 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Surface count is too high");
450 } else if ((numBufferProducers == 0) && (!deferredConsumer)) {
451 ALOGE("%s: Number of consumers cannot be smaller than 1", __FUNCTION__);
452 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "No valid consumers.");
453 }
454
455 bool validSurfaceType = ((surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) ||
456 (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_TEXTURE));
457
458 if (deferredConsumer && !validSurfaceType) {
459 ALOGE("%s: Target surface has invalid surfaceType = %d.", __FUNCTION__, surfaceType);
460 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Target Surface is invalid");
461 }
462
463 return binder::Status::ok();
464}
465
Austin Borgerea931242021-12-13 23:10:41 +0000466binder::Status checkOperatingMode(int operatingMode,
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000467 const CameraMetadata &staticInfo, const String8 &cameraId) {
468 if (operatingMode < 0) {
469 String8 msg = String8::format(
470 "Camera %s: Invalid operating mode %d requested", cameraId.string(), operatingMode);
471 ALOGE("%s: %s", __FUNCTION__, msg.string());
472 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
473 msg.string());
474 }
475
476 bool isConstrainedHighSpeed = (operatingMode == ICameraDeviceUser::CONSTRAINED_HIGH_SPEED_MODE);
477 if (isConstrainedHighSpeed) {
478 camera_metadata_ro_entry_t entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
479 bool isConstrainedHighSpeedSupported = false;
480 for(size_t i = 0; i < entry.count; ++i) {
481 uint8_t capability = entry.data.u8[i];
482 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO) {
483 isConstrainedHighSpeedSupported = true;
484 break;
485 }
486 }
487 if (!isConstrainedHighSpeedSupported) {
488 String8 msg = String8::format(
489 "Camera %s: Try to create a constrained high speed configuration on a device"
490 " that doesn't support it.", cameraId.string());
491 ALOGE("%s: %s", __FUNCTION__, msg.string());
492 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
493 msg.string());
494 }
495 }
496
497 return binder::Status::ok();
498}
499
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800500binder::Status
Austin Borgerea931242021-12-13 23:10:41 +0000501convertToHALStreamCombination(
Jayant Chowdhary2bbdce42020-01-12 14:55:41 -0800502 const SessionConfiguration& sessionConfiguration,
503 const String8 &logicalCameraId, const CameraMetadata &deviceInfo,
504 metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
Shuzhen Wangd4abdf72021-05-28 11:22:50 -0700505 hardware::camera::device::V3_7::StreamConfiguration &streamConfiguration,
506 bool overrideForPerfClass, bool *earlyExit) {
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000507
508 auto operatingMode = sessionConfiguration.getOperatingMode();
509 binder::Status res = checkOperatingMode(operatingMode, deviceInfo, logicalCameraId);
510 if (!res.isOk()) {
511 return res;
512 }
513
514 if (earlyExit == nullptr) {
515 String8 msg("earlyExit nullptr");
516 ALOGE("%s: %s", __FUNCTION__, msg.string());
517 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
518 }
519 *earlyExit = false;
520 auto ret = Camera3Device::mapToStreamConfigurationMode(
Emilian Peevf4816702020-04-03 15:44:51 -0700521 static_cast<camera_stream_configuration_mode_t> (operatingMode),
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000522 /*out*/ &streamConfiguration.operationMode);
523 if (ret != OK) {
524 String8 msg = String8::format(
525 "Camera %s: Failed mapping operating mode %d requested: %s (%d)",
526 logicalCameraId.string(), operatingMode, strerror(-ret), ret);
527 ALOGE("%s: %s", __FUNCTION__, msg.string());
528 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
529 msg.string());
530 }
531
532 bool isInputValid = (sessionConfiguration.getInputWidth() > 0) &&
533 (sessionConfiguration.getInputHeight() > 0) &&
534 (sessionConfiguration.getInputFormat() > 0);
535 auto outputConfigs = sessionConfiguration.getOutputConfigurations();
536 size_t streamCount = outputConfigs.size();
537 streamCount = isInputValid ? streamCount + 1 : streamCount;
538 streamConfiguration.streams.resize(streamCount);
539 size_t streamIdx = 0;
540 if (isInputValid) {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800541 hardware::hidl_vec<CameraMetadataEnumAndroidSensorPixelMode> defaultSensorPixelModes;
542 defaultSensorPixelModes.resize(1);
543 defaultSensorPixelModes[0] =
544 static_cast<CameraMetadataEnumAndroidSensorPixelMode>(
545 ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
Shuzhen Wang83bff122020-11-20 15:51:39 -0800546 streamConfiguration.streams[streamIdx++] = {{{/*streamId*/0,
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000547 hardware::camera::device::V3_2::StreamType::INPUT,
548 static_cast<uint32_t> (sessionConfiguration.getInputWidth()),
549 static_cast<uint32_t> (sessionConfiguration.getInputHeight()),
550 Camera3Device::mapToPixelFormat(sessionConfiguration.getInputFormat()),
551 /*usage*/ 0, HAL_DATASPACE_UNKNOWN,
552 hardware::camera::device::V3_2::StreamRotation::ROTATION_0},
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800553 /*physicalId*/ nullptr, /*bufferSize*/0}, /*groupId*/-1, defaultSensorPixelModes};
Shuzhen Wang83bff122020-11-20 15:51:39 -0800554 streamConfiguration.multiResolutionInputImage =
555 sessionConfiguration.inputIsMultiResolution();
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000556 }
557
558 for (const auto &it : outputConfigs) {
559 const std::vector<sp<IGraphicBufferProducer>>& bufferProducers =
560 it.getGraphicBufferProducers();
561 bool deferredConsumer = it.isDeferred();
562 String8 physicalCameraId = String8(it.getPhysicalCameraId());
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800563
564 std::vector<int32_t> sensorPixelModesUsed = it.getSensorPixelModesUsed();
Shuzhen Wangd4abdf72021-05-28 11:22:50 -0700565 const CameraMetadata &physicalDeviceInfo = getMetadata(physicalCameraId,
566 overrideForPerfClass);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800567 const CameraMetadata &metadataChosen =
568 physicalCameraId.size() > 0 ? physicalDeviceInfo : deviceInfo;
569
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000570 size_t numBufferProducers = bufferProducers.size();
571 bool isStreamInfoValid = false;
Shuzhen Wang83bff122020-11-20 15:51:39 -0800572 int32_t groupId = it.isMultiResolution() ? it.getSurfaceSetID() : -1;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000573 OutputStreamInfo streamInfo;
574
575 res = checkSurfaceType(numBufferProducers, deferredConsumer, it.getSurfaceType());
576 if (!res.isOk()) {
577 return res;
578 }
579 res = checkPhysicalCameraId(physicalCameraIds, physicalCameraId,
580 logicalCameraId);
581 if (!res.isOk()) {
582 return res;
583 }
584
585 if (deferredConsumer) {
586 streamInfo.width = it.getWidth();
587 streamInfo.height = it.getHeight();
588 streamInfo.format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
589 streamInfo.dataSpace = android_dataspace_t::HAL_DATASPACE_UNKNOWN;
590 auto surfaceType = it.getSurfaceType();
591 streamInfo.consumerUsage = GraphicBuffer::USAGE_HW_TEXTURE;
592 if (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) {
593 streamInfo.consumerUsage |= GraphicBuffer::USAGE_HW_COMPOSER;
594 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800595 if (checkAndOverrideSensorPixelModesUsed(sensorPixelModesUsed,
596 streamInfo.format, streamInfo.width,
597 streamInfo.height, metadataChosen, false /*flexibleConsumer*/,
598 &streamInfo.sensorPixelModesUsed) != OK) {
599 ALOGE("%s: Deferred surface sensor pixel modes not valid",
600 __FUNCTION__);
601 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
602 "Deferred surface sensor pixel modes not valid");
603 }
Shuzhen Wang83bff122020-11-20 15:51:39 -0800604 mapStreamInfo(streamInfo, camera3::CAMERA_STREAM_ROTATION_0, physicalCameraId, groupId,
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000605 &streamConfiguration.streams[streamIdx++]);
606 isStreamInfoValid = true;
607
608 if (numBufferProducers == 0) {
609 continue;
610 }
611 }
612
613 for (auto& bufferProducer : bufferProducers) {
614 sp<Surface> surface;
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000615 res = createSurfaceFromGbp(streamInfo, isStreamInfoValid, surface, bufferProducer,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800616 logicalCameraId, metadataChosen, sensorPixelModesUsed);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000617
618 if (!res.isOk())
619 return res;
620
621 if (!isStreamInfoValid) {
622 bool isDepthCompositeStream =
623 camera3::DepthCompositeStream::isDepthCompositeStream(surface);
624 bool isHeicCompositeStream =
625 camera3::HeicCompositeStream::isHeicCompositeStream(surface);
626 if (isDepthCompositeStream || isHeicCompositeStream) {
627 // We need to take in to account that composite streams can have
628 // additional internal camera streams.
629 std::vector<OutputStreamInfo> compositeStreams;
630 if (isDepthCompositeStream) {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800631 // TODO: Take care of composite streams.
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000632 ret = camera3::DepthCompositeStream::getCompositeStreamInfo(streamInfo,
633 deviceInfo, &compositeStreams);
634 } else {
635 ret = camera3::HeicCompositeStream::getCompositeStreamInfo(streamInfo,
636 deviceInfo, &compositeStreams);
637 }
638 if (ret != OK) {
639 String8 msg = String8::format(
640 "Camera %s: Failed adding composite streams: %s (%d)",
641 logicalCameraId.string(), strerror(-ret), ret);
642 ALOGE("%s: %s", __FUNCTION__, msg.string());
643 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
644 }
645
646 if (compositeStreams.size() == 0) {
647 // No internal streams means composite stream not
648 // supported.
649 *earlyExit = true;
650 return binder::Status::ok();
651 } else if (compositeStreams.size() > 1) {
652 streamCount += compositeStreams.size() - 1;
653 streamConfiguration.streams.resize(streamCount);
654 }
655
656 for (const auto& compositeStream : compositeStreams) {
657 mapStreamInfo(compositeStream,
Emilian Peevf4816702020-04-03 15:44:51 -0700658 static_cast<camera_stream_rotation_t> (it.getRotation()),
Shuzhen Wang83bff122020-11-20 15:51:39 -0800659 physicalCameraId, groupId,
660 &streamConfiguration.streams[streamIdx++]);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000661 }
662 } else {
663 mapStreamInfo(streamInfo,
Emilian Peevf4816702020-04-03 15:44:51 -0700664 static_cast<camera_stream_rotation_t> (it.getRotation()),
Shuzhen Wang83bff122020-11-20 15:51:39 -0800665 physicalCameraId, groupId, &streamConfiguration.streams[streamIdx++]);
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000666 }
667 isStreamInfoValid = true;
668 }
669 }
670 }
671 return binder::Status::ok();
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800672}
Colin Crossb8a9dbb2020-08-27 04:12:26 +0000673
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800674static bool inStreamConfigurationMap(int format, int width, int height,
675 const std::unordered_map<int, std::vector<camera3::StreamConfiguration>> &sm) {
676 auto scs = sm.find(format);
677 if (scs == sm.end()) {
678 return false;
679 }
680 for (auto &sc : scs->second) {
681 if (sc.width == width && sc.height == height && sc.isInput == 0) {
682 return true;
683 }
684 }
685 return false;
686}
687
688static std::unordered_set<int32_t> convertToSet(const std::vector<int32_t> &sensorPixelModesUsed) {
689 return std::unordered_set<int32_t>(sensorPixelModesUsed.begin(), sensorPixelModesUsed.end());
690}
691
Austin Borgerea931242021-12-13 23:10:41 +0000692status_t checkAndOverrideSensorPixelModesUsed(
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800693 const std::vector<int32_t> &sensorPixelModesUsed, int format, int width, int height,
694 const CameraMetadata &staticInfo, bool flexibleConsumer,
695 std::unordered_set<int32_t> *overriddenSensorPixelModesUsed) {
Jayant Chowdhary84df28c2021-05-26 22:32:21 -0700696
697 const std::unordered_set<int32_t> &sensorPixelModesUsedSet =
698 convertToSet(sensorPixelModesUsed);
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800699 if (!isUltraHighResolutionSensor(staticInfo)) {
Jayant Chowdhary84df28c2021-05-26 22:32:21 -0700700 if (sensorPixelModesUsedSet.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
701 sensorPixelModesUsedSet.end()) {
702 // invalid value for non ultra high res sensors
703 return BAD_VALUE;
704 }
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800705 overriddenSensorPixelModesUsed->clear();
706 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
707 return OK;
708 }
709
710 StreamConfigurationPair streamConfigurationPair = getStreamConfigurationPair(staticInfo);
Jayant Chowdhary84df28c2021-05-26 22:32:21 -0700711
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800712 bool isInDefaultStreamConfigurationMap =
713 inStreamConfigurationMap(format, width, height,
714 streamConfigurationPair.mDefaultStreamConfigurationMap);
715
716 bool isInMaximumResolutionStreamConfigurationMap =
717 inStreamConfigurationMap(format, width, height,
718 streamConfigurationPair.mMaximumResolutionStreamConfigurationMap);
719
720 // Case 1: The client has not changed the sensor mode defaults. In this case, we check if the
721 // size + format of the OutputConfiguration is found exclusively in 1.
722 // If yes, add that sensorPixelMode to overriddenSensorPixelModes.
723 // If no, add 'DEFAULT' to sensorPixelMode. This maintains backwards
724 // compatibility.
725 if (sensorPixelModesUsedSet.size() == 0) {
726 // Ambiguous case, default to only 'DEFAULT' mode.
727 if (isInDefaultStreamConfigurationMap && isInMaximumResolutionStreamConfigurationMap) {
728 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
729 return OK;
730 }
731 // We don't allow flexible consumer for max resolution mode.
732 if (isInMaximumResolutionStreamConfigurationMap) {
733 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION);
734 return OK;
735 }
736 if (isInDefaultStreamConfigurationMap || (flexibleConsumer && width < ROUNDING_WIDTH_CAP)) {
737 overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
738 return OK;
739 }
740 return BAD_VALUE;
741 }
742
743 // Case2: The app has set sensorPixelModesUsed, we need to verify that they
744 // are valid / err out.
745 if (sensorPixelModesUsedSet.find(ANDROID_SENSOR_PIXEL_MODE_DEFAULT) !=
746 sensorPixelModesUsedSet.end() && !isInDefaultStreamConfigurationMap) {
747 return BAD_VALUE;
748 }
749
750 if (sensorPixelModesUsedSet.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
751 sensorPixelModesUsedSet.end() && !isInMaximumResolutionStreamConfigurationMap) {
752 return BAD_VALUE;
753 }
754 *overriddenSensorPixelModesUsed = sensorPixelModesUsedSet;
755 return OK;
756}
757
Austin Borgerea931242021-12-13 23:10:41 +0000758bool convertHALStreamCombinationFromV37ToV34(
Shuzhen Wang83bff122020-11-20 15:51:39 -0800759 hardware::camera::device::V3_4::StreamConfiguration &streamConfigV34,
760 const hardware::camera::device::V3_7::StreamConfiguration &streamConfigV37) {
761 if (streamConfigV37.multiResolutionInputImage) {
762 // ICameraDevice older than 3.7 doesn't support multi-resolution input image.
763 return false;
764 }
765
766 streamConfigV34.streams.resize(streamConfigV37.streams.size());
767 for (size_t i = 0; i < streamConfigV37.streams.size(); i++) {
768 if (streamConfigV37.streams[i].groupId != -1) {
769 // ICameraDevice older than 3.7 doesn't support multi-resolution output
770 // image
771 return false;
772 }
773 streamConfigV34.streams[i] = streamConfigV37.streams[i].v3_4;
774 }
775 streamConfigV34.operationMode = streamConfigV37.operationMode;
776 streamConfigV34.sessionParams = streamConfigV37.sessionParams;
777
778 return true;
779}
780
Austin Borgerea931242021-12-13 23:10:41 +0000781bool targetPerfClassPrimaryCamera(
Shuzhen Wangd4abdf72021-05-28 11:22:50 -0700782 const std::set<std::string>& perfClassPrimaryCameraIds, const std::string& cameraId,
783 int targetSdkVersion) {
784 bool isPerfClassPrimaryCamera =
785 perfClassPrimaryCameraIds.find(cameraId) != perfClassPrimaryCameraIds.end();
786 return targetSdkVersion >= SDK_VERSION_S && isPerfClassPrimaryCamera;
787}
788
Austin Borgerea931242021-12-13 23:10:41 +0000789} // namespace SessionConfigurationUtils
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800790} // namespace camera3
791} // namespace android