1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker * Copyright 2023 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker *
4*ec779b8eSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker *
8*ec779b8eSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker *
10*ec779b8eSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker */
16*ec779b8eSAndroid Build Coastguard Worker
17*ec779b8eSAndroid Build Coastguard Worker // #define LOG_NDEBUG 0
18*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "VirtualCameraDevice"
19*ec779b8eSAndroid Build Coastguard Worker #include "VirtualCameraDevice.h"
20*ec779b8eSAndroid Build Coastguard Worker
21*ec779b8eSAndroid Build Coastguard Worker #include <algorithm>
22*ec779b8eSAndroid Build Coastguard Worker #include <array>
23*ec779b8eSAndroid Build Coastguard Worker #include <chrono>
24*ec779b8eSAndroid Build Coastguard Worker #include <cstdint>
25*ec779b8eSAndroid Build Coastguard Worker #include <iterator>
26*ec779b8eSAndroid Build Coastguard Worker #include <numeric>
27*ec779b8eSAndroid Build Coastguard Worker #include <optional>
28*ec779b8eSAndroid Build Coastguard Worker #include <string>
29*ec779b8eSAndroid Build Coastguard Worker #include <vector>
30*ec779b8eSAndroid Build Coastguard Worker
31*ec779b8eSAndroid Build Coastguard Worker #include "VirtualCameraService.h"
32*ec779b8eSAndroid Build Coastguard Worker #include "VirtualCameraSession.h"
33*ec779b8eSAndroid Build Coastguard Worker #include "aidl/android/companion/virtualcamera/SupportedStreamConfiguration.h"
34*ec779b8eSAndroid Build Coastguard Worker #include "aidl/android/companion/virtualcamera/VirtualCameraConfiguration.h"
35*ec779b8eSAndroid Build Coastguard Worker #include "aidl/android/hardware/camera/common/Status.h"
36*ec779b8eSAndroid Build Coastguard Worker #include "aidl/android/hardware/camera/device/CameraMetadata.h"
37*ec779b8eSAndroid Build Coastguard Worker #include "aidl/android/hardware/camera/device/StreamConfiguration.h"
38*ec779b8eSAndroid Build Coastguard Worker #include "android/binder_auto_utils.h"
39*ec779b8eSAndroid Build Coastguard Worker #include "android/binder_status.h"
40*ec779b8eSAndroid Build Coastguard Worker #include "log/log.h"
41*ec779b8eSAndroid Build Coastguard Worker #include "system/camera_metadata.h"
42*ec779b8eSAndroid Build Coastguard Worker #include "util/MetadataUtil.h"
43*ec779b8eSAndroid Build Coastguard Worker #include "util/Util.h"
44*ec779b8eSAndroid Build Coastguard Worker
45*ec779b8eSAndroid Build Coastguard Worker namespace android {
46*ec779b8eSAndroid Build Coastguard Worker namespace companion {
47*ec779b8eSAndroid Build Coastguard Worker namespace virtualcamera {
48*ec779b8eSAndroid Build Coastguard Worker
49*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::companion::virtualcamera::Format;
50*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::companion::virtualcamera::IVirtualCameraCallback;
51*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::companion::virtualcamera::LensFacing;
52*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::companion::virtualcamera::SensorOrientation;
53*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::companion::virtualcamera::SupportedStreamConfiguration;
54*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::companion::virtualcamera::VirtualCameraConfiguration;
55*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::camera::common::CameraResourceCost;
56*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::camera::common::Status;
57*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::camera::device::CameraMetadata;
58*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::camera::device::ICameraDeviceCallback;
59*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::camera::device::ICameraDeviceSession;
60*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::camera::device::ICameraInjectionSession;
61*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::camera::device::Stream;
62*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::camera::device::StreamConfiguration;
63*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::camera::device::StreamRotation;
64*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::camera::device::StreamType;
65*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::graphics::common::PixelFormat;
66*ec779b8eSAndroid Build Coastguard Worker
67*ec779b8eSAndroid Build Coastguard Worker namespace {
68*ec779b8eSAndroid Build Coastguard Worker
69*ec779b8eSAndroid Build Coastguard Worker using namespace std::chrono_literals;
70*ec779b8eSAndroid Build Coastguard Worker
71*ec779b8eSAndroid Build Coastguard Worker // Prefix of camera name - "[email protected]/virtual/{camera_id}"
72*ec779b8eSAndroid Build Coastguard Worker const char* kDevicePathPrefix = "[email protected]/virtual/";
73*ec779b8eSAndroid Build Coastguard Worker
74*ec779b8eSAndroid Build Coastguard Worker constexpr int32_t kMaxJpegSize = 3 * 1024 * 1024 /*3MiB*/;
75*ec779b8eSAndroid Build Coastguard Worker
76*ec779b8eSAndroid Build Coastguard Worker constexpr std::chrono::nanoseconds kMaxFrameDuration =
77*ec779b8eSAndroid Build Coastguard Worker std::chrono::duration_cast<std::chrono::nanoseconds>(
78*ec779b8eSAndroid Build Coastguard Worker 1e9ns / VirtualCameraDevice::kMinFps);
79*ec779b8eSAndroid Build Coastguard Worker
80*ec779b8eSAndroid Build Coastguard Worker constexpr uint8_t kPipelineMaxDepth = 2;
81*ec779b8eSAndroid Build Coastguard Worker
82*ec779b8eSAndroid Build Coastguard Worker constexpr int k30Fps = 30;
83*ec779b8eSAndroid Build Coastguard Worker
84*ec779b8eSAndroid Build Coastguard Worker constexpr MetadataBuilder::ControlRegion kDefaultEmptyControlRegion{};
85*ec779b8eSAndroid Build Coastguard Worker
86*ec779b8eSAndroid Build Coastguard Worker const std::array<Resolution, 5> kStandardJpegThumbnailSizes{
87*ec779b8eSAndroid Build Coastguard Worker Resolution(176, 144), Resolution(240, 144), Resolution(256, 144),
88*ec779b8eSAndroid Build Coastguard Worker Resolution(240, 160), Resolution(240, 180)};
89*ec779b8eSAndroid Build Coastguard Worker
90*ec779b8eSAndroid Build Coastguard Worker const std::array<PixelFormat, 3> kOutputFormats{
91*ec779b8eSAndroid Build Coastguard Worker PixelFormat::IMPLEMENTATION_DEFINED, PixelFormat::YCBCR_420_888,
92*ec779b8eSAndroid Build Coastguard Worker PixelFormat::BLOB};
93*ec779b8eSAndroid Build Coastguard Worker
94*ec779b8eSAndroid Build Coastguard Worker // The resolutions below will used to extend the set of supported output formats.
95*ec779b8eSAndroid Build Coastguard Worker // All resolutions with lower pixel count and same aspect ratio as some supported
96*ec779b8eSAndroid Build Coastguard Worker // input resolution will be added to the set of supported output resolutions.
97*ec779b8eSAndroid Build Coastguard Worker const std::array<Resolution, 10> kOutputResolutions{
98*ec779b8eSAndroid Build Coastguard Worker Resolution(320, 240), Resolution(640, 360), Resolution(640, 480),
99*ec779b8eSAndroid Build Coastguard Worker Resolution(720, 480), Resolution(720, 576), Resolution(800, 600),
100*ec779b8eSAndroid Build Coastguard Worker Resolution(1024, 576), Resolution(1280, 720), Resolution(1280, 960),
101*ec779b8eSAndroid Build Coastguard Worker Resolution(1280, 1080),
102*ec779b8eSAndroid Build Coastguard Worker };
103*ec779b8eSAndroid Build Coastguard Worker
getSupportedJpegThumbnailSizes(const std::vector<SupportedStreamConfiguration> & configs)104*ec779b8eSAndroid Build Coastguard Worker std::vector<Resolution> getSupportedJpegThumbnailSizes(
105*ec779b8eSAndroid Build Coastguard Worker const std::vector<SupportedStreamConfiguration>& configs) {
106*ec779b8eSAndroid Build Coastguard Worker auto isSupportedByAnyInputConfig =
107*ec779b8eSAndroid Build Coastguard Worker [&configs](const Resolution thumbnailResolution) {
108*ec779b8eSAndroid Build Coastguard Worker return std::any_of(
109*ec779b8eSAndroid Build Coastguard Worker configs.begin(), configs.end(),
110*ec779b8eSAndroid Build Coastguard Worker [thumbnailResolution](const SupportedStreamConfiguration& config) {
111*ec779b8eSAndroid Build Coastguard Worker return isApproximatellySameAspectRatio(
112*ec779b8eSAndroid Build Coastguard Worker thumbnailResolution, Resolution(config.width, config.height));
113*ec779b8eSAndroid Build Coastguard Worker });
114*ec779b8eSAndroid Build Coastguard Worker };
115*ec779b8eSAndroid Build Coastguard Worker
116*ec779b8eSAndroid Build Coastguard Worker std::vector<Resolution> supportedThumbnailSizes({Resolution(0, 0)});
117*ec779b8eSAndroid Build Coastguard Worker std::copy_if(kStandardJpegThumbnailSizes.begin(),
118*ec779b8eSAndroid Build Coastguard Worker kStandardJpegThumbnailSizes.end(),
119*ec779b8eSAndroid Build Coastguard Worker std::back_insert_iterator(supportedThumbnailSizes),
120*ec779b8eSAndroid Build Coastguard Worker isSupportedByAnyInputConfig);
121*ec779b8eSAndroid Build Coastguard Worker return supportedThumbnailSizes;
122*ec779b8eSAndroid Build Coastguard Worker }
123*ec779b8eSAndroid Build Coastguard Worker
isSupportedOutputFormat(const PixelFormat pixelFormat)124*ec779b8eSAndroid Build Coastguard Worker bool isSupportedOutputFormat(const PixelFormat pixelFormat) {
125*ec779b8eSAndroid Build Coastguard Worker return std::find(kOutputFormats.begin(), kOutputFormats.end(), pixelFormat) !=
126*ec779b8eSAndroid Build Coastguard Worker kOutputFormats.end();
127*ec779b8eSAndroid Build Coastguard Worker }
128*ec779b8eSAndroid Build Coastguard Worker
fpsRangesForInputConfig(const std::vector<SupportedStreamConfiguration> & configs)129*ec779b8eSAndroid Build Coastguard Worker std::vector<FpsRange> fpsRangesForInputConfig(
130*ec779b8eSAndroid Build Coastguard Worker const std::vector<SupportedStreamConfiguration>& configs) {
131*ec779b8eSAndroid Build Coastguard Worker std::set<FpsRange> availableRanges;
132*ec779b8eSAndroid Build Coastguard Worker
133*ec779b8eSAndroid Build Coastguard Worker for (const SupportedStreamConfiguration& config : configs) {
134*ec779b8eSAndroid Build Coastguard Worker availableRanges.insert(
135*ec779b8eSAndroid Build Coastguard Worker {.minFps = VirtualCameraDevice::kMinFps, .maxFps = config.maxFps});
136*ec779b8eSAndroid Build Coastguard Worker availableRanges.insert({.minFps = config.maxFps, .maxFps = config.maxFps});
137*ec779b8eSAndroid Build Coastguard Worker }
138*ec779b8eSAndroid Build Coastguard Worker
139*ec779b8eSAndroid Build Coastguard Worker if (std::any_of(configs.begin(), configs.end(),
140*ec779b8eSAndroid Build Coastguard Worker [](const SupportedStreamConfiguration& config) {
141*ec779b8eSAndroid Build Coastguard Worker return config.maxFps >= k30Fps;
142*ec779b8eSAndroid Build Coastguard Worker })) {
143*ec779b8eSAndroid Build Coastguard Worker // Extend the set of available ranges with (minFps <= 15, 30) & (30, 30) as
144*ec779b8eSAndroid Build Coastguard Worker // required by CDD.
145*ec779b8eSAndroid Build Coastguard Worker availableRanges.insert(
146*ec779b8eSAndroid Build Coastguard Worker {.minFps = VirtualCameraDevice::kMinFps, .maxFps = k30Fps});
147*ec779b8eSAndroid Build Coastguard Worker availableRanges.insert({.minFps = k30Fps, .maxFps = k30Fps});
148*ec779b8eSAndroid Build Coastguard Worker }
149*ec779b8eSAndroid Build Coastguard Worker
150*ec779b8eSAndroid Build Coastguard Worker return std::vector<FpsRange>(availableRanges.begin(), availableRanges.end());
151*ec779b8eSAndroid Build Coastguard Worker }
152*ec779b8eSAndroid Build Coastguard Worker
getMaxResolution(const std::vector<SupportedStreamConfiguration> & configs)153*ec779b8eSAndroid Build Coastguard Worker std::optional<Resolution> getMaxResolution(
154*ec779b8eSAndroid Build Coastguard Worker const std::vector<SupportedStreamConfiguration>& configs) {
155*ec779b8eSAndroid Build Coastguard Worker auto itMax = std::max_element(configs.begin(), configs.end(),
156*ec779b8eSAndroid Build Coastguard Worker [](const SupportedStreamConfiguration& a,
157*ec779b8eSAndroid Build Coastguard Worker const SupportedStreamConfiguration& b) {
158*ec779b8eSAndroid Build Coastguard Worker return a.width * b.height < a.width * b.height;
159*ec779b8eSAndroid Build Coastguard Worker });
160*ec779b8eSAndroid Build Coastguard Worker if (itMax == configs.end()) {
161*ec779b8eSAndroid Build Coastguard Worker ALOGE(
162*ec779b8eSAndroid Build Coastguard Worker "%s: empty vector of supported configurations, cannot find largest "
163*ec779b8eSAndroid Build Coastguard Worker "resolution.",
164*ec779b8eSAndroid Build Coastguard Worker __func__);
165*ec779b8eSAndroid Build Coastguard Worker return std::nullopt;
166*ec779b8eSAndroid Build Coastguard Worker }
167*ec779b8eSAndroid Build Coastguard Worker
168*ec779b8eSAndroid Build Coastguard Worker return Resolution(itMax->width, itMax->height);
169*ec779b8eSAndroid Build Coastguard Worker }
170*ec779b8eSAndroid Build Coastguard Worker
171*ec779b8eSAndroid Build Coastguard Worker // Returns a map of unique resolution to maximum maxFps for all streams with
172*ec779b8eSAndroid Build Coastguard Worker // that resolution.
getResolutionToMaxFpsMap(const std::vector<SupportedStreamConfiguration> & configs)173*ec779b8eSAndroid Build Coastguard Worker std::map<Resolution, int> getResolutionToMaxFpsMap(
174*ec779b8eSAndroid Build Coastguard Worker const std::vector<SupportedStreamConfiguration>& configs) {
175*ec779b8eSAndroid Build Coastguard Worker std::map<Resolution, int> resolutionToMaxFpsMap;
176*ec779b8eSAndroid Build Coastguard Worker
177*ec779b8eSAndroid Build Coastguard Worker for (const SupportedStreamConfiguration& config : configs) {
178*ec779b8eSAndroid Build Coastguard Worker Resolution resolution(config.width, config.height);
179*ec779b8eSAndroid Build Coastguard Worker if (resolutionToMaxFpsMap.find(resolution) == resolutionToMaxFpsMap.end()) {
180*ec779b8eSAndroid Build Coastguard Worker resolutionToMaxFpsMap[resolution] = config.maxFps;
181*ec779b8eSAndroid Build Coastguard Worker } else {
182*ec779b8eSAndroid Build Coastguard Worker int currentMaxFps = resolutionToMaxFpsMap[resolution];
183*ec779b8eSAndroid Build Coastguard Worker resolutionToMaxFpsMap[resolution] = std::max(currentMaxFps, config.maxFps);
184*ec779b8eSAndroid Build Coastguard Worker }
185*ec779b8eSAndroid Build Coastguard Worker }
186*ec779b8eSAndroid Build Coastguard Worker
187*ec779b8eSAndroid Build Coastguard Worker std::map<Resolution, int> additionalResolutionToMaxFpsMap;
188*ec779b8eSAndroid Build Coastguard Worker // Add additional resolutions we can support by downscaling input streams with
189*ec779b8eSAndroid Build Coastguard Worker // same aspect ratio.
190*ec779b8eSAndroid Build Coastguard Worker for (const Resolution& outputResolution : kOutputResolutions) {
191*ec779b8eSAndroid Build Coastguard Worker for (const auto& [resolution, maxFps] : resolutionToMaxFpsMap) {
192*ec779b8eSAndroid Build Coastguard Worker if (resolutionToMaxFpsMap.find(outputResolution) !=
193*ec779b8eSAndroid Build Coastguard Worker resolutionToMaxFpsMap.end()) {
194*ec779b8eSAndroid Build Coastguard Worker // Resolution is already in the map, skip it.
195*ec779b8eSAndroid Build Coastguard Worker continue;
196*ec779b8eSAndroid Build Coastguard Worker }
197*ec779b8eSAndroid Build Coastguard Worker
198*ec779b8eSAndroid Build Coastguard Worker if (outputResolution < resolution &&
199*ec779b8eSAndroid Build Coastguard Worker isApproximatellySameAspectRatio(outputResolution, resolution)) {
200*ec779b8eSAndroid Build Coastguard Worker // Lower resolution with same aspect ratio, we can achieve this by
201*ec779b8eSAndroid Build Coastguard Worker // downscaling, let's add it to the map.
202*ec779b8eSAndroid Build Coastguard Worker ALOGD(
203*ec779b8eSAndroid Build Coastguard Worker "Extending set of output resolutions with %dx%d which has same "
204*ec779b8eSAndroid Build Coastguard Worker "aspect ratio as supported input %dx%d.",
205*ec779b8eSAndroid Build Coastguard Worker outputResolution.width, outputResolution.height, resolution.width,
206*ec779b8eSAndroid Build Coastguard Worker resolution.height);
207*ec779b8eSAndroid Build Coastguard Worker additionalResolutionToMaxFpsMap[outputResolution] = maxFps;
208*ec779b8eSAndroid Build Coastguard Worker break;
209*ec779b8eSAndroid Build Coastguard Worker }
210*ec779b8eSAndroid Build Coastguard Worker }
211*ec779b8eSAndroid Build Coastguard Worker }
212*ec779b8eSAndroid Build Coastguard Worker
213*ec779b8eSAndroid Build Coastguard Worker // Add all resolution we can achieve by downscaling to the map.
214*ec779b8eSAndroid Build Coastguard Worker resolutionToMaxFpsMap.insert(additionalResolutionToMaxFpsMap.begin(),
215*ec779b8eSAndroid Build Coastguard Worker additionalResolutionToMaxFpsMap.end());
216*ec779b8eSAndroid Build Coastguard Worker
217*ec779b8eSAndroid Build Coastguard Worker return resolutionToMaxFpsMap;
218*ec779b8eSAndroid Build Coastguard Worker }
219*ec779b8eSAndroid Build Coastguard Worker
220*ec779b8eSAndroid Build Coastguard Worker // TODO(b/301023410) - Populate camera characteristics according to camera configuration.
initCameraCharacteristics(const std::vector<SupportedStreamConfiguration> & supportedInputConfig,const SensorOrientation sensorOrientation,const LensFacing lensFacing,const int32_t deviceId)221*ec779b8eSAndroid Build Coastguard Worker std::optional<CameraMetadata> initCameraCharacteristics(
222*ec779b8eSAndroid Build Coastguard Worker const std::vector<SupportedStreamConfiguration>& supportedInputConfig,
223*ec779b8eSAndroid Build Coastguard Worker const SensorOrientation sensorOrientation, const LensFacing lensFacing,
224*ec779b8eSAndroid Build Coastguard Worker const int32_t deviceId) {
225*ec779b8eSAndroid Build Coastguard Worker if (!std::all_of(supportedInputConfig.begin(), supportedInputConfig.end(),
226*ec779b8eSAndroid Build Coastguard Worker [](const SupportedStreamConfiguration& config) {
227*ec779b8eSAndroid Build Coastguard Worker return isFormatSupportedForInput(
228*ec779b8eSAndroid Build Coastguard Worker config.width, config.height, config.pixelFormat,
229*ec779b8eSAndroid Build Coastguard Worker config.maxFps);
230*ec779b8eSAndroid Build Coastguard Worker })) {
231*ec779b8eSAndroid Build Coastguard Worker ALOGE("%s: input configuration contains unsupported format", __func__);
232*ec779b8eSAndroid Build Coastguard Worker return std::nullopt;
233*ec779b8eSAndroid Build Coastguard Worker }
234*ec779b8eSAndroid Build Coastguard Worker
235*ec779b8eSAndroid Build Coastguard Worker MetadataBuilder builder =
236*ec779b8eSAndroid Build Coastguard Worker MetadataBuilder()
237*ec779b8eSAndroid Build Coastguard Worker .setSupportedHardwareLevel(
238*ec779b8eSAndroid Build Coastguard Worker ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL)
239*ec779b8eSAndroid Build Coastguard Worker .setDeviceId(deviceId)
240*ec779b8eSAndroid Build Coastguard Worker .setFlashAvailable(false)
241*ec779b8eSAndroid Build Coastguard Worker .setLensFacing(
242*ec779b8eSAndroid Build Coastguard Worker static_cast<camera_metadata_enum_android_lens_facing>(lensFacing))
243*ec779b8eSAndroid Build Coastguard Worker .setAvailableFocalLengths({VirtualCameraDevice::kFocalLength})
244*ec779b8eSAndroid Build Coastguard Worker .setSensorOrientation(static_cast<int32_t>(sensorOrientation))
245*ec779b8eSAndroid Build Coastguard Worker .setSensorReadoutTimestamp(
246*ec779b8eSAndroid Build Coastguard Worker ANDROID_SENSOR_READOUT_TIMESTAMP_NOT_SUPPORTED)
247*ec779b8eSAndroid Build Coastguard Worker .setSensorTimestampSource(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN)
248*ec779b8eSAndroid Build Coastguard Worker .setSensorPhysicalSize(36.0, 24.0)
249*ec779b8eSAndroid Build Coastguard Worker .setAvailableAberrationCorrectionModes(
250*ec779b8eSAndroid Build Coastguard Worker {ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF})
251*ec779b8eSAndroid Build Coastguard Worker .setAvailableNoiseReductionModes({ANDROID_NOISE_REDUCTION_MODE_OFF})
252*ec779b8eSAndroid Build Coastguard Worker .setAvailableFaceDetectModes({ANDROID_STATISTICS_FACE_DETECT_MODE_OFF})
253*ec779b8eSAndroid Build Coastguard Worker .setAvailableStreamUseCases(
254*ec779b8eSAndroid Build Coastguard Worker {ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
255*ec779b8eSAndroid Build Coastguard Worker ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW,
256*ec779b8eSAndroid Build Coastguard Worker ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_STILL_CAPTURE,
257*ec779b8eSAndroid Build Coastguard Worker ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_RECORD,
258*ec779b8eSAndroid Build Coastguard Worker ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW_VIDEO_STILL,
259*ec779b8eSAndroid Build Coastguard Worker ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_CALL})
260*ec779b8eSAndroid Build Coastguard Worker .setAvailableTestPatternModes({ANDROID_SENSOR_TEST_PATTERN_MODE_OFF})
261*ec779b8eSAndroid Build Coastguard Worker .setAvailableMaxDigitalZoom(1.0)
262*ec779b8eSAndroid Build Coastguard Worker .setControlAvailableModes({ANDROID_CONTROL_MODE_AUTO})
263*ec779b8eSAndroid Build Coastguard Worker .setControlAfAvailableModes({ANDROID_CONTROL_AF_MODE_OFF})
264*ec779b8eSAndroid Build Coastguard Worker .setControlAvailableSceneModes({ANDROID_CONTROL_SCENE_MODE_DISABLED})
265*ec779b8eSAndroid Build Coastguard Worker .setControlAvailableEffects({ANDROID_CONTROL_EFFECT_MODE_OFF})
266*ec779b8eSAndroid Build Coastguard Worker .setControlAvailableVideoStabilizationModes(
267*ec779b8eSAndroid Build Coastguard Worker {ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF})
268*ec779b8eSAndroid Build Coastguard Worker .setControlAeAvailableModes({ANDROID_CONTROL_AE_MODE_ON})
269*ec779b8eSAndroid Build Coastguard Worker .setControlAeAvailableAntibandingModes(
270*ec779b8eSAndroid Build Coastguard Worker {ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO})
271*ec779b8eSAndroid Build Coastguard Worker .setControlAeAvailableFpsRanges(
272*ec779b8eSAndroid Build Coastguard Worker fpsRangesForInputConfig(supportedInputConfig))
273*ec779b8eSAndroid Build Coastguard Worker .setControlMaxRegions(0, 0, 0)
274*ec779b8eSAndroid Build Coastguard Worker .setControlAfRegions({kDefaultEmptyControlRegion})
275*ec779b8eSAndroid Build Coastguard Worker .setControlAeRegions({kDefaultEmptyControlRegion})
276*ec779b8eSAndroid Build Coastguard Worker .setControlAwbRegions({kDefaultEmptyControlRegion})
277*ec779b8eSAndroid Build Coastguard Worker .setControlAeCompensationRange(0, 0)
278*ec779b8eSAndroid Build Coastguard Worker .setControlAeCompensationStep(camera_metadata_rational_t{0, 1})
279*ec779b8eSAndroid Build Coastguard Worker .setControlAwbLockAvailable(false)
280*ec779b8eSAndroid Build Coastguard Worker .setControlAeLockAvailable(false)
281*ec779b8eSAndroid Build Coastguard Worker .setControlAvailableAwbModes({ANDROID_CONTROL_AWB_MODE_AUTO})
282*ec779b8eSAndroid Build Coastguard Worker .setControlZoomRatioRange(/*min=*/1.0, /*max=*/1.0)
283*ec779b8eSAndroid Build Coastguard Worker .setCroppingType(ANDROID_SCALER_CROPPING_TYPE_CENTER_ONLY)
284*ec779b8eSAndroid Build Coastguard Worker .setJpegAvailableThumbnailSizes(
285*ec779b8eSAndroid Build Coastguard Worker getSupportedJpegThumbnailSizes(supportedInputConfig))
286*ec779b8eSAndroid Build Coastguard Worker .setMaxJpegSize(kMaxJpegSize)
287*ec779b8eSAndroid Build Coastguard Worker .setMaxFaceCount(0)
288*ec779b8eSAndroid Build Coastguard Worker .setMaxFrameDuration(kMaxFrameDuration)
289*ec779b8eSAndroid Build Coastguard Worker .setMaxNumberOutputStreams(
290*ec779b8eSAndroid Build Coastguard Worker VirtualCameraDevice::kMaxNumberOfRawStreams,
291*ec779b8eSAndroid Build Coastguard Worker VirtualCameraDevice::kMaxNumberOfProcessedStreams,
292*ec779b8eSAndroid Build Coastguard Worker VirtualCameraDevice::kMaxNumberOfStallStreams)
293*ec779b8eSAndroid Build Coastguard Worker .setRequestPartialResultCount(1)
294*ec779b8eSAndroid Build Coastguard Worker .setPipelineMaxDepth(kPipelineMaxDepth)
295*ec779b8eSAndroid Build Coastguard Worker .setSyncMaxLatency(ANDROID_SYNC_MAX_LATENCY_UNKNOWN)
296*ec779b8eSAndroid Build Coastguard Worker .setAvailableRequestKeys({ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
297*ec779b8eSAndroid Build Coastguard Worker ANDROID_CONTROL_CAPTURE_INTENT,
298*ec779b8eSAndroid Build Coastguard Worker ANDROID_CONTROL_AE_MODE,
299*ec779b8eSAndroid Build Coastguard Worker ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
300*ec779b8eSAndroid Build Coastguard Worker ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
301*ec779b8eSAndroid Build Coastguard Worker ANDROID_CONTROL_AE_ANTIBANDING_MODE,
302*ec779b8eSAndroid Build Coastguard Worker ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
303*ec779b8eSAndroid Build Coastguard Worker ANDROID_CONTROL_AF_TRIGGER,
304*ec779b8eSAndroid Build Coastguard Worker ANDROID_CONTROL_AF_MODE,
305*ec779b8eSAndroid Build Coastguard Worker ANDROID_CONTROL_AWB_MODE,
306*ec779b8eSAndroid Build Coastguard Worker ANDROID_SCALER_CROP_REGION,
307*ec779b8eSAndroid Build Coastguard Worker ANDROID_CONTROL_EFFECT_MODE,
308*ec779b8eSAndroid Build Coastguard Worker ANDROID_CONTROL_MODE,
309*ec779b8eSAndroid Build Coastguard Worker ANDROID_CONTROL_SCENE_MODE,
310*ec779b8eSAndroid Build Coastguard Worker ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
311*ec779b8eSAndroid Build Coastguard Worker ANDROID_CONTROL_ZOOM_RATIO,
312*ec779b8eSAndroid Build Coastguard Worker ANDROID_FLASH_MODE,
313*ec779b8eSAndroid Build Coastguard Worker ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
314*ec779b8eSAndroid Build Coastguard Worker ANDROID_JPEG_ORIENTATION,
315*ec779b8eSAndroid Build Coastguard Worker ANDROID_JPEG_QUALITY,
316*ec779b8eSAndroid Build Coastguard Worker ANDROID_JPEG_THUMBNAIL_QUALITY,
317*ec779b8eSAndroid Build Coastguard Worker ANDROID_JPEG_THUMBNAIL_SIZE,
318*ec779b8eSAndroid Build Coastguard Worker ANDROID_NOISE_REDUCTION_MODE,
319*ec779b8eSAndroid Build Coastguard Worker ANDROID_STATISTICS_FACE_DETECT_MODE})
320*ec779b8eSAndroid Build Coastguard Worker .setAvailableResultKeys({
321*ec779b8eSAndroid Build Coastguard Worker ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
322*ec779b8eSAndroid Build Coastguard Worker ANDROID_CONTROL_AE_ANTIBANDING_MODE,
323*ec779b8eSAndroid Build Coastguard Worker ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
324*ec779b8eSAndroid Build Coastguard Worker ANDROID_CONTROL_AE_LOCK,
325*ec779b8eSAndroid Build Coastguard Worker ANDROID_CONTROL_AE_MODE,
326*ec779b8eSAndroid Build Coastguard Worker ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
327*ec779b8eSAndroid Build Coastguard Worker ANDROID_CONTROL_AE_STATE,
328*ec779b8eSAndroid Build Coastguard Worker ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
329*ec779b8eSAndroid Build Coastguard Worker ANDROID_CONTROL_AF_MODE,
330*ec779b8eSAndroid Build Coastguard Worker ANDROID_CONTROL_AF_STATE,
331*ec779b8eSAndroid Build Coastguard Worker ANDROID_CONTROL_AF_TRIGGER,
332*ec779b8eSAndroid Build Coastguard Worker ANDROID_CONTROL_AWB_LOCK,
333*ec779b8eSAndroid Build Coastguard Worker ANDROID_CONTROL_AWB_MODE,
334*ec779b8eSAndroid Build Coastguard Worker ANDROID_CONTROL_AWB_STATE,
335*ec779b8eSAndroid Build Coastguard Worker ANDROID_CONTROL_CAPTURE_INTENT,
336*ec779b8eSAndroid Build Coastguard Worker ANDROID_CONTROL_EFFECT_MODE,
337*ec779b8eSAndroid Build Coastguard Worker ANDROID_CONTROL_MODE,
338*ec779b8eSAndroid Build Coastguard Worker ANDROID_CONTROL_SCENE_MODE,
339*ec779b8eSAndroid Build Coastguard Worker ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
340*ec779b8eSAndroid Build Coastguard Worker ANDROID_STATISTICS_FACE_DETECT_MODE,
341*ec779b8eSAndroid Build Coastguard Worker ANDROID_FLASH_MODE,
342*ec779b8eSAndroid Build Coastguard Worker ANDROID_FLASH_STATE,
343*ec779b8eSAndroid Build Coastguard Worker ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
344*ec779b8eSAndroid Build Coastguard Worker ANDROID_JPEG_QUALITY,
345*ec779b8eSAndroid Build Coastguard Worker ANDROID_JPEG_THUMBNAIL_QUALITY,
346*ec779b8eSAndroid Build Coastguard Worker ANDROID_LENS_FOCAL_LENGTH,
347*ec779b8eSAndroid Build Coastguard Worker ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
348*ec779b8eSAndroid Build Coastguard Worker ANDROID_NOISE_REDUCTION_MODE,
349*ec779b8eSAndroid Build Coastguard Worker ANDROID_REQUEST_PIPELINE_DEPTH,
350*ec779b8eSAndroid Build Coastguard Worker ANDROID_SENSOR_TIMESTAMP,
351*ec779b8eSAndroid Build Coastguard Worker ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE,
352*ec779b8eSAndroid Build Coastguard Worker ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
353*ec779b8eSAndroid Build Coastguard Worker ANDROID_STATISTICS_SCENE_FLICKER,
354*ec779b8eSAndroid Build Coastguard Worker })
355*ec779b8eSAndroid Build Coastguard Worker .setAvailableCapabilities(
356*ec779b8eSAndroid Build Coastguard Worker {ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE});
357*ec779b8eSAndroid Build Coastguard Worker
358*ec779b8eSAndroid Build Coastguard Worker // Active array size must correspond to largest supported input resolution.
359*ec779b8eSAndroid Build Coastguard Worker std::optional<Resolution> maxResolution =
360*ec779b8eSAndroid Build Coastguard Worker getMaxResolution(supportedInputConfig);
361*ec779b8eSAndroid Build Coastguard Worker if (!maxResolution.has_value()) {
362*ec779b8eSAndroid Build Coastguard Worker return std::nullopt;
363*ec779b8eSAndroid Build Coastguard Worker }
364*ec779b8eSAndroid Build Coastguard Worker builder.setSensorActiveArraySize(0, 0, maxResolution->width,
365*ec779b8eSAndroid Build Coastguard Worker maxResolution->height);
366*ec779b8eSAndroid Build Coastguard Worker builder.setSensorPixelArraySize(maxResolution->width, maxResolution->height);
367*ec779b8eSAndroid Build Coastguard Worker
368*ec779b8eSAndroid Build Coastguard Worker std::vector<MetadataBuilder::StreamConfiguration> outputConfigurations;
369*ec779b8eSAndroid Build Coastguard Worker
370*ec779b8eSAndroid Build Coastguard Worker // TODO(b/301023410) Add also all "standard" resolutions we can rescale the
371*ec779b8eSAndroid Build Coastguard Worker // streams to (all standard resolutions with same aspect ratio).
372*ec779b8eSAndroid Build Coastguard Worker
373*ec779b8eSAndroid Build Coastguard Worker std::map<Resolution, int> resolutionToMaxFpsMap =
374*ec779b8eSAndroid Build Coastguard Worker getResolutionToMaxFpsMap(supportedInputConfig);
375*ec779b8eSAndroid Build Coastguard Worker
376*ec779b8eSAndroid Build Coastguard Worker // Add configurations for all unique input resolutions and output formats.
377*ec779b8eSAndroid Build Coastguard Worker for (const PixelFormat format : kOutputFormats) {
378*ec779b8eSAndroid Build Coastguard Worker std::transform(
379*ec779b8eSAndroid Build Coastguard Worker resolutionToMaxFpsMap.begin(), resolutionToMaxFpsMap.end(),
380*ec779b8eSAndroid Build Coastguard Worker std::back_inserter(outputConfigurations), [format](const auto& entry) {
381*ec779b8eSAndroid Build Coastguard Worker Resolution resolution = entry.first;
382*ec779b8eSAndroid Build Coastguard Worker int maxFps = entry.second;
383*ec779b8eSAndroid Build Coastguard Worker return MetadataBuilder::StreamConfiguration{
384*ec779b8eSAndroid Build Coastguard Worker .width = resolution.width,
385*ec779b8eSAndroid Build Coastguard Worker .height = resolution.height,
386*ec779b8eSAndroid Build Coastguard Worker .format = static_cast<int32_t>(format),
387*ec779b8eSAndroid Build Coastguard Worker .minFrameDuration = std::chrono::nanoseconds(1s) / maxFps,
388*ec779b8eSAndroid Build Coastguard Worker .minStallDuration = 0s};
389*ec779b8eSAndroid Build Coastguard Worker });
390*ec779b8eSAndroid Build Coastguard Worker }
391*ec779b8eSAndroid Build Coastguard Worker
392*ec779b8eSAndroid Build Coastguard Worker ALOGV("Adding %zu output configurations", outputConfigurations.size());
393*ec779b8eSAndroid Build Coastguard Worker builder.setAvailableOutputStreamConfigurations(outputConfigurations);
394*ec779b8eSAndroid Build Coastguard Worker
395*ec779b8eSAndroid Build Coastguard Worker auto metadata = builder.setAvailableCharacteristicKeys().build();
396*ec779b8eSAndroid Build Coastguard Worker if (metadata == nullptr) {
397*ec779b8eSAndroid Build Coastguard Worker ALOGE("Failed to build metadata!");
398*ec779b8eSAndroid Build Coastguard Worker return CameraMetadata();
399*ec779b8eSAndroid Build Coastguard Worker }
400*ec779b8eSAndroid Build Coastguard Worker
401*ec779b8eSAndroid Build Coastguard Worker return std::move(*metadata);
402*ec779b8eSAndroid Build Coastguard Worker }
403*ec779b8eSAndroid Build Coastguard Worker
404*ec779b8eSAndroid Build Coastguard Worker } // namespace
405*ec779b8eSAndroid Build Coastguard Worker
VirtualCameraDevice(const std::string & cameraId,const VirtualCameraConfiguration & configuration,int32_t deviceId)406*ec779b8eSAndroid Build Coastguard Worker VirtualCameraDevice::VirtualCameraDevice(
407*ec779b8eSAndroid Build Coastguard Worker const std::string& cameraId,
408*ec779b8eSAndroid Build Coastguard Worker const VirtualCameraConfiguration& configuration, int32_t deviceId)
409*ec779b8eSAndroid Build Coastguard Worker : mCameraId(cameraId),
410*ec779b8eSAndroid Build Coastguard Worker mVirtualCameraClientCallback(configuration.virtualCameraCallback),
411*ec779b8eSAndroid Build Coastguard Worker mSupportedInputConfigurations(configuration.supportedStreamConfigs) {
412*ec779b8eSAndroid Build Coastguard Worker std::optional<CameraMetadata> metadata = initCameraCharacteristics(
413*ec779b8eSAndroid Build Coastguard Worker mSupportedInputConfigurations, configuration.sensorOrientation,
414*ec779b8eSAndroid Build Coastguard Worker configuration.lensFacing, deviceId);
415*ec779b8eSAndroid Build Coastguard Worker if (metadata.has_value()) {
416*ec779b8eSAndroid Build Coastguard Worker mCameraCharacteristics = *metadata;
417*ec779b8eSAndroid Build Coastguard Worker } else {
418*ec779b8eSAndroid Build Coastguard Worker ALOGE(
419*ec779b8eSAndroid Build Coastguard Worker "%s: Failed to initialize camera characteristic based on provided "
420*ec779b8eSAndroid Build Coastguard Worker "configuration.",
421*ec779b8eSAndroid Build Coastguard Worker __func__);
422*ec779b8eSAndroid Build Coastguard Worker }
423*ec779b8eSAndroid Build Coastguard Worker }
424*ec779b8eSAndroid Build Coastguard Worker
getCameraCharacteristics(CameraMetadata * _aidl_return)425*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus VirtualCameraDevice::getCameraCharacteristics(
426*ec779b8eSAndroid Build Coastguard Worker CameraMetadata* _aidl_return) {
427*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
428*ec779b8eSAndroid Build Coastguard Worker if (_aidl_return == nullptr) {
429*ec779b8eSAndroid Build Coastguard Worker return cameraStatus(Status::ILLEGAL_ARGUMENT);
430*ec779b8eSAndroid Build Coastguard Worker }
431*ec779b8eSAndroid Build Coastguard Worker
432*ec779b8eSAndroid Build Coastguard Worker *_aidl_return = mCameraCharacteristics;
433*ec779b8eSAndroid Build Coastguard Worker return ndk::ScopedAStatus::ok();
434*ec779b8eSAndroid Build Coastguard Worker }
435*ec779b8eSAndroid Build Coastguard Worker
getPhysicalCameraCharacteristics(const std::string & in_physicalCameraId,CameraMetadata * _aidl_return)436*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus VirtualCameraDevice::getPhysicalCameraCharacteristics(
437*ec779b8eSAndroid Build Coastguard Worker const std::string& in_physicalCameraId, CameraMetadata* _aidl_return) {
438*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s: physicalCameraId %s", __func__, in_physicalCameraId.c_str());
439*ec779b8eSAndroid Build Coastguard Worker (void)_aidl_return;
440*ec779b8eSAndroid Build Coastguard Worker
441*ec779b8eSAndroid Build Coastguard Worker // VTS tests expect this call to fail with illegal argument status for
442*ec779b8eSAndroid Build Coastguard Worker // all publicly advertised camera ids.
443*ec779b8eSAndroid Build Coastguard Worker // Because we don't support physical camera ids, we just always
444*ec779b8eSAndroid Build Coastguard Worker // fail with illegal argument (there's no valid argument to provide).
445*ec779b8eSAndroid Build Coastguard Worker return cameraStatus(Status::ILLEGAL_ARGUMENT);
446*ec779b8eSAndroid Build Coastguard Worker }
447*ec779b8eSAndroid Build Coastguard Worker
getResourceCost(CameraResourceCost * _aidl_return)448*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus VirtualCameraDevice::getResourceCost(
449*ec779b8eSAndroid Build Coastguard Worker CameraResourceCost* _aidl_return) {
450*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
451*ec779b8eSAndroid Build Coastguard Worker if (_aidl_return == nullptr) {
452*ec779b8eSAndroid Build Coastguard Worker return cameraStatus(Status::ILLEGAL_ARGUMENT);
453*ec779b8eSAndroid Build Coastguard Worker }
454*ec779b8eSAndroid Build Coastguard Worker _aidl_return->resourceCost = 100; // ¯\_(ツ)_/¯
455*ec779b8eSAndroid Build Coastguard Worker return ndk::ScopedAStatus::ok();
456*ec779b8eSAndroid Build Coastguard Worker }
457*ec779b8eSAndroid Build Coastguard Worker
isStreamCombinationSupported(const StreamConfiguration & in_streams,bool * _aidl_return)458*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus VirtualCameraDevice::isStreamCombinationSupported(
459*ec779b8eSAndroid Build Coastguard Worker const StreamConfiguration& in_streams, bool* _aidl_return) {
460*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
461*ec779b8eSAndroid Build Coastguard Worker
462*ec779b8eSAndroid Build Coastguard Worker if (_aidl_return == nullptr) {
463*ec779b8eSAndroid Build Coastguard Worker return cameraStatus(Status::ILLEGAL_ARGUMENT);
464*ec779b8eSAndroid Build Coastguard Worker }
465*ec779b8eSAndroid Build Coastguard Worker
466*ec779b8eSAndroid Build Coastguard Worker *_aidl_return = isStreamCombinationSupported(in_streams);
467*ec779b8eSAndroid Build Coastguard Worker return ndk::ScopedAStatus::ok();
468*ec779b8eSAndroid Build Coastguard Worker };
469*ec779b8eSAndroid Build Coastguard Worker
isStreamCombinationSupported(const StreamConfiguration & streamConfiguration) const470*ec779b8eSAndroid Build Coastguard Worker bool VirtualCameraDevice::isStreamCombinationSupported(
471*ec779b8eSAndroid Build Coastguard Worker const StreamConfiguration& streamConfiguration) const {
472*ec779b8eSAndroid Build Coastguard Worker if (streamConfiguration.streams.empty()) {
473*ec779b8eSAndroid Build Coastguard Worker ALOGE("%s: Querying empty configuration", __func__);
474*ec779b8eSAndroid Build Coastguard Worker return false;
475*ec779b8eSAndroid Build Coastguard Worker }
476*ec779b8eSAndroid Build Coastguard Worker
477*ec779b8eSAndroid Build Coastguard Worker const std::vector<Stream>& streams = streamConfiguration.streams;
478*ec779b8eSAndroid Build Coastguard Worker
479*ec779b8eSAndroid Build Coastguard Worker Resolution firstStreamResolution(streams[0].width, streams[0].height);
480*ec779b8eSAndroid Build Coastguard Worker auto isSameAspectRatioAsFirst = [firstStreamResolution](const Stream& stream) {
481*ec779b8eSAndroid Build Coastguard Worker return isApproximatellySameAspectRatio(
482*ec779b8eSAndroid Build Coastguard Worker firstStreamResolution, Resolution(stream.width, stream.height));
483*ec779b8eSAndroid Build Coastguard Worker };
484*ec779b8eSAndroid Build Coastguard Worker if (!std::all_of(streams.begin(), streams.end(), isSameAspectRatioAsFirst)) {
485*ec779b8eSAndroid Build Coastguard Worker ALOGW(
486*ec779b8eSAndroid Build Coastguard Worker "%s: Requested streams do not have same aspect ratio. Different aspect "
487*ec779b8eSAndroid Build Coastguard Worker "ratios are currently "
488*ec779b8eSAndroid Build Coastguard Worker "not supported by virtual camera. Stream configuration: %s",
489*ec779b8eSAndroid Build Coastguard Worker __func__, streamConfiguration.toString().c_str());
490*ec779b8eSAndroid Build Coastguard Worker return false;
491*ec779b8eSAndroid Build Coastguard Worker }
492*ec779b8eSAndroid Build Coastguard Worker
493*ec779b8eSAndroid Build Coastguard Worker int numberOfProcessedStreams = 0;
494*ec779b8eSAndroid Build Coastguard Worker int numberOfStallStreams = 0;
495*ec779b8eSAndroid Build Coastguard Worker for (const Stream& stream : streamConfiguration.streams) {
496*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s: Configuration queried: %s", __func__, stream.toString().c_str());
497*ec779b8eSAndroid Build Coastguard Worker
498*ec779b8eSAndroid Build Coastguard Worker if (stream.streamType == StreamType::INPUT) {
499*ec779b8eSAndroid Build Coastguard Worker ALOGW("%s: Input stream type is not supported", __func__);
500*ec779b8eSAndroid Build Coastguard Worker return false;
501*ec779b8eSAndroid Build Coastguard Worker }
502*ec779b8eSAndroid Build Coastguard Worker
503*ec779b8eSAndroid Build Coastguard Worker if (stream.rotation != StreamRotation::ROTATION_0 ||
504*ec779b8eSAndroid Build Coastguard Worker !isSupportedOutputFormat(stream.format)) {
505*ec779b8eSAndroid Build Coastguard Worker ALOGV("Unsupported output stream type");
506*ec779b8eSAndroid Build Coastguard Worker return false;
507*ec779b8eSAndroid Build Coastguard Worker }
508*ec779b8eSAndroid Build Coastguard Worker
509*ec779b8eSAndroid Build Coastguard Worker if (stream.format == PixelFormat::BLOB) {
510*ec779b8eSAndroid Build Coastguard Worker numberOfStallStreams++;
511*ec779b8eSAndroid Build Coastguard Worker } else {
512*ec779b8eSAndroid Build Coastguard Worker numberOfProcessedStreams++;
513*ec779b8eSAndroid Build Coastguard Worker }
514*ec779b8eSAndroid Build Coastguard Worker
515*ec779b8eSAndroid Build Coastguard Worker Resolution requestedResolution(stream.width, stream.height);
516*ec779b8eSAndroid Build Coastguard Worker auto matchesSupportedInputConfig =
517*ec779b8eSAndroid Build Coastguard Worker [requestedResolution](const SupportedStreamConfiguration& config) {
518*ec779b8eSAndroid Build Coastguard Worker Resolution supportedInputResolution(config.width, config.height);
519*ec779b8eSAndroid Build Coastguard Worker return requestedResolution <= supportedInputResolution &&
520*ec779b8eSAndroid Build Coastguard Worker isApproximatellySameAspectRatio(requestedResolution,
521*ec779b8eSAndroid Build Coastguard Worker supportedInputResolution);
522*ec779b8eSAndroid Build Coastguard Worker };
523*ec779b8eSAndroid Build Coastguard Worker if (std::none_of(mSupportedInputConfigurations.begin(),
524*ec779b8eSAndroid Build Coastguard Worker mSupportedInputConfigurations.end(),
525*ec779b8eSAndroid Build Coastguard Worker matchesSupportedInputConfig)) {
526*ec779b8eSAndroid Build Coastguard Worker ALOGV("Requested config doesn't match any supported input config");
527*ec779b8eSAndroid Build Coastguard Worker return false;
528*ec779b8eSAndroid Build Coastguard Worker }
529*ec779b8eSAndroid Build Coastguard Worker }
530*ec779b8eSAndroid Build Coastguard Worker
531*ec779b8eSAndroid Build Coastguard Worker if (numberOfProcessedStreams > kMaxNumberOfProcessedStreams) {
532*ec779b8eSAndroid Build Coastguard Worker ALOGE("%s: %d processed streams exceeds the supported maximum of %d",
533*ec779b8eSAndroid Build Coastguard Worker __func__, numberOfProcessedStreams, kMaxNumberOfProcessedStreams);
534*ec779b8eSAndroid Build Coastguard Worker return false;
535*ec779b8eSAndroid Build Coastguard Worker }
536*ec779b8eSAndroid Build Coastguard Worker
537*ec779b8eSAndroid Build Coastguard Worker if (numberOfStallStreams > kMaxNumberOfStallStreams) {
538*ec779b8eSAndroid Build Coastguard Worker ALOGE("%s: %d stall streams exceeds the supported maximum of %d", __func__,
539*ec779b8eSAndroid Build Coastguard Worker numberOfStallStreams, kMaxNumberOfStallStreams);
540*ec779b8eSAndroid Build Coastguard Worker return false;
541*ec779b8eSAndroid Build Coastguard Worker }
542*ec779b8eSAndroid Build Coastguard Worker
543*ec779b8eSAndroid Build Coastguard Worker return true;
544*ec779b8eSAndroid Build Coastguard Worker }
545*ec779b8eSAndroid Build Coastguard Worker
open(const std::shared_ptr<ICameraDeviceCallback> & in_callback,std::shared_ptr<ICameraDeviceSession> * _aidl_return)546*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus VirtualCameraDevice::open(
547*ec779b8eSAndroid Build Coastguard Worker const std::shared_ptr<ICameraDeviceCallback>& in_callback,
548*ec779b8eSAndroid Build Coastguard Worker std::shared_ptr<ICameraDeviceSession>* _aidl_return) {
549*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
550*ec779b8eSAndroid Build Coastguard Worker
551*ec779b8eSAndroid Build Coastguard Worker *_aidl_return = ndk::SharedRefBase::make<VirtualCameraSession>(
552*ec779b8eSAndroid Build Coastguard Worker sharedFromThis(), in_callback, mVirtualCameraClientCallback);
553*ec779b8eSAndroid Build Coastguard Worker
554*ec779b8eSAndroid Build Coastguard Worker return ndk::ScopedAStatus::ok();
555*ec779b8eSAndroid Build Coastguard Worker };
556*ec779b8eSAndroid Build Coastguard Worker
openInjectionSession(const std::shared_ptr<ICameraDeviceCallback> & in_callback,std::shared_ptr<ICameraInjectionSession> * _aidl_return)557*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus VirtualCameraDevice::openInjectionSession(
558*ec779b8eSAndroid Build Coastguard Worker const std::shared_ptr<ICameraDeviceCallback>& in_callback,
559*ec779b8eSAndroid Build Coastguard Worker std::shared_ptr<ICameraInjectionSession>* _aidl_return) {
560*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
561*ec779b8eSAndroid Build Coastguard Worker
562*ec779b8eSAndroid Build Coastguard Worker (void)in_callback;
563*ec779b8eSAndroid Build Coastguard Worker (void)_aidl_return;
564*ec779b8eSAndroid Build Coastguard Worker return cameraStatus(Status::OPERATION_NOT_SUPPORTED);
565*ec779b8eSAndroid Build Coastguard Worker }
566*ec779b8eSAndroid Build Coastguard Worker
setTorchMode(bool in_on)567*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus VirtualCameraDevice::setTorchMode(bool in_on) {
568*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s: on = %s", __func__, in_on ? "on" : "off");
569*ec779b8eSAndroid Build Coastguard Worker return cameraStatus(Status::OPERATION_NOT_SUPPORTED);
570*ec779b8eSAndroid Build Coastguard Worker }
571*ec779b8eSAndroid Build Coastguard Worker
turnOnTorchWithStrengthLevel(int32_t in_torchStrength)572*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus VirtualCameraDevice::turnOnTorchWithStrengthLevel(
573*ec779b8eSAndroid Build Coastguard Worker int32_t in_torchStrength) {
574*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s: torchStrength = %d", __func__, in_torchStrength);
575*ec779b8eSAndroid Build Coastguard Worker return cameraStatus(Status::OPERATION_NOT_SUPPORTED);
576*ec779b8eSAndroid Build Coastguard Worker }
577*ec779b8eSAndroid Build Coastguard Worker
getTorchStrengthLevel(int32_t * _aidl_return)578*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus VirtualCameraDevice::getTorchStrengthLevel(
579*ec779b8eSAndroid Build Coastguard Worker int32_t* _aidl_return) {
580*ec779b8eSAndroid Build Coastguard Worker (void)_aidl_return;
581*ec779b8eSAndroid Build Coastguard Worker return cameraStatus(Status::OPERATION_NOT_SUPPORTED);
582*ec779b8eSAndroid Build Coastguard Worker }
583*ec779b8eSAndroid Build Coastguard Worker
dump(int fd,const char **,uint32_t)584*ec779b8eSAndroid Build Coastguard Worker binder_status_t VirtualCameraDevice::dump(int fd, const char**, uint32_t) {
585*ec779b8eSAndroid Build Coastguard Worker ALOGD("Dumping virtual camera %s", mCameraId.c_str());
586*ec779b8eSAndroid Build Coastguard Worker const char* indent = " ";
587*ec779b8eSAndroid Build Coastguard Worker const char* doubleIndent = " ";
588*ec779b8eSAndroid Build Coastguard Worker dprintf(fd, "%svirtual_camera %s belongs to virtual device %d\n", indent,
589*ec779b8eSAndroid Build Coastguard Worker mCameraId.c_str(),
590*ec779b8eSAndroid Build Coastguard Worker getDeviceId(mCameraCharacteristics)
591*ec779b8eSAndroid Build Coastguard Worker .value_or(VirtualCameraService::kDefaultDeviceId));
592*ec779b8eSAndroid Build Coastguard Worker dprintf(fd, "%sSupportedStreamConfiguration:\n", indent);
593*ec779b8eSAndroid Build Coastguard Worker for (auto& config : mSupportedInputConfigurations) {
594*ec779b8eSAndroid Build Coastguard Worker dprintf(fd, "%s%s", doubleIndent, config.toString().c_str());
595*ec779b8eSAndroid Build Coastguard Worker }
596*ec779b8eSAndroid Build Coastguard Worker return STATUS_OK;
597*ec779b8eSAndroid Build Coastguard Worker }
598*ec779b8eSAndroid Build Coastguard Worker
getCameraName() const599*ec779b8eSAndroid Build Coastguard Worker std::string VirtualCameraDevice::getCameraName() const {
600*ec779b8eSAndroid Build Coastguard Worker return std::string(kDevicePathPrefix) + mCameraId;
601*ec779b8eSAndroid Build Coastguard Worker }
602*ec779b8eSAndroid Build Coastguard Worker
603*ec779b8eSAndroid Build Coastguard Worker const std::vector<SupportedStreamConfiguration>&
getInputConfigs() const604*ec779b8eSAndroid Build Coastguard Worker VirtualCameraDevice::getInputConfigs() const {
605*ec779b8eSAndroid Build Coastguard Worker return mSupportedInputConfigurations;
606*ec779b8eSAndroid Build Coastguard Worker }
607*ec779b8eSAndroid Build Coastguard Worker
getMaxInputResolution() const608*ec779b8eSAndroid Build Coastguard Worker Resolution VirtualCameraDevice::getMaxInputResolution() const {
609*ec779b8eSAndroid Build Coastguard Worker std::optional<Resolution> maxResolution =
610*ec779b8eSAndroid Build Coastguard Worker getMaxResolution(mSupportedInputConfigurations);
611*ec779b8eSAndroid Build Coastguard Worker if (!maxResolution.has_value()) {
612*ec779b8eSAndroid Build Coastguard Worker ALOGE(
613*ec779b8eSAndroid Build Coastguard Worker "%s: Cannot determine sensor size for virtual camera - input "
614*ec779b8eSAndroid Build Coastguard Worker "configurations empty?",
615*ec779b8eSAndroid Build Coastguard Worker __func__);
616*ec779b8eSAndroid Build Coastguard Worker return Resolution(0, 0);
617*ec779b8eSAndroid Build Coastguard Worker }
618*ec779b8eSAndroid Build Coastguard Worker return maxResolution.value();
619*ec779b8eSAndroid Build Coastguard Worker }
620*ec779b8eSAndroid Build Coastguard Worker
allocateInputStreamId()621*ec779b8eSAndroid Build Coastguard Worker int VirtualCameraDevice::allocateInputStreamId() {
622*ec779b8eSAndroid Build Coastguard Worker return mNextInputStreamId++;
623*ec779b8eSAndroid Build Coastguard Worker }
624*ec779b8eSAndroid Build Coastguard Worker
sharedFromThis()625*ec779b8eSAndroid Build Coastguard Worker std::shared_ptr<VirtualCameraDevice> VirtualCameraDevice::sharedFromThis() {
626*ec779b8eSAndroid Build Coastguard Worker // SharedRefBase which BnCameraDevice inherits from breaks
627*ec779b8eSAndroid Build Coastguard Worker // std::enable_shared_from_this. This is recommended replacement for
628*ec779b8eSAndroid Build Coastguard Worker // shared_from_this() per documentation in binder_interface_utils.h.
629*ec779b8eSAndroid Build Coastguard Worker return ref<VirtualCameraDevice>();
630*ec779b8eSAndroid Build Coastguard Worker }
631*ec779b8eSAndroid Build Coastguard Worker
632*ec779b8eSAndroid Build Coastguard Worker } // namespace virtualcamera
633*ec779b8eSAndroid Build Coastguard Worker } // namespace companion
634*ec779b8eSAndroid Build Coastguard Worker } // namespace android
635