blob: 4b042f7286e8265ee92e92623dd858e2209368bc [file] [log] [blame]
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001/*
Shuzhen Wangc28189a2017-11-27 23:05:10 -08002 * Copyright (C) 2013-2018 The Android Open Source Project
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08003 *
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 "Camera3-Device"
18#define ATRACE_TAG ATRACE_TAG_CAMERA
19//#define LOG_NDEBUG 0
20//#define LOG_NNDEBUG 0 // Per-frame verbose logging
21
22#ifdef LOG_NNDEBUG
23#define ALOGVV(...) ALOGV(__VA_ARGS__)
24#else
25#define ALOGVV(...) ((void)0)
26#endif
27
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -070028// Convenience macro for transient errors
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -080029#define CLOGE(fmt, ...) ALOGE("Camera %s: %s: " fmt, mId.string(), __FUNCTION__, \
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -070030 ##__VA_ARGS__)
31
Yin-Chia Yeh99fd0972019-06-27 14:22:44 -070032#define CLOGW(fmt, ...) ALOGW("Camera %s: %s: " fmt, mId.string(), __FUNCTION__, \
33 ##__VA_ARGS__)
34
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -070035// Convenience macros for transitioning to the error state
36#define SET_ERR(fmt, ...) setErrorState( \
37 "%s: " fmt, __FUNCTION__, \
38 ##__VA_ARGS__)
39#define SET_ERR_L(fmt, ...) setErrorStateLocked( \
40 "%s: " fmt, __FUNCTION__, \
41 ##__VA_ARGS__)
42
Colin Crosse5729fa2014-03-21 15:04:25 -070043#include <inttypes.h>
44
Shuzhen Wang5c22c152017-12-31 17:12:25 -080045#include <utility>
46
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -080047#include <utils/Log.h>
48#include <utils/Trace.h>
49#include <utils/Timers.h>
Zhijun He90f7c372016-08-16 16:19:43 -070050#include <cutils/properties.h>
Eino-Ville Talvala7b82efe2013-07-25 17:12:35 -070051
Cliff Wuc2ad9c82021-04-21 00:58:58 +080052#include <android/hardware/camera/device/3.7/ICameraInjectionSession.h>
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -080053#include <android/hardware/camera2/ICameraDeviceUser.h>
54
Igor Murashkinff3e31d2013-10-23 16:40:06 -070055#include "utils/CameraTraces.h"
Eino-Ville Talvalaf99498e2015-09-25 16:52:55 -070056#include "mediautils/SchedulingPolicyService.h"
Eino-Ville Talvala7b82efe2013-07-25 17:12:35 -070057#include "device3/Camera3Device.h"
58#include "device3/Camera3OutputStream.h"
59#include "device3/Camera3InputStream.h"
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -040060#include "device3/Camera3FakeStream.h"
Shuzhen Wang0129d522016-10-30 22:43:41 -070061#include "device3/Camera3SharedOutputStream.h"
Eino-Ville Talvalaf67e23e2014-07-23 17:17:59 -070062#include "CameraService.h"
Jayant Chowdhary12361932018-08-27 14:46:13 -070063#include "utils/CameraThreadState.h"
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -080064#include "utils/SessionConfigurationUtils.h"
Jayant Chowdharyd4776262020-06-23 23:45:57 -070065#include "utils/TraceHFR.h"
Shuzhen Wang316781a2020-08-18 18:11:01 -070066#include "utils/CameraServiceProxyWrapper.h"
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -080067
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -080068#include <algorithm>
Yin-Chia Yeh84be5782019-03-01 11:47:02 -080069#include <tuple>
70
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -080071using namespace android::camera3;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -080072using namespace android::hardware::camera;
73using namespace android::hardware::camera::device::V3_2;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -080074using android::hardware::camera::metadata::V3_6::CameraMetadataEnumAndroidSensorPixelMode;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -080075
76namespace android {
77
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -080078Camera3Device::Camera3Device(const String8 &id):
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -080079 mId(id),
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -080080 mOperatingMode(NO_MODE),
Eino-Ville Talvala9a179412015-06-09 13:15:16 -070081 mIsConstrainedHighSpeedConfiguration(false),
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -070082 mStatus(STATUS_UNINITIALIZED),
Ruben Brunk183f0562015-08-12 12:55:02 -070083 mStatusWaiters(0),
Zhijun He204e3292014-07-14 17:09:23 -070084 mUsePartialResult(false),
85 mNumPartialResults(1),
Shuzhen Wangc28dccc2016-02-11 23:48:46 -080086 mTimestampOffset(0),
Eino-Ville Talvala42368d92013-04-09 14:13:50 -070087 mNextResultFrameNumber(0),
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -070088 mNextReprocessResultFrameNumber(0),
Shuzhen Wang5ee99842019-04-12 11:55:48 -070089 mNextZslStillResultFrameNumber(0),
Eino-Ville Talvala42368d92013-04-09 14:13:50 -070090 mNextShutterFrameNumber(0),
Chien-Yu Chen3df11ce2015-09-30 14:13:30 -070091 mNextReprocessShutterFrameNumber(0),
Shuzhen Wang5ee99842019-04-12 11:55:48 -070092 mNextZslStillShutterFrameNumber(0),
Emilian Peev71c73a22017-03-21 16:35:51 +000093 mListener(NULL),
Emilian Peev811d2952018-05-25 11:08:40 +010094 mVendorTagId(CAMERA_METADATA_INVALID_VENDOR_ID),
Shuzhen Wang268a1362018-10-16 16:32:59 -070095 mLastTemplateId(-1),
96 mNeedFixupMonochromeTags(false)
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -080097{
98 ATRACE_CALL();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -080099 ALOGV("%s: Created device for camera %s", __FUNCTION__, mId.string());
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800100}
101
102Camera3Device::~Camera3Device()
103{
104 ATRACE_CALL();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800105 ALOGV("%s: Tearing down for camera id %s", __FUNCTION__, mId.string());
Yin-Chia Yehc5248132018-08-15 12:19:20 -0700106 disconnectImpl();
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800107}
108
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800109const String8& Camera3Device::getId() const {
Igor Murashkin71381052013-03-04 14:53:08 -0800110 return mId;
111}
112
Emilian Peevbd8c5032018-02-14 23:05:40 +0000113status_t Camera3Device::initialize(sp<CameraProviderManager> manager, const String8& monitorTags) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800114 ATRACE_CALL();
115 Mutex::Autolock il(mInterfaceLock);
116 Mutex::Autolock l(mLock);
117
118 ALOGV("%s: Initializing HIDL device for camera %s", __FUNCTION__, mId.string());
119 if (mStatus != STATUS_UNINITIALIZED) {
120 CLOGE("Already initialized!");
121 return INVALID_OPERATION;
122 }
123 if (manager == nullptr) return INVALID_OPERATION;
124
125 sp<ICameraDeviceSession> session;
126 ATRACE_BEGIN("CameraHal::openSession");
Steven Moreland5ff9c912017-03-09 23:13:00 -0800127 status_t res = manager->openSession(mId.string(), this,
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800128 /*out*/ &session);
129 ATRACE_END();
130 if (res != OK) {
131 SET_ERR_L("Could not open camera session: %s (%d)", strerror(-res), res);
132 return res;
133 }
134
Steven Moreland5ff9c912017-03-09 23:13:00 -0800135 res = manager->getCameraCharacteristics(mId.string(), &mDeviceInfo);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800136 if (res != OK) {
Shuzhen Wang2e7f58f2018-07-11 14:00:29 -0700137 SET_ERR_L("Could not retrieve camera characteristics: %s (%d)", strerror(-res), res);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800138 session->close();
139 return res;
140 }
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -0800141 mSupportNativeZoomRatio = manager->supportNativeZoomRatio(mId.string());
Yin-Chia Yeh52778d42016-12-22 18:20:43 -0800142
Shuzhen Wang2e7f58f2018-07-11 14:00:29 -0700143 std::vector<std::string> physicalCameraIds;
Shuzhen Wang03d8cc12018-09-12 14:17:09 -0700144 bool isLogical = manager->isLogicalCamera(mId.string(), &physicalCameraIds);
Shuzhen Wang2e7f58f2018-07-11 14:00:29 -0700145 if (isLogical) {
146 for (auto& physicalId : physicalCameraIds) {
Shuzhen Wang4f6fa9d2019-03-29 10:40:35 -0700147 res = manager->getCameraCharacteristics(
148 physicalId, &mPhysicalDeviceInfoMap[physicalId]);
Shuzhen Wang2e7f58f2018-07-11 14:00:29 -0700149 if (res != OK) {
150 SET_ERR_L("Could not retrieve camera %s characteristics: %s (%d)",
151 physicalId.c_str(), strerror(-res), res);
152 session->close();
153 return res;
154 }
Shuzhen Wang4f6fa9d2019-03-29 10:40:35 -0700155
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -0800156 bool usePrecorrectArray =
157 DistortionMapper::isDistortionSupported(mPhysicalDeviceInfoMap[physicalId]);
158 if (usePrecorrectArray) {
159 res = mDistortionMappers[physicalId].setupStaticInfo(
160 mPhysicalDeviceInfoMap[physicalId]);
Shuzhen Wang4f6fa9d2019-03-29 10:40:35 -0700161 if (res != OK) {
162 SET_ERR_L("Unable to read camera %s's calibration fields for distortion "
163 "correction", physicalId.c_str());
164 session->close();
165 return res;
166 }
167 }
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -0800168
Shuzhen Wang1c834da2019-12-18 11:17:03 -0800169 mZoomRatioMappers[physicalId] = ZoomRatioMapper(
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -0800170 &mPhysicalDeviceInfoMap[physicalId],
171 mSupportNativeZoomRatio, usePrecorrectArray);
Shuzhen Wang2e7f58f2018-07-11 14:00:29 -0700172 }
173 }
174
Yifan Hongf79b5542017-04-11 14:44:25 -0700175 std::shared_ptr<RequestMetadataQueue> queue;
Yifan Honga640c5a2017-04-12 16:30:31 -0700176 auto requestQueueRet = session->getCaptureRequestMetadataQueue(
177 [&queue](const auto& descriptor) {
178 queue = std::make_shared<RequestMetadataQueue>(descriptor);
179 if (!queue->isValid() || queue->availableToWrite() <= 0) {
180 ALOGE("HAL returns empty request metadata fmq, not use it");
181 queue = nullptr;
182 // don't use the queue onwards.
183 }
184 });
185 if (!requestQueueRet.isOk()) {
186 ALOGE("Transaction error when getting request metadata fmq: %s, not use it",
187 requestQueueRet.description().c_str());
Eino-Ville Talvalac5cbb872017-04-27 12:48:33 -0700188 return DEAD_OBJECT;
Yifan Hongf79b5542017-04-11 14:44:25 -0700189 }
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700190
191 std::unique_ptr<ResultMetadataQueue>& resQueue = mResultMetadataQueue;
Yifan Honga640c5a2017-04-12 16:30:31 -0700192 auto resultQueueRet = session->getCaptureResultMetadataQueue(
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700193 [&resQueue](const auto& descriptor) {
194 resQueue = std::make_unique<ResultMetadataQueue>(descriptor);
195 if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
Yifan Honga640c5a2017-04-12 16:30:31 -0700196 ALOGE("HAL returns empty result metadata fmq, not use it");
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700197 resQueue = nullptr;
198 // Don't use the resQueue onwards.
Yifan Honga640c5a2017-04-12 16:30:31 -0700199 }
200 });
201 if (!resultQueueRet.isOk()) {
202 ALOGE("Transaction error when getting result metadata queue from camera session: %s",
203 resultQueueRet.description().c_str());
Eino-Ville Talvalac5cbb872017-04-27 12:48:33 -0700204 return DEAD_OBJECT;
Yifan Honga640c5a2017-04-12 16:30:31 -0700205 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -0700206 IF_ALOGV() {
207 session->interfaceChain([](
208 ::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
209 ALOGV("Session interface chain:");
Chih-Hung Hsieh3ef324d2018-12-11 11:48:12 -0800210 for (const auto& iface : interfaceChain) {
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -0700211 ALOGV(" %s", iface.c_str());
212 }
213 });
214 }
Yifan Hongf79b5542017-04-11 14:44:25 -0700215
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -0800216 camera_metadata_entry bufMgrMode =
217 mDeviceInfo.find(ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION);
218 if (bufMgrMode.count > 0) {
219 mUseHalBufManager = (bufMgrMode.data.u8[0] ==
220 ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5);
221 }
222
Yin-Chia Yehb978c382019-10-30 00:22:37 -0700223 camera_metadata_entry_t capabilities = mDeviceInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
224 for (size_t i = 0; i < capabilities.count; i++) {
225 uint8_t capability = capabilities.data.u8[i];
226 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_OFFLINE_PROCESSING) {
227 mSupportOfflineProcessing = true;
228 }
229 }
230
231 mInterface = new HalInterface(session, queue, mUseHalBufManager, mSupportOfflineProcessing);
Emilian Peev71c73a22017-03-21 16:35:51 +0000232 std::string providerType;
233 mVendorTagId = manager->getProviderTagIdLocked(mId.string());
Emilian Peevbd8c5032018-02-14 23:05:40 +0000234 mTagMonitor.initialize(mVendorTagId);
235 if (!monitorTags.isEmpty()) {
236 mTagMonitor.parseTagsToMonitor(String8(monitorTags));
237 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800238
Shuzhen Wang268a1362018-10-16 16:32:59 -0700239 // Metadata tags needs fixup for monochrome camera device version less
240 // than 3.5.
241 hardware::hidl_version maxVersion{0,0};
242 res = manager->getHighestSupportedVersion(mId.string(), &maxVersion);
243 if (res != OK) {
244 ALOGE("%s: Error in getting camera device version id: %s (%d)",
245 __FUNCTION__, strerror(-res), res);
246 return res;
247 }
248 int deviceVersion = HARDWARE_DEVICE_API_VERSION(
249 maxVersion.get_major(), maxVersion.get_minor());
250
251 bool isMonochrome = false;
Yin-Chia Yehb978c382019-10-30 00:22:37 -0700252 for (size_t i = 0; i < capabilities.count; i++) {
253 uint8_t capability = capabilities.data.u8[i];
Shuzhen Wang268a1362018-10-16 16:32:59 -0700254 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME) {
255 isMonochrome = true;
256 }
257 }
258 mNeedFixupMonochromeTags = (isMonochrome && deviceVersion < CAMERA_DEVICE_API_VERSION_3_5);
259
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800260 return initializeCommonLocked();
261}
262
263status_t Camera3Device::initializeCommonLocked() {
264
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700265 /** Start up status tracker thread */
266 mStatusTracker = new StatusTracker(this);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800267 status_t res = mStatusTracker->run(String8::format("C3Dev-%s-Status", mId.string()).string());
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700268 if (res != OK) {
269 SET_ERR_L("Unable to start status tracking thread: %s (%d)",
270 strerror(-res), res);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800271 mInterface->close();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700272 mStatusTracker.clear();
273 return res;
274 }
275
Eino-Ville Talvala24b366e2016-07-21 12:53:07 -0700276 /** Register in-flight map to the status tracker */
Yin-Chia Yeh87b3ec02019-06-03 10:44:39 -0700277 mInFlightStatusId = mStatusTracker->addComponent("InflightRequests");
Eino-Ville Talvala24b366e2016-07-21 12:53:07 -0700278
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -0700279 if (mUseHalBufManager) {
280 res = mRequestBufferSM.initialize(mStatusTracker);
281 if (res != OK) {
282 SET_ERR_L("Unable to start request buffer state machine: %s (%d)",
283 strerror(-res), res);
284 mInterface->close();
285 mStatusTracker.clear();
286 return res;
287 }
288 }
289
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -0800290 /** Create buffer manager */
291 mBufferManager = new Camera3BufferManager();
292
293 Vector<int32_t> sessionParamKeys;
294 camera_metadata_entry_t sessionKeysEntry = mDeviceInfo.find(
295 ANDROID_REQUEST_AVAILABLE_SESSION_KEYS);
296 if (sessionKeysEntry.count > 0) {
297 sessionParamKeys.insertArrayAt(sessionKeysEntry.data.i32, 0, sessionKeysEntry.count);
298 }
299
Chien-Yu Chenab5135b2015-06-30 11:20:58 -0700300 /** Start up request queue thread */
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -0700301 mRequestThread = new RequestThread(
302 this, mStatusTracker, mInterface, sessionParamKeys, mUseHalBufManager);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800303 res = mRequestThread->run(String8::format("C3Dev-%s-ReqQueue", mId.string()).string());
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800304 if (res != OK) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -0700305 SET_ERR_L("Unable to start request queue thread: %s (%d)",
306 strerror(-res), res);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800307 mInterface->close();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800308 mRequestThread.clear();
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800309 return res;
310 }
311
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -0700312 mPreparerThread = new PreparerThread();
313
Ruben Brunk183f0562015-08-12 12:55:02 -0700314 internalUpdateStatusLocked(STATUS_UNCONFIGURED);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800315 mNextStreamId = 0;
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -0400316 mFakeStreamId = NO_STREAM;
Eino-Ville Talvalaea26c772013-06-11 16:04:06 -0700317 mNeedConfig = true;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700318 mPauseStateNotify = false;
Shuzhen Wang83bff122020-11-20 15:51:39 -0800319 mIsInputStreamMultiResolution = false;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800320
Shuzhen Wangc28dccc2016-02-11 23:48:46 -0800321 // Measure the clock domain offset between camera and video/hw_composer
322 camera_metadata_entry timestampSource =
323 mDeviceInfo.find(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE);
324 if (timestampSource.count > 0 && timestampSource.data.u8[0] ==
325 ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME) {
326 mTimestampOffset = getMonoToBoottimeOffset();
327 }
328
Eino-Ville Talvalafd6ecdd2013-10-11 09:51:09 -0700329 // Will the HAL be sending in early partial result metadata?
Emilian Peev08dd2452017-04-06 16:55:14 +0100330 camera_metadata_entry partialResultsCount =
331 mDeviceInfo.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
332 if (partialResultsCount.count > 0) {
333 mNumPartialResults = partialResultsCount.data.i32[0];
334 mUsePartialResult = (mNumPartialResults > 1);
Eino-Ville Talvalafd6ecdd2013-10-11 09:51:09 -0700335 }
336
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -0800337 bool usePrecorrectArray = DistortionMapper::isDistortionSupported(mDeviceInfo);
338 if (usePrecorrectArray) {
Shuzhen Wang4f6fa9d2019-03-29 10:40:35 -0700339 res = mDistortionMappers[mId.c_str()].setupStaticInfo(mDeviceInfo);
Eino-Ville Talvala7b8a1fd2018-05-22 15:30:35 -0700340 if (res != OK) {
341 SET_ERR_L("Unable to read necessary calibration fields for distortion correction");
342 return res;
343 }
344 }
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -0800345
Shuzhen Wang1c834da2019-12-18 11:17:03 -0800346 mZoomRatioMappers[mId.c_str()] = ZoomRatioMapper(&mDeviceInfo,
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -0800347 mSupportNativeZoomRatio, usePrecorrectArray);
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -0800348
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -0800349 if (RotateAndCropMapper::isNeeded(&mDeviceInfo)) {
350 mRotateAndCropMappers.emplace(mId.c_str(), &mDeviceInfo);
351 }
352
Eino-Ville Talvala305cec62020-11-12 14:18:17 -0800353 camera_metadata_entry_t availableTestPatternModes = mDeviceInfo.find(
354 ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES);
355 for (size_t i = 0; i < availableTestPatternModes.count; i++) {
Eino-Ville Talvala11afe4f2021-05-27 14:45:31 -0700356 if (availableTestPatternModes.data.i32[i] ==
357 ANDROID_SENSOR_TEST_PATTERN_MODE_SOLID_COLOR) {
Eino-Ville Talvala305cec62020-11-12 14:18:17 -0800358 mSupportCameraMute = true;
Eino-Ville Talvala11afe4f2021-05-27 14:45:31 -0700359 mSupportTestPatternSolidColor = true;
Eino-Ville Talvala305cec62020-11-12 14:18:17 -0800360 break;
Eino-Ville Talvala11afe4f2021-05-27 14:45:31 -0700361 } else if (availableTestPatternModes.data.i32[i] ==
362 ANDROID_SENSOR_TEST_PATTERN_MODE_BLACK) {
363 mSupportCameraMute = true;
364 mSupportTestPatternSolidColor = false;
Eino-Ville Talvala305cec62020-11-12 14:18:17 -0800365 }
366 }
367
Cliff Wuc2ad9c82021-04-21 00:58:58 +0800368 mInjectionMethods = new Camera3DeviceInjectionMethods(this);
369
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800370 return OK;
371}
372
373status_t Camera3Device::disconnect() {
Yin-Chia Yehc5248132018-08-15 12:19:20 -0700374 return disconnectImpl();
375}
376
377status_t Camera3Device::disconnectImpl() {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800378 ATRACE_CALL();
Yin-Chia Yehe1c80632016-08-08 14:48:05 -0700379 ALOGI("%s: E", __FUNCTION__);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800380
Eino-Ville Talvala214a17f2013-06-13 12:20:02 -0700381 status_t res = OK;
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700382 std::vector<wp<Camera3StreamInterface>> streams;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700383 {
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800384 Mutex::Autolock il(mInterfaceLock);
385 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
386 {
387 Mutex::Autolock l(mLock);
388 if (mStatus == STATUS_UNINITIALIZED) return res;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700389
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800390 if (mStatus == STATUS_ACTIVE ||
391 (mStatus == STATUS_ERROR && mRequestThread != NULL)) {
392 res = mRequestThread->clearRepeatingRequests();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700393 if (res != OK) {
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800394 SET_ERR_L("Can't stop streaming");
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700395 // Continue to close device even in case of error
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800396 } else {
397 res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration);
398 if (res != OK) {
399 SET_ERR_L("Timeout waiting for HAL to drain (% " PRIi64 " ns)",
400 maxExpectedDuration);
401 // Continue to close device even in case of error
402 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700403 }
Eino-Ville Talvala214a17f2013-06-13 12:20:02 -0700404 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800405
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800406 if (mStatus == STATUS_ERROR) {
407 CLOGE("Shutting down in an error state");
408 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700409
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800410 if (mStatusTracker != NULL) {
411 mStatusTracker->requestExit();
412 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700413
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800414 if (mRequestThread != NULL) {
415 mRequestThread->requestExit();
416 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700417
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800418 streams.reserve(mOutputStreams.size() + (mInputStream != nullptr ? 1 : 0));
419 for (size_t i = 0; i < mOutputStreams.size(); i++) {
420 streams.push_back(mOutputStreams[i]);
421 }
422 if (mInputStream != nullptr) {
423 streams.push_back(mInputStream);
424 }
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700425 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700426 }
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800427 // Joining done without holding mLock and mInterfaceLock, otherwise deadlocks may ensue
428 // as the threads try to access parent state (b/143513518)
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700429 if (mRequestThread != NULL && mStatus != STATUS_ERROR) {
430 // HAL may be in a bad state, so waiting for request thread
431 // (which may be stuck in the HAL processCaptureRequest call)
432 // could be dangerous.
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800433 // give up mInterfaceLock here and then lock it again. Could this lead
434 // to other deadlocks
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700435 mRequestThread->join();
436 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700437 {
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800438 Mutex::Autolock il(mInterfaceLock);
439 if (mStatusTracker != NULL) {
440 mStatusTracker->join();
441 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800442
Cliff Wuc2ad9c82021-04-21 00:58:58 +0800443 if (mInjectionMethods->isInjecting()) {
444 mInjectionMethods->stopInjection();
445 }
446
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800447 HalInterface* interface;
448 {
449 Mutex::Autolock l(mLock);
450 mRequestThread.clear();
451 Mutex::Autolock stLock(mTrackerLock);
452 mStatusTracker.clear();
453 interface = mInterface.get();
454 }
Eino-Ville Talvalaefff1c42015-08-28 16:27:27 -0700455
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800456 // Call close without internal mutex held, as the HAL close may need to
457 // wait on assorted callbacks,etc, to complete before it can return.
458 interface->close();
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700459
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800460 flushInflightRequests();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800461
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800462 {
463 Mutex::Autolock l(mLock);
464 mInterface->clear();
465 mOutputStreams.clear();
466 mInputStream.clear();
467 mDeletedStreams.clear();
468 mBufferManager.clear();
469 internalUpdateStatusLocked(STATUS_UNINITIALIZED);
470 }
471
472 for (auto& weakStream : streams) {
473 sp<Camera3StreamInterface> stream = weakStream.promote();
474 if (stream != nullptr) {
475 ALOGE("%s: Stream %d leaked! strong reference (%d)!",
476 __FUNCTION__, stream->getId(), stream->getStrongCount() - 1);
477 }
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700478 }
479 }
Yin-Chia Yehe1c80632016-08-08 14:48:05 -0700480 ALOGI("%s: X", __FUNCTION__);
Eino-Ville Talvala214a17f2013-06-13 12:20:02 -0700481 return res;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800482}
483
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700484// For dumping/debugging only -
485// try to acquire a lock a few times, eventually give up to proceed with
486// debug/dump operations
487bool Camera3Device::tryLockSpinRightRound(Mutex& lock) {
488 bool gotLock = false;
489 for (size_t i = 0; i < kDumpLockAttempts; ++i) {
490 if (lock.tryLock() == NO_ERROR) {
491 gotLock = true;
492 break;
493 } else {
494 usleep(kDumpSleepDuration);
495 }
496 }
497 return gotLock;
498}
499
Shuzhen Wang83bff122020-11-20 15:51:39 -0800500camera3::Size Camera3Device::getMaxJpegResolution() const {
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700501 int32_t maxJpegWidth = 0, maxJpegHeight = 0;
Emilian Peev08dd2452017-04-06 16:55:14 +0100502 const int STREAM_CONFIGURATION_SIZE = 4;
503 const int STREAM_FORMAT_OFFSET = 0;
504 const int STREAM_WIDTH_OFFSET = 1;
505 const int STREAM_HEIGHT_OFFSET = 2;
506 const int STREAM_IS_INPUT_OFFSET = 3;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800507 bool isHighResolutionSensor =
508 camera3::SessionConfigurationUtils::isUltraHighResolutionSensor(mDeviceInfo);
509 int32_t scalerSizesTag = isHighResolutionSensor ?
510 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION :
511 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS;
Emilian Peev08dd2452017-04-06 16:55:14 +0100512 camera_metadata_ro_entry_t availableStreamConfigs =
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800513 mDeviceInfo.find(scalerSizesTag);
Emilian Peev08dd2452017-04-06 16:55:14 +0100514 if (availableStreamConfigs.count == 0 ||
515 availableStreamConfigs.count % STREAM_CONFIGURATION_SIZE != 0) {
Shuzhen Wang83bff122020-11-20 15:51:39 -0800516 return camera3::Size(0, 0);
Emilian Peev08dd2452017-04-06 16:55:14 +0100517 }
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700518
Emilian Peev08dd2452017-04-06 16:55:14 +0100519 // Get max jpeg size (area-wise).
520 for (size_t i=0; i < availableStreamConfigs.count; i+= STREAM_CONFIGURATION_SIZE) {
521 int32_t format = availableStreamConfigs.data.i32[i + STREAM_FORMAT_OFFSET];
522 int32_t width = availableStreamConfigs.data.i32[i + STREAM_WIDTH_OFFSET];
523 int32_t height = availableStreamConfigs.data.i32[i + STREAM_HEIGHT_OFFSET];
524 int32_t isInput = availableStreamConfigs.data.i32[i + STREAM_IS_INPUT_OFFSET];
525 if (isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT
526 && format == HAL_PIXEL_FORMAT_BLOB &&
527 (width * height > maxJpegWidth * maxJpegHeight)) {
528 maxJpegWidth = width;
529 maxJpegHeight = height;
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700530 }
531 }
Emilian Peev08dd2452017-04-06 16:55:14 +0100532
Shuzhen Wang83bff122020-11-20 15:51:39 -0800533 return camera3::Size(maxJpegWidth, maxJpegHeight);
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700534}
535
Shuzhen Wangc28dccc2016-02-11 23:48:46 -0800536nsecs_t Camera3Device::getMonoToBoottimeOffset() {
537 // try three times to get the clock offset, choose the one
538 // with the minimum gap in measurements.
539 const int tries = 3;
540 nsecs_t bestGap, measured;
541 for (int i = 0; i < tries; ++i) {
542 const nsecs_t tmono = systemTime(SYSTEM_TIME_MONOTONIC);
543 const nsecs_t tbase = systemTime(SYSTEM_TIME_BOOTTIME);
544 const nsecs_t tmono2 = systemTime(SYSTEM_TIME_MONOTONIC);
545 const nsecs_t gap = tmono2 - tmono;
546 if (i == 0 || gap < bestGap) {
547 bestGap = gap;
548 measured = tbase - ((tmono + tmono2) >> 1);
549 }
550 }
551 return measured;
552}
553
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800554hardware::graphics::common::V1_0::PixelFormat Camera3Device::mapToPixelFormat(
555 int frameworkFormat) {
556 return (hardware::graphics::common::V1_0::PixelFormat) frameworkFormat;
557}
558
559DataspaceFlags Camera3Device::mapToHidlDataspace(
560 android_dataspace dataSpace) {
561 return dataSpace;
562}
563
Chia-I Wu67a0c0e2017-04-06 13:37:01 -0700564BufferUsageFlags Camera3Device::mapToConsumerUsage(
Emilian Peev050f5dc2017-05-18 14:43:56 +0100565 uint64_t usage) {
Yin-Chia Yeh47cf8e62017-04-04 13:00:03 -0700566 return usage;
567}
568
Emilian Peevf4816702020-04-03 15:44:51 -0700569StreamRotation Camera3Device::mapToStreamRotation(camera_stream_rotation_t rotation) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800570 switch (rotation) {
Emilian Peevf4816702020-04-03 15:44:51 -0700571 case CAMERA_STREAM_ROTATION_0:
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800572 return StreamRotation::ROTATION_0;
Emilian Peevf4816702020-04-03 15:44:51 -0700573 case CAMERA_STREAM_ROTATION_90:
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800574 return StreamRotation::ROTATION_90;
Emilian Peevf4816702020-04-03 15:44:51 -0700575 case CAMERA_STREAM_ROTATION_180:
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800576 return StreamRotation::ROTATION_180;
Emilian Peevf4816702020-04-03 15:44:51 -0700577 case CAMERA_STREAM_ROTATION_270:
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800578 return StreamRotation::ROTATION_270;
579 }
580 ALOGE("%s: Unknown stream rotation %d", __FUNCTION__, rotation);
581 return StreamRotation::ROTATION_0;
582}
583
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -0800584status_t Camera3Device::mapToStreamConfigurationMode(
Emilian Peevf4816702020-04-03 15:44:51 -0700585 camera_stream_configuration_mode_t operationMode, StreamConfigurationMode *mode) {
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -0800586 if (mode == nullptr) return BAD_VALUE;
Emilian Peevf4816702020-04-03 15:44:51 -0700587 if (operationMode < CAMERA_VENDOR_STREAM_CONFIGURATION_MODE_START) {
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -0800588 switch(operationMode) {
Emilian Peevf4816702020-04-03 15:44:51 -0700589 case CAMERA_STREAM_CONFIGURATION_NORMAL_MODE:
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -0800590 *mode = StreamConfigurationMode::NORMAL_MODE;
591 break;
Emilian Peevf4816702020-04-03 15:44:51 -0700592 case CAMERA_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE:
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -0800593 *mode = StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE;
594 break;
595 default:
596 ALOGE("%s: Unknown stream configuration mode %d", __FUNCTION__, operationMode);
597 return BAD_VALUE;
598 }
599 } else {
600 *mode = static_cast<StreamConfigurationMode>(operationMode);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800601 }
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -0800602 return OK;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800603}
604
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800605int Camera3Device::mapToFrameworkFormat(
606 hardware::graphics::common::V1_0::PixelFormat pixelFormat) {
607 return static_cast<uint32_t>(pixelFormat);
608}
609
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -0700610android_dataspace Camera3Device::mapToFrameworkDataspace(
611 DataspaceFlags dataSpace) {
612 return static_cast<android_dataspace>(dataSpace);
613}
614
Emilian Peev050f5dc2017-05-18 14:43:56 +0100615uint64_t Camera3Device::mapConsumerToFrameworkUsage(
Chia-I Wu67a0c0e2017-04-06 13:37:01 -0700616 BufferUsageFlags usage) {
Yin-Chia Yeh47cf8e62017-04-04 13:00:03 -0700617 return usage;
618}
619
Emilian Peev050f5dc2017-05-18 14:43:56 +0100620uint64_t Camera3Device::mapProducerToFrameworkUsage(
Chia-I Wu67a0c0e2017-04-06 13:37:01 -0700621 BufferUsageFlags usage) {
Yin-Chia Yeh47cf8e62017-04-04 13:00:03 -0700622 return usage;
623}
624
Zhijun Hef7da0962014-04-24 13:27:56 -0700625ssize_t Camera3Device::getJpegBufferSize(uint32_t width, uint32_t height) const {
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700626 // Get max jpeg size (area-wise).
Shuzhen Wang83bff122020-11-20 15:51:39 -0800627 camera3::Size maxJpegResolution = getMaxJpegResolution();
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700628 if (maxJpegResolution.width == 0) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800629 ALOGE("%s: Camera %s: Can't find valid available jpeg sizes in static metadata!",
630 __FUNCTION__, mId.string());
Zhijun Hef7da0962014-04-24 13:27:56 -0700631 return BAD_VALUE;
632 }
633
Zhijun Hef7da0962014-04-24 13:27:56 -0700634 // Get max jpeg buffer size
635 ssize_t maxJpegBufferSize = 0;
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700636 camera_metadata_ro_entry jpegBufMaxSize = mDeviceInfo.find(ANDROID_JPEG_MAX_SIZE);
637 if (jpegBufMaxSize.count == 0) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800638 ALOGE("%s: Camera %s: Can't find maximum JPEG size in static metadata!", __FUNCTION__,
639 mId.string());
Zhijun Hef7da0962014-04-24 13:27:56 -0700640 return BAD_VALUE;
641 }
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700642 maxJpegBufferSize = jpegBufMaxSize.data.i32[0];
Yin-Chia Yeh0c4e56d2015-01-09 15:21:27 -0800643 assert(kMinJpegBufferSize < maxJpegBufferSize);
Zhijun Hef7da0962014-04-24 13:27:56 -0700644
645 // Calculate final jpeg buffer size for the given resolution.
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700646 float scaleFactor = ((float) (width * height)) /
647 (maxJpegResolution.width * maxJpegResolution.height);
Yin-Chia Yeh0c4e56d2015-01-09 15:21:27 -0800648 ssize_t jpegBufferSize = scaleFactor * (maxJpegBufferSize - kMinJpegBufferSize) +
649 kMinJpegBufferSize;
Zhijun Hef7da0962014-04-24 13:27:56 -0700650 if (jpegBufferSize > maxJpegBufferSize) {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800651 ALOGI("%s: jpeg buffer size calculated is > maxJpeg bufferSize(%zd), clamping",
652 __FUNCTION__, maxJpegBufferSize);
Zhijun Hef7da0962014-04-24 13:27:56 -0700653 jpegBufferSize = maxJpegBufferSize;
Zhijun Hef7da0962014-04-24 13:27:56 -0700654 }
655
656 return jpegBufferSize;
657}
658
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -0700659ssize_t Camera3Device::getPointCloudBufferSize() const {
660 const int FLOATS_PER_POINT=4;
661 camera_metadata_ro_entry maxPointCount = mDeviceInfo.find(ANDROID_DEPTH_MAX_DEPTH_SAMPLES);
662 if (maxPointCount.count == 0) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800663 ALOGE("%s: Camera %s: Can't find maximum depth point cloud size in static metadata!",
664 __FUNCTION__, mId.string());
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -0700665 return BAD_VALUE;
666 }
667 ssize_t maxBytesForPointCloud = sizeof(android_depth_points) +
668 maxPointCount.data.i32[0] * sizeof(float) * FLOATS_PER_POINT;
669 return maxBytesForPointCloud;
670}
671
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800672ssize_t Camera3Device::getRawOpaqueBufferSize(int32_t width, int32_t height,
673 bool maxResolution) const {
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800674 const int PER_CONFIGURATION_SIZE = 3;
675 const int WIDTH_OFFSET = 0;
676 const int HEIGHT_OFFSET = 1;
677 const int SIZE_OFFSET = 2;
678 camera_metadata_ro_entry rawOpaqueSizes =
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -0800679 mDeviceInfo.find(
680 camera3::SessionConfigurationUtils::getAppropriateModeTag(
681 ANDROID_SENSOR_OPAQUE_RAW_SIZE,
682 maxResolution));
Aurimas Liutikasbc57b122016-02-16 09:59:16 -0800683 size_t count = rawOpaqueSizes.count;
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800684 if (count == 0 || (count % PER_CONFIGURATION_SIZE)) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800685 ALOGE("%s: Camera %s: bad opaque RAW size static metadata length(%zu)!",
686 __FUNCTION__, mId.string(), count);
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800687 return BAD_VALUE;
688 }
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -0700689
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800690 for (size_t i = 0; i < count; i += PER_CONFIGURATION_SIZE) {
691 if (width == rawOpaqueSizes.data.i32[i + WIDTH_OFFSET] &&
692 height == rawOpaqueSizes.data.i32[i + HEIGHT_OFFSET]) {
693 return rawOpaqueSizes.data.i32[i + SIZE_OFFSET];
694 }
695 }
696
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800697 ALOGE("%s: Camera %s: cannot find size for %dx%d opaque RAW image!",
698 __FUNCTION__, mId.string(), width, height);
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800699 return BAD_VALUE;
700}
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -0700701
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800702status_t Camera3Device::dump(int fd, const Vector<String16> &args) {
703 ATRACE_CALL();
704 (void)args;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700705
706 // Try to lock, but continue in case of failure (to avoid blocking in
707 // deadlocks)
708 bool gotInterfaceLock = tryLockSpinRightRound(mInterfaceLock);
709 bool gotLock = tryLockSpinRightRound(mLock);
710
711 ALOGW_IF(!gotInterfaceLock,
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800712 "Camera %s: %s: Unable to lock interface lock, proceeding anyway",
713 mId.string(), __FUNCTION__);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700714 ALOGW_IF(!gotLock,
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800715 "Camera %s: %s: Unable to lock main lock, proceeding anyway",
716 mId.string(), __FUNCTION__);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700717
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800718 bool dumpTemplates = false;
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700719
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800720 String16 templatesOption("-t");
721 int n = args.size();
722 for (int i = 0; i < n; i++) {
723 if (args[i] == templatesOption) {
724 dumpTemplates = true;
725 }
Emilian Peevbd8c5032018-02-14 23:05:40 +0000726 if (args[i] == TagMonitor::kMonitorOption) {
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700727 if (i + 1 < n) {
728 String8 monitorTags = String8(args[i + 1]);
729 if (monitorTags == "off") {
730 mTagMonitor.disableMonitoring();
731 } else {
732 mTagMonitor.parseTagsToMonitor(monitorTags);
733 }
734 } else {
735 mTagMonitor.disableMonitoring();
736 }
737 }
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800738 }
739
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800740 String8 lines;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800741
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800742 const char *status =
743 mStatus == STATUS_ERROR ? "ERROR" :
744 mStatus == STATUS_UNINITIALIZED ? "UNINITIALIZED" :
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700745 mStatus == STATUS_UNCONFIGURED ? "UNCONFIGURED" :
746 mStatus == STATUS_CONFIGURED ? "CONFIGURED" :
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800747 mStatus == STATUS_ACTIVE ? "ACTIVE" :
748 "Unknown";
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700749
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800750 lines.appendFormat(" Device status: %s\n", status);
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -0700751 if (mStatus == STATUS_ERROR) {
752 lines.appendFormat(" Error cause: %s\n", mErrorCause.string());
753 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800754 lines.appendFormat(" Stream configuration:\n");
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -0800755 const char *mode =
756 mOperatingMode == static_cast<int>(StreamConfigurationMode::NORMAL_MODE) ? "NORMAL" :
757 mOperatingMode == static_cast<int>(
758 StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE) ? "CONSTRAINED_HIGH_SPEED" :
759 "CUSTOM";
760 lines.appendFormat(" Operation mode: %s (%d) \n", mode, mOperatingMode);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800761
762 if (mInputStream != NULL) {
763 write(fd, lines.string(), lines.size());
764 mInputStream->dump(fd, args);
765 } else {
766 lines.appendFormat(" No input stream.\n");
767 write(fd, lines.string(), lines.size());
768 }
769 for (size_t i = 0; i < mOutputStreams.size(); i++) {
770 mOutputStreams[i]->dump(fd,args);
771 }
772
Zhijun He431503c2016-03-07 17:30:16 -0800773 if (mBufferManager != NULL) {
774 lines = String8(" Camera3 Buffer Manager:\n");
775 write(fd, lines.string(), lines.size());
776 mBufferManager->dump(fd, args);
777 }
Zhijun He125684a2015-12-26 15:07:30 -0800778
Eino-Ville Talvala42368d92013-04-09 14:13:50 -0700779 lines = String8(" In-flight requests:\n");
780 if (mInFlightMap.size() == 0) {
781 lines.append(" None\n");
782 } else {
783 for (size_t i = 0; i < mInFlightMap.size(); i++) {
784 InFlightRequest r = mInFlightMap.valueAt(i);
Colin Crosse5729fa2014-03-21 15:04:25 -0700785 lines.appendFormat(" Frame %d | Timestamp: %" PRId64 ", metadata"
Greg Kaiser51b882c2020-06-10 05:41:44 +0000786 " arrived: %s, buffers left: %d\n", mInFlightMap.keyAt(i),
Chien-Yu Chen43e69a62014-11-25 16:38:33 -0800787 r.shutterTimestamp, r.haveResultMetadata ? "true" : "false",
Greg Kaiser51b882c2020-06-10 05:41:44 +0000788 r.numBuffersLeft);
Eino-Ville Talvala42368d92013-04-09 14:13:50 -0700789 }
790 }
791 write(fd, lines.string(), lines.size());
792
Shuzhen Wang686f6442017-06-20 16:16:04 -0700793 if (mRequestThread != NULL) {
794 mRequestThread->dumpCaptureRequestLatency(fd,
795 " ProcessCaptureRequest latency histogram:");
796 }
797
Igor Murashkin1e479c02013-09-06 16:55:14 -0700798 {
799 lines = String8(" Last request sent:\n");
800 write(fd, lines.string(), lines.size());
801
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700802 CameraMetadata lastRequest = getLatestRequestLocked();
Igor Murashkin1e479c02013-09-06 16:55:14 -0700803 lastRequest.dump(fd, /*verbosity*/2, /*indentation*/6);
804 }
805
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800806 if (dumpTemplates) {
Emilian Peevf4816702020-04-03 15:44:51 -0700807 const char *templateNames[CAMERA_TEMPLATE_COUNT] = {
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800808 "TEMPLATE_PREVIEW",
809 "TEMPLATE_STILL_CAPTURE",
810 "TEMPLATE_VIDEO_RECORD",
811 "TEMPLATE_VIDEO_SNAPSHOT",
812 "TEMPLATE_ZERO_SHUTTER_LAG",
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -0800813 "TEMPLATE_MANUAL",
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800814 };
815
Emilian Peevf4816702020-04-03 15:44:51 -0700816 for (int i = 1; i < CAMERA_TEMPLATE_COUNT; i++) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800817 camera_metadata_t *templateRequest = nullptr;
818 mInterface->constructDefaultRequestSettings(
Emilian Peevf4816702020-04-03 15:44:51 -0700819 (camera_request_template_t) i, &templateRequest);
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800820 lines = String8::format(" HAL Request %s:\n", templateNames[i-1]);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800821 if (templateRequest == nullptr) {
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800822 lines.append(" Not supported\n");
823 write(fd, lines.string(), lines.size());
824 } else {
825 write(fd, lines.string(), lines.size());
826 dump_indented_camera_metadata(templateRequest,
827 fd, /*verbosity*/2, /*indentation*/8);
828 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800829 free_camera_metadata(templateRequest);
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800830 }
831 }
832
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700833 mTagMonitor.dumpMonitoredMetadata(fd);
834
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800835 if (mInterface->valid()) {
Eino-Ville Talvalad00111e2017-01-31 11:59:12 -0800836 lines = String8(" HAL device dump:\n");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800837 write(fd, lines.string(), lines.size());
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800838 mInterface->dump(fd);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800839 }
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800840
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700841 if (gotLock) mLock.unlock();
842 if (gotInterfaceLock) mInterfaceLock.unlock();
843
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800844 return OK;
845}
846
Emilian Peevfaa4bde2020-01-23 12:19:37 -0800847const CameraMetadata& Camera3Device::infoPhysical(const String8& physicalId) const {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800848 ALOGVV("%s: E", __FUNCTION__);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800849 if (CC_UNLIKELY(mStatus == STATUS_UNINITIALIZED ||
850 mStatus == STATUS_ERROR)) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -0700851 ALOGW("%s: Access to static info %s!", __FUNCTION__,
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800852 mStatus == STATUS_ERROR ?
853 "when in error state" : "before init");
854 }
Shuzhen Wang2e7f58f2018-07-11 14:00:29 -0700855 if (physicalId.isEmpty()) {
856 return mDeviceInfo;
857 } else {
858 std::string id(physicalId.c_str());
859 if (mPhysicalDeviceInfoMap.find(id) != mPhysicalDeviceInfoMap.end()) {
860 return mPhysicalDeviceInfoMap.at(id);
861 } else {
862 ALOGE("%s: Invalid physical camera id %s", __FUNCTION__, physicalId.c_str());
863 return mDeviceInfo;
864 }
865 }
866}
867
868const CameraMetadata& Camera3Device::info() const {
869 String8 emptyId;
Emilian Peevfaa4bde2020-01-23 12:19:37 -0800870 return infoPhysical(emptyId);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800871}
872
Jianing Wei90e59c92014-03-12 18:29:36 -0700873status_t Camera3Device::checkStatusOkToCaptureLocked() {
874 switch (mStatus) {
875 case STATUS_ERROR:
876 CLOGE("Device has encountered a serious error");
877 return INVALID_OPERATION;
878 case STATUS_UNINITIALIZED:
879 CLOGE("Device not initialized");
880 return INVALID_OPERATION;
881 case STATUS_UNCONFIGURED:
882 case STATUS_CONFIGURED:
883 case STATUS_ACTIVE:
884 // OK
885 break;
886 default:
887 SET_ERR_L("Unexpected status: %d", mStatus);
888 return INVALID_OPERATION;
889 }
890 return OK;
891}
892
893status_t Camera3Device::convertMetadataListToRequestListLocked(
Emilian Peevaebbe412018-01-15 13:53:24 +0000894 const List<const PhysicalCameraSettingsList> &metadataList,
Shuzhen Wang0129d522016-10-30 22:43:41 -0700895 const std::list<const SurfaceMap> &surfaceMaps,
Shuzhen Wang316781a2020-08-18 18:11:01 -0700896 bool repeating, nsecs_t requestTimeNs,
Shuzhen Wang9d066012016-09-30 11:30:20 -0700897 RequestList *requestList) {
Jianing Wei90e59c92014-03-12 18:29:36 -0700898 if (requestList == NULL) {
899 CLOGE("requestList cannot be NULL.");
900 return BAD_VALUE;
901 }
902
Jianing Weicb0652e2014-03-12 18:29:36 -0700903 int32_t burstId = 0;
Emilian Peevaebbe412018-01-15 13:53:24 +0000904 List<const PhysicalCameraSettingsList>::const_iterator metadataIt = metadataList.begin();
Shuzhen Wang0129d522016-10-30 22:43:41 -0700905 std::list<const SurfaceMap>::const_iterator surfaceMapIt = surfaceMaps.begin();
906 for (; metadataIt != metadataList.end() && surfaceMapIt != surfaceMaps.end();
907 ++metadataIt, ++surfaceMapIt) {
908 sp<CaptureRequest> newRequest = setUpRequestLocked(*metadataIt, *surfaceMapIt);
Jianing Wei90e59c92014-03-12 18:29:36 -0700909 if (newRequest == 0) {
910 CLOGE("Can't create capture request");
911 return BAD_VALUE;
912 }
Jianing Weicb0652e2014-03-12 18:29:36 -0700913
Shuzhen Wang9d066012016-09-30 11:30:20 -0700914 newRequest->mRepeating = repeating;
Shuzhen Wang316781a2020-08-18 18:11:01 -0700915 newRequest->mRequestTimeNs = requestTimeNs;
Shuzhen Wang9d066012016-09-30 11:30:20 -0700916
Jianing Weicb0652e2014-03-12 18:29:36 -0700917 // Setup burst Id and request Id
918 newRequest->mResultExtras.burstId = burstId++;
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -0800919 auto requestIdEntry = metadataIt->begin()->metadata.find(ANDROID_REQUEST_ID);
920 if (requestIdEntry.count == 0) {
Jianing Weicb0652e2014-03-12 18:29:36 -0700921 CLOGE("RequestID does not exist in metadata");
922 return BAD_VALUE;
923 }
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -0800924 newRequest->mResultExtras.requestId = requestIdEntry.data.i32[0];
Jianing Weicb0652e2014-03-12 18:29:36 -0700925
Jianing Wei90e59c92014-03-12 18:29:36 -0700926 requestList->push_back(newRequest);
Jianing Wei2d6bb3f2014-04-11 10:00:31 -0700927
928 ALOGV("%s: requestId = %" PRId32, __FUNCTION__, newRequest->mResultExtras.requestId);
Jianing Wei90e59c92014-03-12 18:29:36 -0700929 }
Shuzhen Wang0129d522016-10-30 22:43:41 -0700930 if (metadataIt != metadataList.end() || surfaceMapIt != surfaceMaps.end()) {
931 ALOGE("%s: metadataList and surfaceMaps are not the same size!", __FUNCTION__);
932 return BAD_VALUE;
933 }
Chien-Yu Chen85a64552015-08-28 15:46:12 -0700934
935 // Setup batch size if this is a high speed video recording request.
936 if (mIsConstrainedHighSpeedConfiguration && requestList->size() > 0) {
937 auto firstRequest = requestList->begin();
938 for (auto& outputStream : (*firstRequest)->mOutputStreams) {
939 if (outputStream->isVideoStream()) {
940 (*firstRequest)->mBatchSize = requestList->size();
Yin-Chia Yeh14ef48d2020-02-10 15:06:37 -0800941 outputStream->setBatchSize(requestList->size());
Chien-Yu Chen85a64552015-08-28 15:46:12 -0700942 break;
943 }
944 }
945 }
946
Jianing Wei90e59c92014-03-12 18:29:36 -0700947 return OK;
948}
949
Yin-Chia Yeh7e5a2042019-02-06 16:01:06 -0800950status_t Camera3Device::capture(CameraMetadata &request, int64_t* lastFrameNumber) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800951 ATRACE_CALL();
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800952
Emilian Peevaebbe412018-01-15 13:53:24 +0000953 List<const PhysicalCameraSettingsList> requestsList;
Shuzhen Wang0129d522016-10-30 22:43:41 -0700954 std::list<const SurfaceMap> surfaceMaps;
Emilian Peevaebbe412018-01-15 13:53:24 +0000955 convertToRequestList(requestsList, surfaceMaps, request);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700956
Yin-Chia Yeh7e5a2042019-02-06 16:01:06 -0800957 return captureList(requestsList, surfaceMaps, lastFrameNumber);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700958}
959
Emilian Peevaebbe412018-01-15 13:53:24 +0000960void Camera3Device::convertToRequestList(List<const PhysicalCameraSettingsList>& requestsList,
Shuzhen Wang0129d522016-10-30 22:43:41 -0700961 std::list<const SurfaceMap>& surfaceMaps,
962 const CameraMetadata& request) {
Emilian Peevaebbe412018-01-15 13:53:24 +0000963 PhysicalCameraSettingsList requestList;
964 requestList.push_back({std::string(getId().string()), request});
965 requestsList.push_back(requestList);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700966
967 SurfaceMap surfaceMap;
968 camera_metadata_ro_entry streams = request.find(ANDROID_REQUEST_OUTPUT_STREAMS);
969 // With no surface list passed in, stream and surface will have 1-to-1
970 // mapping. So the surface index is 0 for each stream in the surfaceMap.
971 for (size_t i = 0; i < streams.count; i++) {
972 surfaceMap[streams.data.i32[i]].push_back(0);
973 }
974 surfaceMaps.push_back(surfaceMap);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800975}
976
Jianing Wei90e59c92014-03-12 18:29:36 -0700977status_t Camera3Device::submitRequestsHelper(
Emilian Peevaebbe412018-01-15 13:53:24 +0000978 const List<const PhysicalCameraSettingsList> &requests,
Shuzhen Wang0129d522016-10-30 22:43:41 -0700979 const std::list<const SurfaceMap> &surfaceMaps,
980 bool repeating,
Jianing Wei2d6bb3f2014-04-11 10:00:31 -0700981 /*out*/
982 int64_t *lastFrameNumber) {
Jianing Wei90e59c92014-03-12 18:29:36 -0700983 ATRACE_CALL();
Shuzhen Wang316781a2020-08-18 18:11:01 -0700984 nsecs_t requestTimeNs = systemTime();
985
Jianing Wei90e59c92014-03-12 18:29:36 -0700986 Mutex::Autolock il(mInterfaceLock);
987 Mutex::Autolock l(mLock);
988
989 status_t res = checkStatusOkToCaptureLocked();
990 if (res != OK) {
991 // error logged by previous call
992 return res;
993 }
994
995 RequestList requestList;
996
Shuzhen Wang0129d522016-10-30 22:43:41 -0700997 res = convertMetadataListToRequestListLocked(requests, surfaceMaps,
Shuzhen Wang316781a2020-08-18 18:11:01 -0700998 repeating, requestTimeNs, /*out*/&requestList);
Jianing Wei90e59c92014-03-12 18:29:36 -0700999 if (res != OK) {
1000 // error logged by previous call
1001 return res;
1002 }
1003
1004 if (repeating) {
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07001005 res = mRequestThread->setRepeatingRequests(requestList, lastFrameNumber);
Jianing Wei90e59c92014-03-12 18:29:36 -07001006 } else {
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07001007 res = mRequestThread->queueRequestList(requestList, lastFrameNumber);
Jianing Wei90e59c92014-03-12 18:29:36 -07001008 }
1009
1010 if (res == OK) {
1011 waitUntilStateThenRelock(/*active*/true, kActiveTimeout);
1012 if (res != OK) {
1013 SET_ERR_L("Can't transition to active in %f seconds!",
1014 kActiveTimeout/1e9);
1015 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001016 ALOGV("Camera %s: Capture request %" PRId32 " enqueued", mId.string(),
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07001017 (*(requestList.begin()))->mResultExtras.requestId);
Jianing Wei90e59c92014-03-12 18:29:36 -07001018 } else {
1019 CLOGE("Cannot queue request. Impossible.");
1020 return BAD_VALUE;
1021 }
1022
1023 return res;
1024}
1025
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07001026hardware::Return<void> Camera3Device::requestStreamBuffers(
1027 const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& bufReqs,
1028 requestStreamBuffers_cb _hidl_cb) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001029 RequestBufferStates states {
Shuzhen Wang316781a2020-08-18 18:11:01 -07001030 mId, mRequestBufferInterfaceLock, mUseHalBufManager, mOutputStreams, mSessionStatsBuilder,
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001031 *this, *mInterface, *this};
1032 camera3::requestStreamBuffers(states, bufReqs, _hidl_cb);
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07001033 return hardware::Void();
1034}
1035
1036hardware::Return<void> Camera3Device::returnStreamBuffers(
1037 const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer>& buffers) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001038 ReturnBufferStates states {
Shuzhen Wang316781a2020-08-18 18:11:01 -07001039 mId, mUseHalBufManager, mOutputStreams, mSessionStatsBuilder, *mInterface};
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001040 camera3::returnStreamBuffers(states, buffers);
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07001041 return hardware::Void();
1042}
1043
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001044hardware::Return<void> Camera3Device::processCaptureResult_3_4(
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001045 const hardware::hidl_vec<
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001046 hardware::camera::device::V3_4::CaptureResult>& results) {
Yin-Chia Yeh657c1872017-07-18 18:09:57 -07001047 // Ideally we should grab mLock, but that can lead to deadlock, and
1048 // it's not super important to get up to date value of mStatus for this
1049 // warning print, hence skipping the lock here
1050 if (mStatus == STATUS_ERROR) {
1051 // Per API contract, HAL should act as closed after device error
1052 // But mStatus can be set to error by framework as well, so just log
1053 // a warning here.
1054 ALOGW("%s: received capture result in error state.", __FUNCTION__);
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07001055 }
Yifan Honga640c5a2017-04-12 16:30:31 -07001056
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001057 sp<NotificationListener> listener;
1058 {
1059 std::lock_guard<std::mutex> l(mOutputLock);
1060 listener = mListener.promote();
1061 }
1062
Yifan Honga640c5a2017-04-12 16:30:31 -07001063 if (mProcessCaptureResultLock.tryLock() != OK) {
1064 // This should never happen; it indicates a wrong client implementation
1065 // that doesn't follow the contract. But, we can be tolerant here.
1066 ALOGE("%s: callback overlapped! waiting 1s...",
1067 __FUNCTION__);
1068 if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
1069 ALOGE("%s: cannot acquire lock in 1s, dropping results",
1070 __FUNCTION__);
1071 // really don't know what to do, so bail out.
1072 return hardware::Void();
1073 }
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001074 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001075 CaptureOutputStates states {
1076 mId,
Shuzhen Wangb7b42652020-05-07 11:59:02 -07001077 mInFlightLock, mLastCompletedRegularFrameNumber,
1078 mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
1079 mInFlightMap, mOutputLock, mResultQueue, mResultSignal,
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001080 mNextShutterFrameNumber,
1081 mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
1082 mNextResultFrameNumber,
1083 mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
1084 mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
1085 mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08001086 mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
Shuzhen Wang316781a2020-08-18 18:11:01 -07001087 mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
1088 *mInterface
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001089 };
1090
Yifan Honga640c5a2017-04-12 16:30:31 -07001091 for (const auto& result : results) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001092 processOneCaptureResultLocked(states, result.v3_2, result.physicalCameraMetadata);
Yifan Honga640c5a2017-04-12 16:30:31 -07001093 }
1094 mProcessCaptureResultLock.unlock();
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001095 return hardware::Void();
1096}
1097
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001098// Only one processCaptureResult should be called at a time, so
1099// the locks won't block. The locks are present here simply to enforce this.
1100hardware::Return<void> Camera3Device::processCaptureResult(
1101 const hardware::hidl_vec<
1102 hardware::camera::device::V3_2::CaptureResult>& results) {
1103 hardware::hidl_vec<hardware::camera::device::V3_4::PhysicalCameraMetadata> noPhysMetadata;
1104
1105 // Ideally we should grab mLock, but that can lead to deadlock, and
1106 // it's not super important to get up to date value of mStatus for this
1107 // warning print, hence skipping the lock here
1108 if (mStatus == STATUS_ERROR) {
1109 // Per API contract, HAL should act as closed after device error
1110 // But mStatus can be set to error by framework as well, so just log
1111 // a warning here.
1112 ALOGW("%s: received capture result in error state.", __FUNCTION__);
1113 }
1114
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001115 sp<NotificationListener> listener;
1116 {
1117 std::lock_guard<std::mutex> l(mOutputLock);
1118 listener = mListener.promote();
1119 }
1120
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001121 if (mProcessCaptureResultLock.tryLock() != OK) {
1122 // This should never happen; it indicates a wrong client implementation
1123 // that doesn't follow the contract. But, we can be tolerant here.
1124 ALOGE("%s: callback overlapped! waiting 1s...",
1125 __FUNCTION__);
1126 if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
1127 ALOGE("%s: cannot acquire lock in 1s, dropping results",
1128 __FUNCTION__);
1129 // really don't know what to do, so bail out.
1130 return hardware::Void();
1131 }
1132 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001133
1134 CaptureOutputStates states {
1135 mId,
Shuzhen Wangb7b42652020-05-07 11:59:02 -07001136 mInFlightLock, mLastCompletedRegularFrameNumber,
1137 mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
1138 mInFlightMap, mOutputLock, mResultQueue, mResultSignal,
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001139 mNextShutterFrameNumber,
1140 mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
1141 mNextResultFrameNumber,
1142 mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
1143 mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
1144 mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08001145 mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
Shuzhen Wang316781a2020-08-18 18:11:01 -07001146 mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
1147 *mInterface
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001148 };
1149
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001150 for (const auto& result : results) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001151 processOneCaptureResultLocked(states, result, noPhysMetadata);
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001152 }
1153 mProcessCaptureResultLock.unlock();
1154 return hardware::Void();
1155}
1156
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001157hardware::Return<void> Camera3Device::notify(
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001158 const hardware::hidl_vec<hardware::camera::device::V3_2::NotifyMsg>& msgs) {
Yin-Chia Yeh657c1872017-07-18 18:09:57 -07001159 // Ideally we should grab mLock, but that can lead to deadlock, and
1160 // it's not super important to get up to date value of mStatus for this
1161 // warning print, hence skipping the lock here
1162 if (mStatus == STATUS_ERROR) {
1163 // Per API contract, HAL should act as closed after device error
1164 // But mStatus can be set to error by framework as well, so just log
1165 // a warning here.
1166 ALOGW("%s: received notify message in error state.", __FUNCTION__);
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07001167 }
Yin-Chia Yeh657c1872017-07-18 18:09:57 -07001168
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001169 sp<NotificationListener> listener;
1170 {
1171 std::lock_guard<std::mutex> l(mOutputLock);
1172 listener = mListener.promote();
1173 }
1174
1175 CaptureOutputStates states {
1176 mId,
Shuzhen Wangb7b42652020-05-07 11:59:02 -07001177 mInFlightLock, mLastCompletedRegularFrameNumber,
1178 mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
1179 mInFlightMap, mOutputLock, mResultQueue, mResultSignal,
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001180 mNextShutterFrameNumber,
1181 mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
1182 mNextResultFrameNumber,
1183 mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
1184 mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
1185 mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08001186 mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
Shuzhen Wang316781a2020-08-18 18:11:01 -07001187 mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
1188 *mInterface
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001189 };
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001190 for (const auto& msg : msgs) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001191 camera3::notify(states, msg);
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001192 }
1193 return hardware::Void();
1194}
1195
Emilian Peevaebbe412018-01-15 13:53:24 +00001196status_t Camera3Device::captureList(const List<const PhysicalCameraSettingsList> &requestsList,
Shuzhen Wang0129d522016-10-30 22:43:41 -07001197 const std::list<const SurfaceMap> &surfaceMaps,
Jianing Weicb0652e2014-03-12 18:29:36 -07001198 int64_t *lastFrameNumber) {
Jianing Wei90e59c92014-03-12 18:29:36 -07001199 ATRACE_CALL();
1200
Emilian Peevaebbe412018-01-15 13:53:24 +00001201 return submitRequestsHelper(requestsList, surfaceMaps, /*repeating*/false, lastFrameNumber);
Jianing Wei90e59c92014-03-12 18:29:36 -07001202}
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001203
Jianing Weicb0652e2014-03-12 18:29:36 -07001204status_t Camera3Device::setStreamingRequest(const CameraMetadata &request,
1205 int64_t* /*lastFrameNumber*/) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001206 ATRACE_CALL();
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001207
Emilian Peevaebbe412018-01-15 13:53:24 +00001208 List<const PhysicalCameraSettingsList> requestsList;
Shuzhen Wang0129d522016-10-30 22:43:41 -07001209 std::list<const SurfaceMap> surfaceMaps;
Emilian Peevaebbe412018-01-15 13:53:24 +00001210 convertToRequestList(requestsList, surfaceMaps, request);
Shuzhen Wang0129d522016-10-30 22:43:41 -07001211
Emilian Peevaebbe412018-01-15 13:53:24 +00001212 return setStreamingRequestList(requestsList, /*surfaceMap*/surfaceMaps,
Shuzhen Wang0129d522016-10-30 22:43:41 -07001213 /*lastFrameNumber*/NULL);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001214}
1215
Emilian Peevaebbe412018-01-15 13:53:24 +00001216status_t Camera3Device::setStreamingRequestList(
1217 const List<const PhysicalCameraSettingsList> &requestsList,
1218 const std::list<const SurfaceMap> &surfaceMaps, int64_t *lastFrameNumber) {
Jianing Wei90e59c92014-03-12 18:29:36 -07001219 ATRACE_CALL();
1220
Emilian Peevaebbe412018-01-15 13:53:24 +00001221 return submitRequestsHelper(requestsList, surfaceMaps, /*repeating*/true, lastFrameNumber);
Jianing Wei90e59c92014-03-12 18:29:36 -07001222}
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001223
1224sp<Camera3Device::CaptureRequest> Camera3Device::setUpRequestLocked(
Emilian Peevaebbe412018-01-15 13:53:24 +00001225 const PhysicalCameraSettingsList &request, const SurfaceMap &surfaceMap) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001226 status_t res;
1227
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001228 if (mStatus == STATUS_UNCONFIGURED || mNeedConfig) {
Eino-Ville Talvalae7091aa2017-03-07 15:23:06 -08001229 // This point should only be reached via API1 (API2 must explicitly call configureStreams)
1230 // so unilaterally select normal operating mode.
Emilian Peevaebbe412018-01-15 13:53:24 +00001231 res = filterParamsAndConfigureLocked(request.begin()->metadata,
Emilian Peevf4816702020-04-03 15:44:51 -07001232 CAMERA_STREAM_CONFIGURATION_NORMAL_MODE);
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07001233 // Stream configuration failed. Client might try other configuraitons.
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001234 if (res != OK) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07001235 CLOGE("Can't set up streams: %s (%d)", strerror(-res), res);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001236 return NULL;
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07001237 } else if (mStatus == STATUS_UNCONFIGURED) {
1238 // Stream configuration successfully configure to empty stream configuration.
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001239 CLOGE("No streams configured");
1240 return NULL;
1241 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001242 }
1243
Shuzhen Wang0129d522016-10-30 22:43:41 -07001244 sp<CaptureRequest> newRequest = createCaptureRequest(request, surfaceMap);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001245 return newRequest;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001246}
1247
Jianing Weicb0652e2014-03-12 18:29:36 -07001248status_t Camera3Device::clearStreamingRequest(int64_t *lastFrameNumber) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001249 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001250 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001251 Mutex::Autolock l(mLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001252
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001253 switch (mStatus) {
1254 case STATUS_ERROR:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001255 CLOGE("Device has encountered a serious error");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001256 return INVALID_OPERATION;
1257 case STATUS_UNINITIALIZED:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001258 CLOGE("Device not initialized");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001259 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001260 case STATUS_UNCONFIGURED:
1261 case STATUS_CONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001262 case STATUS_ACTIVE:
1263 // OK
1264 break;
1265 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001266 SET_ERR_L("Unexpected status: %d", mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001267 return INVALID_OPERATION;
1268 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001269 ALOGV("Camera %s: Clearing repeating request", mId.string());
Jianing Weicb0652e2014-03-12 18:29:36 -07001270
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07001271 return mRequestThread->clearRepeatingRequests(lastFrameNumber);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001272}
1273
1274status_t Camera3Device::waitUntilRequestReceived(int32_t requestId, nsecs_t timeout) {
1275 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001276 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001277
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001278 return mRequestThread->waitUntilRequestProcessed(requestId, timeout);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001279}
1280
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001281status_t Camera3Device::createInputStream(
Shuzhen Wang83bff122020-11-20 15:51:39 -08001282 uint32_t width, uint32_t height, int format, bool isMultiResolution, int *id) {
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001283 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001284 Mutex::Autolock il(mInterfaceLock);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001285 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001286 Mutex::Autolock l(mLock);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001287 ALOGV("Camera %s: Creating new input stream %d: %d x %d, format %d",
1288 mId.string(), mNextStreamId, width, height, format);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001289
1290 status_t res;
1291 bool wasActive = false;
1292
1293 switch (mStatus) {
1294 case STATUS_ERROR:
1295 ALOGE("%s: Device has encountered a serious error", __FUNCTION__);
1296 return INVALID_OPERATION;
1297 case STATUS_UNINITIALIZED:
1298 ALOGE("%s: Device not initialized", __FUNCTION__);
1299 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001300 case STATUS_UNCONFIGURED:
1301 case STATUS_CONFIGURED:
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001302 // OK
1303 break;
1304 case STATUS_ACTIVE:
1305 ALOGV("%s: Stopping activity to reconfigure streams", __FUNCTION__);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001306 res = internalPauseAndWaitLocked(maxExpectedDuration);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001307 if (res != OK) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001308 SET_ERR_L("Can't pause captures to reconfigure streams!");
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001309 return res;
1310 }
1311 wasActive = true;
1312 break;
1313 default:
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001314 SET_ERR_L("%s: Unexpected status: %d", mStatus);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001315 return INVALID_OPERATION;
1316 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001317 assert(mStatus != STATUS_ACTIVE);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001318
1319 if (mInputStream != 0) {
1320 ALOGE("%s: Cannot create more than 1 input stream", __FUNCTION__);
1321 return INVALID_OPERATION;
1322 }
1323
1324 sp<Camera3InputStream> newStream = new Camera3InputStream(mNextStreamId,
1325 width, height, format);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001326 newStream->setStatusTracker(mStatusTracker);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001327
1328 mInputStream = newStream;
Shuzhen Wang83bff122020-11-20 15:51:39 -08001329 mIsInputStreamMultiResolution = isMultiResolution;
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001330
1331 *id = mNextStreamId++;
1332
1333 // Continue captures if active at start
1334 if (wasActive) {
1335 ALOGV("%s: Restarting activity to reconfigure streams", __FUNCTION__);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001336 // Reuse current operating mode and session parameters for new stream config
1337 res = configureStreamsLocked(mOperatingMode, mSessionParams);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001338 if (res != OK) {
1339 ALOGE("%s: Can't reconfigure device for new stream %d: %s (%d)",
1340 __FUNCTION__, mNextStreamId, strerror(-res), res);
1341 return res;
1342 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001343 internalResumeLocked();
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001344 }
1345
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001346 ALOGV("Camera %s: Created input stream", mId.string());
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001347 return OK;
1348}
1349
Eino-Ville Talvala727d1722015-06-09 13:44:19 -07001350status_t Camera3Device::createStream(sp<Surface> consumer,
Shuzhen Wang0129d522016-10-30 22:43:41 -07001351 uint32_t width, uint32_t height, int format,
Emilian Peevf4816702020-04-03 15:44:51 -07001352 android_dataspace dataSpace, camera_stream_rotation_t rotation, int *id,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001353 const String8& physicalCameraId,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001354 const std::unordered_set<int32_t> &sensorPixelModesUsed,
1355 std::vector<int> *surfaceIds, int streamSetId, bool isShared, bool isMultiResolution,
1356 uint64_t consumerUsage) {
Shuzhen Wang0129d522016-10-30 22:43:41 -07001357 ATRACE_CALL();
1358
1359 if (consumer == nullptr) {
1360 ALOGE("%s: consumer must not be null", __FUNCTION__);
1361 return BAD_VALUE;
1362 }
1363
1364 std::vector<sp<Surface>> consumers;
1365 consumers.push_back(consumer);
1366
1367 return createStream(consumers, /*hasDeferredConsumer*/ false, width, height,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001368 format, dataSpace, rotation, id, physicalCameraId, sensorPixelModesUsed, surfaceIds,
1369 streamSetId, isShared, isMultiResolution, consumerUsage);
1370}
1371
1372static bool isRawFormat(int format) {
1373 switch (format) {
1374 case HAL_PIXEL_FORMAT_RAW16:
1375 case HAL_PIXEL_FORMAT_RAW12:
1376 case HAL_PIXEL_FORMAT_RAW10:
1377 case HAL_PIXEL_FORMAT_RAW_OPAQUE:
1378 return true;
1379 default:
1380 return false;
1381 }
Shuzhen Wang0129d522016-10-30 22:43:41 -07001382}
1383
1384status_t Camera3Device::createStream(const std::vector<sp<Surface>>& consumers,
1385 bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
Emilian Peevf4816702020-04-03 15:44:51 -07001386 android_dataspace dataSpace, camera_stream_rotation_t rotation, int *id,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001387 const String8& physicalCameraId, const std::unordered_set<int32_t> &sensorPixelModesUsed,
Shuzhen Wang83bff122020-11-20 15:51:39 -08001388 std::vector<int> *surfaceIds, int streamSetId, bool isShared, bool isMultiResolution,
1389 uint64_t consumerUsage) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001390 ATRACE_CALL();
Emilian Peev40ead602017-09-26 15:46:36 +01001391
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001392 Mutex::Autolock il(mInterfaceLock);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001393 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001394 Mutex::Autolock l(mLock);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001395 ALOGV("Camera %s: Creating new stream %d: %d x %d, format %d, dataspace %d rotation %d"
Shuzhen Wang83bff122020-11-20 15:51:39 -08001396 " consumer usage %" PRIu64 ", isShared %d, physicalCameraId %s, isMultiResolution %d",
1397 mId.string(), mNextStreamId, width, height, format, dataSpace, rotation,
1398 consumerUsage, isShared, physicalCameraId.string(), isMultiResolution);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001399
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001400 status_t res;
1401 bool wasActive = false;
1402
1403 switch (mStatus) {
1404 case STATUS_ERROR:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001405 CLOGE("Device has encountered a serious error");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001406 return INVALID_OPERATION;
1407 case STATUS_UNINITIALIZED:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001408 CLOGE("Device not initialized");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001409 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001410 case STATUS_UNCONFIGURED:
1411 case STATUS_CONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001412 // OK
1413 break;
1414 case STATUS_ACTIVE:
1415 ALOGV("%s: Stopping activity to reconfigure streams", __FUNCTION__);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001416 res = internalPauseAndWaitLocked(maxExpectedDuration);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001417 if (res != OK) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001418 SET_ERR_L("Can't pause captures to reconfigure streams!");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001419 return res;
1420 }
1421 wasActive = true;
1422 break;
1423 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001424 SET_ERR_L("Unexpected status: %d", mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001425 return INVALID_OPERATION;
1426 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001427 assert(mStatus != STATUS_ACTIVE);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001428
1429 sp<Camera3OutputStream> newStream;
Zhijun He5d677d12016-05-29 16:52:39 -07001430
Shuzhen Wang0129d522016-10-30 22:43:41 -07001431 if (consumers.size() == 0 && !hasDeferredConsumer) {
1432 ALOGE("%s: Number of consumers cannot be smaller than 1", __FUNCTION__);
1433 return BAD_VALUE;
1434 }
Zhijun He5d677d12016-05-29 16:52:39 -07001435
Shuzhen Wang0129d522016-10-30 22:43:41 -07001436 if (hasDeferredConsumer && format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
Zhijun He5d677d12016-05-29 16:52:39 -07001437 ALOGE("Deferred consumer stream creation only support IMPLEMENTATION_DEFINED format");
1438 return BAD_VALUE;
1439 }
1440
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001441 if (isRawFormat(format) && sensorPixelModesUsed.size() > 1) {
1442 // We can't use one stream with a raw format in both sensor pixel modes since its going to
1443 // be found in only one sensor pixel mode.
1444 ALOGE("%s: RAW opaque stream cannot be used with > 1 sensor pixel modes", __FUNCTION__);
1445 return BAD_VALUE;
1446 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001447 if (format == HAL_PIXEL_FORMAT_BLOB) {
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -07001448 ssize_t blobBufferSize;
Shuzhen Wang68ac7ad2019-01-30 14:03:28 -08001449 if (dataSpace == HAL_DATASPACE_DEPTH) {
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -07001450 blobBufferSize = getPointCloudBufferSize();
1451 if (blobBufferSize <= 0) {
1452 SET_ERR_L("Invalid point cloud buffer size %zd", blobBufferSize);
1453 return BAD_VALUE;
1454 }
Shuzhen Wang68ac7ad2019-01-30 14:03:28 -08001455 } else if (dataSpace == static_cast<android_dataspace>(HAL_DATASPACE_JPEG_APP_SEGMENTS)) {
1456 blobBufferSize = width * height;
1457 } else {
1458 blobBufferSize = getJpegBufferSize(width, height);
1459 if (blobBufferSize <= 0) {
1460 SET_ERR_L("Invalid jpeg buffer size %zd", blobBufferSize);
1461 return BAD_VALUE;
1462 }
Zhijun Hef7da0962014-04-24 13:27:56 -07001463 }
Shuzhen Wang0129d522016-10-30 22:43:41 -07001464 newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
Shuzhen Wangc28dccc2016-02-11 23:48:46 -08001465 width, height, blobBufferSize, format, dataSpace, rotation,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001466 mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
1467 isMultiResolution);
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -08001468 } else if (format == HAL_PIXEL_FORMAT_RAW_OPAQUE) {
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001469 bool maxResolution =
1470 sensorPixelModesUsed.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
1471 sensorPixelModesUsed.end();
1472 ssize_t rawOpaqueBufferSize = getRawOpaqueBufferSize(width, height, maxResolution);
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -08001473 if (rawOpaqueBufferSize <= 0) {
1474 SET_ERR_L("Invalid RAW opaque buffer size %zd", rawOpaqueBufferSize);
1475 return BAD_VALUE;
1476 }
Shuzhen Wang0129d522016-10-30 22:43:41 -07001477 newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
Shuzhen Wangc28dccc2016-02-11 23:48:46 -08001478 width, height, rawOpaqueBufferSize, format, dataSpace, rotation,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001479 mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
1480 isMultiResolution);
Shuzhen Wang758c2152017-01-10 18:26:18 -08001481 } else if (isShared) {
1482 newStream = new Camera3SharedOutputStream(mNextStreamId, consumers,
1483 width, height, format, consumerUsage, dataSpace, rotation,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001484 mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
1485 mUseHalBufManager);
Shuzhen Wang0129d522016-10-30 22:43:41 -07001486 } else if (consumers.size() == 0 && hasDeferredConsumer) {
Zhijun He5d677d12016-05-29 16:52:39 -07001487 newStream = new Camera3OutputStream(mNextStreamId,
1488 width, height, format, consumerUsage, dataSpace, rotation,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001489 mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
1490 isMultiResolution);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001491 } else {
Shuzhen Wang0129d522016-10-30 22:43:41 -07001492 newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
Shuzhen Wangc28dccc2016-02-11 23:48:46 -08001493 width, height, format, dataSpace, rotation,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08001494 mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
1495 isMultiResolution);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001496 }
Emilian Peev40ead602017-09-26 15:46:36 +01001497
1498 size_t consumerCount = consumers.size();
1499 for (size_t i = 0; i < consumerCount; i++) {
1500 int id = newStream->getSurfaceId(consumers[i]);
1501 if (id < 0) {
1502 SET_ERR_L("Invalid surface id");
1503 return BAD_VALUE;
1504 }
1505 if (surfaceIds != nullptr) {
1506 surfaceIds->push_back(id);
1507 }
1508 }
1509
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001510 newStream->setStatusTracker(mStatusTracker);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001511
Emilian Peev08dd2452017-04-06 16:55:14 +01001512 newStream->setBufferManager(mBufferManager);
Zhijun He125684a2015-12-26 15:07:30 -08001513
Shuzhen Wangabbcb6b2020-12-09 22:32:44 -08001514 newStream->setImageDumpMask(mImageDumpMask);
1515
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001516 res = mOutputStreams.add(mNextStreamId, newStream);
1517 if (res < 0) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001518 SET_ERR_L("Can't add new stream to set: %s (%d)", strerror(-res), res);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001519 return res;
1520 }
1521
Shuzhen Wang316781a2020-08-18 18:11:01 -07001522 mSessionStatsBuilder.addStream(mNextStreamId);
1523
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001524 *id = mNextStreamId++;
Eino-Ville Talvalaea26c772013-06-11 16:04:06 -07001525 mNeedConfig = true;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001526
1527 // Continue captures if active at start
1528 if (wasActive) {
1529 ALOGV("%s: Restarting activity to reconfigure streams", __FUNCTION__);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001530 // Reuse current operating mode and session parameters for new stream config
1531 res = configureStreamsLocked(mOperatingMode, mSessionParams);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001532 if (res != OK) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001533 CLOGE("Can't reconfigure device for new stream %d: %s (%d)",
1534 mNextStreamId, strerror(-res), res);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001535 return res;
1536 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001537 internalResumeLocked();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001538 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001539 ALOGV("Camera %s: Created new stream", mId.string());
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001540 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001541}
1542
Emilian Peev710c1422017-08-30 11:19:38 +01001543status_t Camera3Device::getStreamInfo(int id, StreamInfo *streamInfo) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001544 ATRACE_CALL();
Emilian Peev710c1422017-08-30 11:19:38 +01001545 if (nullptr == streamInfo) {
1546 return BAD_VALUE;
1547 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001548 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001549 Mutex::Autolock l(mLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001550
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001551 switch (mStatus) {
1552 case STATUS_ERROR:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001553 CLOGE("Device has encountered a serious error");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001554 return INVALID_OPERATION;
1555 case STATUS_UNINITIALIZED:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001556 CLOGE("Device not initialized!");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001557 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001558 case STATUS_UNCONFIGURED:
1559 case STATUS_CONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001560 case STATUS_ACTIVE:
1561 // OK
1562 break;
1563 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001564 SET_ERR_L("Unexpected status: %d", mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001565 return INVALID_OPERATION;
1566 }
1567
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001568 sp<Camera3StreamInterface> stream = mOutputStreams.get(id);
1569 if (stream == nullptr) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001570 CLOGE("Stream %d is unknown", id);
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001571 return BAD_VALUE;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001572 }
1573
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001574 streamInfo->width = stream->getWidth();
1575 streamInfo->height = stream->getHeight();
1576 streamInfo->format = stream->getFormat();
1577 streamInfo->dataSpace = stream->getDataSpace();
1578 streamInfo->formatOverridden = stream->isFormatOverridden();
1579 streamInfo->originalFormat = stream->getOriginalFormat();
1580 streamInfo->dataSpaceOverridden = stream->isDataSpaceOverridden();
1581 streamInfo->originalDataSpace = stream->getOriginalDataSpace();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001582 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001583}
1584
1585status_t Camera3Device::setStreamTransform(int id,
1586 int transform) {
1587 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001588 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001589 Mutex::Autolock l(mLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001590
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001591 switch (mStatus) {
1592 case STATUS_ERROR:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001593 CLOGE("Device has encountered a serious error");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001594 return INVALID_OPERATION;
1595 case STATUS_UNINITIALIZED:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001596 CLOGE("Device not initialized");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001597 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001598 case STATUS_UNCONFIGURED:
1599 case STATUS_CONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001600 case STATUS_ACTIVE:
1601 // OK
1602 break;
1603 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001604 SET_ERR_L("Unexpected status: %d", mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001605 return INVALID_OPERATION;
1606 }
1607
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001608 sp<Camera3OutputStreamInterface> stream = mOutputStreams.get(id);
1609 if (stream == nullptr) {
1610 CLOGE("Stream %d does not exist", id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001611 return BAD_VALUE;
1612 }
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001613 return stream->setTransform(transform);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001614}
1615
1616status_t Camera3Device::deleteStream(int id) {
1617 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001618 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001619 Mutex::Autolock l(mLock);
1620 status_t res;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001621
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001622 ALOGV("%s: Camera %s: Deleting stream %d", __FUNCTION__, mId.string(), id);
Igor Murashkine2172be2013-05-28 15:31:39 -07001623
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001624 // CameraDevice semantics require device to already be idle before
1625 // deleteStream is called, unlike for createStream.
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001626 if (mStatus == STATUS_ACTIVE) {
Yin-Chia Yeh693047d2018-03-08 12:14:19 -08001627 ALOGW("%s: Camera %s: Device not idle", __FUNCTION__, mId.string());
Igor Murashkin52827132013-05-13 14:53:44 -07001628 return -EBUSY;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001629 }
1630
Yin-Chia Yeh5090c732017-07-20 16:05:29 -07001631 if (mStatus == STATUS_ERROR) {
1632 ALOGW("%s: Camera %s: deleteStream not allowed in ERROR state",
1633 __FUNCTION__, mId.string());
1634 return -EBUSY;
1635 }
1636
Igor Murashkin2fba5842013-04-22 14:03:54 -07001637 sp<Camera3StreamInterface> deletedStream;
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001638 sp<Camera3StreamInterface> stream = mOutputStreams.get(id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001639 if (mInputStream != NULL && id == mInputStream->getId()) {
1640 deletedStream = mInputStream;
1641 mInputStream.clear();
1642 } else {
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001643 if (stream == nullptr) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001644 CLOGE("Stream %d does not exist", id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001645 return BAD_VALUE;
1646 }
Shuzhen Wang316781a2020-08-18 18:11:01 -07001647 mSessionStatsBuilder.removeStream(id);
Zhijun He5f446352014-01-22 09:49:33 -08001648 }
1649
1650 // Delete output stream or the output part of a bi-directional stream.
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001651 if (stream != nullptr) {
1652 deletedStream = stream;
1653 mOutputStreams.remove(id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001654 }
1655
1656 // Free up the stream endpoint so that it can be used by some other stream
1657 res = deletedStream->disconnect();
1658 if (res != OK) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001659 SET_ERR_L("Can't disconnect deleted stream %d", id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001660 // fall through since we want to still list the stream as deleted.
1661 }
1662 mDeletedStreams.add(deletedStream);
Eino-Ville Talvalaea26c772013-06-11 16:04:06 -07001663 mNeedConfig = true;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001664
1665 return res;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001666}
1667
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001668status_t Camera3Device::configureStreams(const CameraMetadata& sessionParams, int operatingMode) {
Igor Murashkine2d167e2014-08-19 16:19:59 -07001669 ATRACE_CALL();
1670 ALOGV("%s: E", __FUNCTION__);
1671
1672 Mutex::Autolock il(mInterfaceLock);
1673 Mutex::Autolock l(mLock);
Chien-Yu Chen17338fc2015-06-18 16:30:12 -07001674
Emilian Peev811d2952018-05-25 11:08:40 +01001675 // In case the client doesn't include any session parameter, try a
1676 // speculative configuration using the values from the last cached
1677 // default request.
1678 if (sessionParams.isEmpty() &&
Emilian Peevf4816702020-04-03 15:44:51 -07001679 ((mLastTemplateId > 0) && (mLastTemplateId < CAMERA_TEMPLATE_COUNT)) &&
Emilian Peev811d2952018-05-25 11:08:40 +01001680 (!mRequestTemplateCache[mLastTemplateId].isEmpty())) {
1681 ALOGV("%s: Speculative session param configuration with template id: %d", __func__,
1682 mLastTemplateId);
1683 return filterParamsAndConfigureLocked(mRequestTemplateCache[mLastTemplateId],
1684 operatingMode);
1685 }
1686
Emilian Peevac3ce6c2017-12-12 15:27:02 +00001687 return filterParamsAndConfigureLocked(sessionParams, operatingMode);
1688}
1689
1690status_t Camera3Device::filterParamsAndConfigureLocked(const CameraMetadata& sessionParams,
1691 int operatingMode) {
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001692 //Filter out any incoming session parameters
1693 const CameraMetadata params(sessionParams);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001694 camera_metadata_entry_t availableSessionKeys = mDeviceInfo.find(
1695 ANDROID_REQUEST_AVAILABLE_SESSION_KEYS);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00001696 CameraMetadata filteredParams(availableSessionKeys.count);
1697 camera_metadata_t *meta = const_cast<camera_metadata_t *>(
1698 filteredParams.getAndLock());
1699 set_camera_metadata_vendor_id(meta, mVendorTagId);
1700 filteredParams.unlock(meta);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001701 if (availableSessionKeys.count > 0) {
1702 for (size_t i = 0; i < availableSessionKeys.count; i++) {
1703 camera_metadata_ro_entry entry = params.find(
1704 availableSessionKeys.data.i32[i]);
1705 if (entry.count > 0) {
1706 filteredParams.update(entry);
1707 }
1708 }
1709 }
1710
1711 return configureStreamsLocked(operatingMode, filteredParams);
Igor Murashkine2d167e2014-08-19 16:19:59 -07001712}
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001713
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -07001714status_t Camera3Device::getInputBufferProducer(
1715 sp<IGraphicBufferProducer> *producer) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07001716 ATRACE_CALL();
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -07001717 Mutex::Autolock il(mInterfaceLock);
1718 Mutex::Autolock l(mLock);
1719
1720 if (producer == NULL) {
1721 return BAD_VALUE;
1722 } else if (mInputStream == NULL) {
1723 return INVALID_OPERATION;
1724 }
1725
1726 return mInputStream->getInputBufferProducer(producer);
1727}
1728
Emilian Peevf4816702020-04-03 15:44:51 -07001729status_t Camera3Device::createDefaultRequest(camera_request_template_t templateId,
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001730 CameraMetadata *request) {
1731 ATRACE_CALL();
Alex Rayfe7e0c62013-05-30 00:12:13 -07001732 ALOGV("%s: for template %d", __FUNCTION__, templateId);
Chien-Yu Chen9cd14022016-03-09 12:21:01 -08001733
Emilian Peevf4816702020-04-03 15:44:51 -07001734 if (templateId <= 0 || templateId >= CAMERA_TEMPLATE_COUNT) {
Chien-Yu Chen9cd14022016-03-09 12:21:01 -08001735 android_errorWriteWithInfoLog(CameraService::SN_EVENT_LOG_ID, "26866110",
Jayant Chowdhary12361932018-08-27 14:46:13 -07001736 CameraThreadState::getCallingUid(), nullptr, 0);
Chien-Yu Chen9cd14022016-03-09 12:21:01 -08001737 return BAD_VALUE;
1738 }
1739
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001740 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001741
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001742 {
1743 Mutex::Autolock l(mLock);
1744 switch (mStatus) {
1745 case STATUS_ERROR:
1746 CLOGE("Device has encountered a serious error");
1747 return INVALID_OPERATION;
1748 case STATUS_UNINITIALIZED:
1749 CLOGE("Device is not initialized!");
1750 return INVALID_OPERATION;
1751 case STATUS_UNCONFIGURED:
1752 case STATUS_CONFIGURED:
1753 case STATUS_ACTIVE:
1754 // OK
1755 break;
1756 default:
1757 SET_ERR_L("Unexpected status: %d", mStatus);
1758 return INVALID_OPERATION;
1759 }
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001760
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001761 if (!mRequestTemplateCache[templateId].isEmpty()) {
1762 *request = mRequestTemplateCache[templateId];
Emilian Peev811d2952018-05-25 11:08:40 +01001763 mLastTemplateId = templateId;
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001764 return OK;
1765 }
Zhijun Hea1530f12014-09-14 12:44:20 -07001766 }
1767
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001768 camera_metadata_t *rawRequest;
1769 status_t res = mInterface->constructDefaultRequestSettings(
Emilian Peevf4816702020-04-03 15:44:51 -07001770 (camera_request_template_t) templateId, &rawRequest);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001771
1772 {
1773 Mutex::Autolock l(mLock);
1774 if (res == BAD_VALUE) {
1775 ALOGI("%s: template %d is not supported on this camera device",
1776 __FUNCTION__, templateId);
1777 return res;
1778 } else if (res != OK) {
1779 CLOGE("Unable to construct request template %d: %s (%d)",
1780 templateId, strerror(-res), res);
1781 return res;
1782 }
1783
1784 set_camera_metadata_vendor_id(rawRequest, mVendorTagId);
1785 mRequestTemplateCache[templateId].acquire(rawRequest);
1786
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08001787 // Override the template request with zoomRatioMapper
1788 res = mZoomRatioMappers[mId.c_str()].initZoomRatioInTemplate(
1789 &mRequestTemplateCache[templateId]);
1790 if (res != OK) {
1791 CLOGE("Failed to update zoom ratio for template %d: %s (%d)",
1792 templateId, strerror(-res), res);
1793 return res;
1794 }
1795
Shuzhen Wangd25dc972020-03-24 17:11:43 -07001796 // Fill in JPEG_QUALITY if not available
1797 if (!mRequestTemplateCache[templateId].exists(ANDROID_JPEG_QUALITY)) {
1798 static const uint8_t kDefaultJpegQuality = 95;
1799 mRequestTemplateCache[templateId].update(ANDROID_JPEG_QUALITY,
1800 &kDefaultJpegQuality, 1);
1801 }
1802
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001803 *request = mRequestTemplateCache[templateId];
Emilian Peev811d2952018-05-25 11:08:40 +01001804 mLastTemplateId = templateId;
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001805 }
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001806 return OK;
1807}
1808
1809status_t Camera3Device::waitUntilDrained() {
1810 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001811 Mutex::Autolock il(mInterfaceLock);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001812 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001813 Mutex::Autolock l(mLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001814
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001815 return waitUntilDrainedLocked(maxExpectedDuration);
Zhijun He69a37482014-03-23 18:44:49 -07001816}
1817
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001818status_t Camera3Device::waitUntilDrainedLocked(nsecs_t maxExpectedDuration) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001819 switch (mStatus) {
1820 case STATUS_UNINITIALIZED:
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001821 case STATUS_UNCONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001822 ALOGV("%s: Already idle", __FUNCTION__);
1823 return OK;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001824 case STATUS_CONFIGURED:
1825 // To avoid race conditions, check with tracker to be sure
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001826 case STATUS_ERROR:
1827 case STATUS_ACTIVE:
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001828 // Need to verify shut down
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001829 break;
1830 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001831 SET_ERR_L("Unexpected status: %d",mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001832 return INVALID_OPERATION;
1833 }
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07001834 ALOGV("%s: Camera %s: Waiting until idle (%" PRIi64 "ns)", __FUNCTION__, mId.string(),
1835 maxExpectedDuration);
1836 status_t res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration);
Eino-Ville Talvala9c8a0912014-09-14 14:52:19 -07001837 if (res != OK) {
Yin-Chia Yeh87b3ec02019-06-03 10:44:39 -07001838 mStatusTracker->dumpActiveComponents();
Eino-Ville Talvala9c8a0912014-09-14 14:52:19 -07001839 SET_ERR_L("Error waiting for HAL to drain: %s (%d)", strerror(-res),
1840 res);
1841 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001842 return res;
1843}
1844
Ruben Brunk183f0562015-08-12 12:55:02 -07001845void Camera3Device::internalUpdateStatusLocked(Status status) {
1846 mStatus = status;
1847 mRecentStatusUpdates.add(mStatus);
1848 mStatusChanged.broadcast();
1849}
1850
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001851// Pause to reconfigure
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001852status_t Camera3Device::internalPauseAndWaitLocked(nsecs_t maxExpectedDuration) {
Emilian Peeve86358b2019-02-15 13:51:39 -08001853 if (mRequestThread.get() != nullptr) {
1854 mRequestThread->setPaused(true);
1855 } else {
1856 return NO_INIT;
1857 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001858
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07001859 ALOGV("%s: Camera %s: Internal wait until idle (% " PRIi64 " ns)", __FUNCTION__, mId.string(),
1860 maxExpectedDuration);
1861 status_t res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001862 if (res != OK) {
1863 SET_ERR_L("Can't idle device in %f seconds!",
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07001864 maxExpectedDuration/1e9);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001865 }
1866
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001867 return res;
1868}
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001869
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001870// Resume after internalPauseAndWaitLocked
1871status_t Camera3Device::internalResumeLocked() {
1872 status_t res;
1873
1874 mRequestThread->setPaused(false);
1875
Eino-Ville Talvala002001b2018-01-23 16:53:50 -08001876 ALOGV("%s: Camera %s: Internal wait until active (% " PRIi64 " ns)", __FUNCTION__, mId.string(),
1877 kActiveTimeout);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001878 res = waitUntilStateThenRelock(/*active*/ true, kActiveTimeout);
1879 if (res != OK) {
1880 SET_ERR_L("Can't transition to active in %f seconds!",
1881 kActiveTimeout/1e9);
1882 }
1883 mPauseStateNotify = false;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001884 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001885}
1886
Ruben Brunk183f0562015-08-12 12:55:02 -07001887status_t Camera3Device::waitUntilStateThenRelock(bool active, nsecs_t timeout) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001888 status_t res = OK;
Ruben Brunk183f0562015-08-12 12:55:02 -07001889
1890 size_t startIndex = 0;
1891 if (mStatusWaiters == 0) {
1892 // Clear the list of recent statuses if there are no existing threads waiting on updates to
1893 // this status list
1894 mRecentStatusUpdates.clear();
1895 } else {
1896 // If other threads are waiting on updates to this status list, set the position of the
1897 // first element that this list will check rather than clearing the list.
1898 startIndex = mRecentStatusUpdates.size();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001899 }
1900
Ruben Brunk183f0562015-08-12 12:55:02 -07001901 mStatusWaiters++;
1902
Yin-Chia Yehe52b8fa2020-07-28 00:17:58 -07001903 bool signalPipelineDrain = false;
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07001904 if (!active && mUseHalBufManager) {
1905 auto streamIds = mOutputStreams.getStreamIds();
Yin-Chia Yehcd333fe2019-02-08 13:45:41 -08001906 if (mStatus == STATUS_ACTIVE) {
1907 mRequestThread->signalPipelineDrain(streamIds);
Yin-Chia Yehe52b8fa2020-07-28 00:17:58 -07001908 signalPipelineDrain = true;
Yin-Chia Yehcd333fe2019-02-08 13:45:41 -08001909 }
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07001910 mRequestBufferSM.onWaitUntilIdle();
1911 }
1912
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001913 bool stateSeen = false;
1914 do {
Ruben Brunk183f0562015-08-12 12:55:02 -07001915 if (active == (mStatus == STATUS_ACTIVE)) {
1916 // Desired state is current
1917 break;
1918 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001919
1920 res = mStatusChanged.waitRelative(mLock, timeout);
1921 if (res != OK) break;
1922
Ruben Brunk183f0562015-08-12 12:55:02 -07001923 // This is impossible, but if not, could result in subtle deadlocks and invalid state
1924 // transitions.
1925 LOG_ALWAYS_FATAL_IF(startIndex > mRecentStatusUpdates.size(),
1926 "%s: Skipping status updates in Camera3Device, may result in deadlock.",
1927 __FUNCTION__);
1928
1929 // Encountered desired state since we began waiting
1930 for (size_t i = startIndex; i < mRecentStatusUpdates.size(); i++) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001931 if (active == (mRecentStatusUpdates[i] == STATUS_ACTIVE) ) {
1932 stateSeen = true;
1933 break;
1934 }
1935 }
1936 } while (!stateSeen);
1937
Yin-Chia Yehe52b8fa2020-07-28 00:17:58 -07001938 if (signalPipelineDrain) {
1939 mRequestThread->resetPipelineDrain();
1940 }
1941
Ruben Brunk183f0562015-08-12 12:55:02 -07001942 mStatusWaiters--;
1943
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001944 return res;
1945}
1946
1947
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07001948status_t Camera3Device::setNotifyCallback(wp<NotificationListener> listener) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001949 ATRACE_CALL();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001950 std::lock_guard<std::mutex> l(mOutputLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001951
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001952 if (listener != NULL && mListener != NULL) {
1953 ALOGW("%s: Replacing old callback listener", __FUNCTION__);
1954 }
1955 mListener = listener;
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07001956 mRequestThread->setNotificationListener(listener);
1957 mPreparerThread->setNotificationListener(listener);
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001958
1959 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001960}
1961
Eino-Ville Talvala46910bd2013-07-18 19:15:17 -07001962bool Camera3Device::willNotify3A() {
1963 return false;
1964}
1965
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001966status_t Camera3Device::waitForNextFrame(nsecs_t timeout) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07001967 ATRACE_CALL();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001968 std::unique_lock<std::mutex> l(mOutputLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001969
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001970 while (mResultQueue.empty()) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001971 auto st = mResultSignal.wait_for(l, std::chrono::nanoseconds(timeout));
1972 if (st == std::cv_status::timeout) {
1973 return TIMED_OUT;
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001974 }
1975 }
1976 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001977}
1978
Jianing Weicb0652e2014-03-12 18:29:36 -07001979status_t Camera3Device::getNextResult(CaptureResult *frame) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001980 ATRACE_CALL();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001981 std::lock_guard<std::mutex> l(mOutputLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001982
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001983 if (mResultQueue.empty()) {
1984 return NOT_ENOUGH_DATA;
1985 }
1986
Jianing Weicb0652e2014-03-12 18:29:36 -07001987 if (frame == NULL) {
1988 ALOGE("%s: argument cannot be NULL", __FUNCTION__);
1989 return BAD_VALUE;
1990 }
1991
1992 CaptureResult &result = *(mResultQueue.begin());
1993 frame->mResultExtras = result.mResultExtras;
1994 frame->mMetadata.acquire(result.mMetadata);
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001995 frame->mPhysicalMetadatas = std::move(result.mPhysicalMetadatas);
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001996 mResultQueue.erase(mResultQueue.begin());
1997
1998 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001999}
2000
2001status_t Camera3Device::triggerAutofocus(uint32_t id) {
2002 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002003 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002004
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07002005 ALOGV("%s: Triggering autofocus, id %d", __FUNCTION__, id);
2006 // Mix-in this trigger into the next request and only the next request.
2007 RequestTrigger trigger[] = {
2008 {
2009 ANDROID_CONTROL_AF_TRIGGER,
2010 ANDROID_CONTROL_AF_TRIGGER_START
2011 },
2012 {
2013 ANDROID_CONTROL_AF_TRIGGER_ID,
2014 static_cast<int32_t>(id)
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07002015 }
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07002016 };
2017
2018 return mRequestThread->queueTrigger(trigger,
2019 sizeof(trigger)/sizeof(trigger[0]));
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002020}
2021
2022status_t Camera3Device::triggerCancelAutofocus(uint32_t id) {
2023 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002024 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002025
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07002026 ALOGV("%s: Triggering cancel autofocus, id %d", __FUNCTION__, id);
2027 // Mix-in this trigger into the next request and only the next request.
2028 RequestTrigger trigger[] = {
2029 {
2030 ANDROID_CONTROL_AF_TRIGGER,
2031 ANDROID_CONTROL_AF_TRIGGER_CANCEL
2032 },
2033 {
2034 ANDROID_CONTROL_AF_TRIGGER_ID,
2035 static_cast<int32_t>(id)
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07002036 }
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07002037 };
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002038
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07002039 return mRequestThread->queueTrigger(trigger,
2040 sizeof(trigger)/sizeof(trigger[0]));
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002041}
2042
2043status_t Camera3Device::triggerPrecaptureMetering(uint32_t id) {
2044 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002045 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002046
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07002047 ALOGV("%s: Triggering precapture metering, id %d", __FUNCTION__, id);
2048 // Mix-in this trigger into the next request and only the next request.
2049 RequestTrigger trigger[] = {
2050 {
2051 ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
2052 ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_START
2053 },
2054 {
2055 ANDROID_CONTROL_AE_PRECAPTURE_ID,
2056 static_cast<int32_t>(id)
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07002057 }
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07002058 };
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002059
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07002060 return mRequestThread->queueTrigger(trigger,
2061 sizeof(trigger)/sizeof(trigger[0]));
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002062}
2063
Jianing Weicb0652e2014-03-12 18:29:36 -07002064status_t Camera3Device::flush(int64_t *frameNumber) {
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07002065 ATRACE_CALL();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002066 ALOGV("%s: Camera %s: Flushing all requests", __FUNCTION__, mId.string());
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002067 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07002068
Zhijun He7ef20392014-04-21 16:04:17 -07002069 {
2070 Mutex::Autolock l(mLock);
Emilian Peeved2ebe42018-09-25 16:59:09 +01002071
2072 // b/116514106 "disconnect()" can get called twice for the same device. The
2073 // camera device will not be initialized during the second run.
2074 if (mStatus == STATUS_UNINITIALIZED) {
2075 return OK;
2076 }
2077
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07002078 mRequestThread->clear(/*out*/frameNumber);
Shuzhen Wang316781a2020-08-18 18:11:01 -07002079
2080 // Stop session and stream counter
2081 mSessionStatsBuilder.stopCounter();
Zhijun He7ef20392014-04-21 16:04:17 -07002082 }
2083
Emilian Peev08dd2452017-04-06 16:55:14 +01002084 return mRequestThread->flush();
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07002085}
2086
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002087status_t Camera3Device::prepare(int streamId) {
Ruben Brunkc78ac262015-08-13 17:58:46 -07002088 return prepare(camera3::Camera3StreamInterface::ALLOCATE_PIPELINE_MAX, streamId);
2089}
2090
2091status_t Camera3Device::prepare(int maxCount, int streamId) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002092 ATRACE_CALL();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002093 ALOGV("%s: Camera %s: Preparing stream %d", __FUNCTION__, mId.string(), streamId);
Eino-Ville Talvala261394e2015-05-13 14:28:38 -07002094 Mutex::Autolock il(mInterfaceLock);
2095 Mutex::Autolock l(mLock);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002096
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002097 sp<Camera3StreamInterface> stream = mOutputStreams.get(streamId);
2098 if (stream == nullptr) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002099 CLOGE("Stream %d does not exist", streamId);
2100 return BAD_VALUE;
2101 }
2102
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002103 if (stream->isUnpreparable() || stream->hasOutstandingBuffers() ) {
Eino-Ville Talvala261394e2015-05-13 14:28:38 -07002104 CLOGE("Stream %d has already been a request target", streamId);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002105 return BAD_VALUE;
2106 }
2107
2108 if (mRequestThread->isStreamPending(stream)) {
Eino-Ville Talvala261394e2015-05-13 14:28:38 -07002109 CLOGE("Stream %d is already a target in a pending request", streamId);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002110 return BAD_VALUE;
2111 }
2112
Ruben Brunkc78ac262015-08-13 17:58:46 -07002113 return mPreparerThread->prepare(maxCount, stream);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002114}
2115
Eino-Ville Talvalab25e3c82015-07-15 16:04:27 -07002116status_t Camera3Device::tearDown(int streamId) {
2117 ATRACE_CALL();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002118 ALOGV("%s: Camera %s: Tearing down stream %d", __FUNCTION__, mId.string(), streamId);
Eino-Ville Talvalab25e3c82015-07-15 16:04:27 -07002119 Mutex::Autolock il(mInterfaceLock);
2120 Mutex::Autolock l(mLock);
2121
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002122 sp<Camera3StreamInterface> stream = mOutputStreams.get(streamId);
2123 if (stream == nullptr) {
Eino-Ville Talvalab25e3c82015-07-15 16:04:27 -07002124 CLOGE("Stream %d does not exist", streamId);
2125 return BAD_VALUE;
2126 }
2127
Eino-Ville Talvalab25e3c82015-07-15 16:04:27 -07002128 if (stream->hasOutstandingBuffers() || mRequestThread->isStreamPending(stream)) {
2129 CLOGE("Stream %d is a target of a in-progress request", streamId);
2130 return BAD_VALUE;
2131 }
2132
2133 return stream->tearDown();
2134}
2135
Shuzhen Wangb0fdc1e2016-03-20 23:21:39 -07002136status_t Camera3Device::addBufferListenerForStream(int streamId,
2137 wp<Camera3StreamBufferListener> listener) {
2138 ATRACE_CALL();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002139 ALOGV("%s: Camera %s: Adding buffer listener for stream %d", __FUNCTION__, mId.string(), streamId);
Shuzhen Wangb0fdc1e2016-03-20 23:21:39 -07002140 Mutex::Autolock il(mInterfaceLock);
2141 Mutex::Autolock l(mLock);
2142
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002143 sp<Camera3StreamInterface> stream = mOutputStreams.get(streamId);
2144 if (stream == nullptr) {
Shuzhen Wangb0fdc1e2016-03-20 23:21:39 -07002145 CLOGE("Stream %d does not exist", streamId);
2146 return BAD_VALUE;
2147 }
Shuzhen Wangb0fdc1e2016-03-20 23:21:39 -07002148 stream->addBufferListener(listener);
2149
2150 return OK;
2151}
2152
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002153/**
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002154 * Methods called by subclasses
2155 */
2156
2157void Camera3Device::notifyStatus(bool idle) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07002158 ATRACE_CALL();
Shuzhen Wang316781a2020-08-18 18:11:01 -07002159 std::vector<int> streamIds;
2160 std::vector<hardware::CameraStreamStats> streamStats;
2161
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002162 {
2163 // Need mLock to safely update state and synchronize to current
2164 // state of methods in flight.
2165 Mutex::Autolock l(mLock);
2166 // We can get various system-idle notices from the status tracker
2167 // while starting up. Only care about them if we've actually sent
2168 // in some requests recently.
2169 if (mStatus != STATUS_ACTIVE && mStatus != STATUS_CONFIGURED) {
2170 return;
2171 }
Eino-Ville Talvala002001b2018-01-23 16:53:50 -08002172 ALOGV("%s: Camera %s: Now %s, pauseState: %s", __FUNCTION__, mId.string(),
2173 idle ? "idle" : "active", mPauseStateNotify ? "true" : "false");
Ruben Brunk183f0562015-08-12 12:55:02 -07002174 internalUpdateStatusLocked(idle ? STATUS_CONFIGURED : STATUS_ACTIVE);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002175
2176 // Skip notifying listener if we're doing some user-transparent
2177 // state changes
2178 if (mPauseStateNotify) return;
Shuzhen Wang316781a2020-08-18 18:11:01 -07002179
2180 // Populate stream statistics in case of Idle
2181 if (idle) {
2182 for (size_t i = 0; i < mOutputStreams.size(); i++) {
2183 auto stream = mOutputStreams[i];
2184 if (stream.get() == nullptr) continue;
2185 streamIds.push_back(stream->getId());
2186 Camera3Stream* camera3Stream = Camera3Stream::cast(stream->asHalStream());
2187 int64_t usage = 0LL;
2188 if (camera3Stream != nullptr) {
2189 usage = camera3Stream->getUsage();
2190 }
2191 streamStats.emplace_back(stream->getWidth(), stream->getHeight(),
2192 stream->getFormat(), stream->getDataSpace(), usage,
2193 stream->getMaxHalBuffers(),
2194 stream->getMaxTotalBuffers() - stream->getMaxHalBuffers());
2195 }
2196 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002197 }
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07002198
2199 sp<NotificationListener> listener;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002200 {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002201 std::lock_guard<std::mutex> l(mOutputLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07002202 listener = mListener.promote();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002203 }
Eino-Ville Talvala178e8232021-04-16 18:41:39 -07002204 status_t res = OK;
2205 if (listener != nullptr) {
2206 if (idle) {
2207 // Get session stats from the builder, and notify the listener.
2208 int64_t requestCount, resultErrorCount;
2209 bool deviceError;
2210 std::map<int, StreamStats> streamStatsMap;
2211 mSessionStatsBuilder.buildAndReset(&requestCount, &resultErrorCount,
2212 &deviceError, &streamStatsMap);
2213 for (size_t i = 0; i < streamIds.size(); i++) {
2214 int streamId = streamIds[i];
2215 auto stats = streamStatsMap.find(streamId);
2216 if (stats != streamStatsMap.end()) {
2217 streamStats[i].mRequestCount = stats->second.mRequestedFrameCount;
2218 streamStats[i].mErrorCount = stats->second.mDroppedFrameCount;
2219 streamStats[i].mStartLatencyMs = stats->second.mStartLatencyMs;
2220 streamStats[i].mHistogramType =
2221 hardware::CameraStreamStats::HISTOGRAM_TYPE_CAPTURE_LATENCY;
2222 streamStats[i].mHistogramBins.assign(
2223 stats->second.mCaptureLatencyBins.begin(),
2224 stats->second.mCaptureLatencyBins.end());
2225 streamStats[i].mHistogramCounts.assign(
2226 stats->second.mCaptureLatencyHistogram.begin(),
2227 stats->second.mCaptureLatencyHistogram.end());
2228 }
Shuzhen Wang316781a2020-08-18 18:11:01 -07002229 }
Eino-Ville Talvala178e8232021-04-16 18:41:39 -07002230 listener->notifyIdle(requestCount, resultErrorCount, deviceError, streamStats);
2231 } else {
2232 res = listener->notifyActive();
Shuzhen Wang316781a2020-08-18 18:11:01 -07002233 }
Eino-Ville Talvala178e8232021-04-16 18:41:39 -07002234 }
2235 if (res != OK) {
2236 SET_ERR("Camera access permission lost mid-operation: %s (%d)",
2237 strerror(-res), res);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002238 }
2239}
2240
Shuzhen Wang758c2152017-01-10 18:26:18 -08002241status_t Camera3Device::setConsumerSurfaces(int streamId,
Emilian Peev40ead602017-09-26 15:46:36 +01002242 const std::vector<sp<Surface>>& consumers, std::vector<int> *surfaceIds) {
Zhijun He5d677d12016-05-29 16:52:39 -07002243 ATRACE_CALL();
Shuzhen Wang758c2152017-01-10 18:26:18 -08002244 ALOGV("%s: Camera %s: set consumer surface for stream %d",
2245 __FUNCTION__, mId.string(), streamId);
Emilian Peev40ead602017-09-26 15:46:36 +01002246
2247 if (surfaceIds == nullptr) {
2248 return BAD_VALUE;
2249 }
2250
Zhijun He5d677d12016-05-29 16:52:39 -07002251 Mutex::Autolock il(mInterfaceLock);
2252 Mutex::Autolock l(mLock);
2253
Shuzhen Wang758c2152017-01-10 18:26:18 -08002254 if (consumers.size() == 0) {
2255 CLOGE("No consumer is passed!");
Zhijun He5d677d12016-05-29 16:52:39 -07002256 return BAD_VALUE;
2257 }
2258
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002259 sp<Camera3OutputStreamInterface> stream = mOutputStreams.get(streamId);
2260 if (stream == nullptr) {
Zhijun He5d677d12016-05-29 16:52:39 -07002261 CLOGE("Stream %d is unknown", streamId);
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002262 return BAD_VALUE;
Zhijun He5d677d12016-05-29 16:52:39 -07002263 }
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002264
2265 // isConsumerConfigurationDeferred will be off after setConsumers
2266 bool isDeferred = stream->isConsumerConfigurationDeferred();
Shuzhen Wang758c2152017-01-10 18:26:18 -08002267 status_t res = stream->setConsumers(consumers);
Zhijun He5d677d12016-05-29 16:52:39 -07002268 if (res != OK) {
2269 CLOGE("Stream %d set consumer failed (error %d %s) ", streamId, res, strerror(-res));
2270 return res;
2271 }
2272
Emilian Peev40ead602017-09-26 15:46:36 +01002273 for (auto &consumer : consumers) {
2274 int id = stream->getSurfaceId(consumer);
2275 if (id < 0) {
2276 CLOGE("Invalid surface id!");
2277 return BAD_VALUE;
2278 }
2279 surfaceIds->push_back(id);
2280 }
2281
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002282 if (isDeferred) {
Shuzhen Wang0129d522016-10-30 22:43:41 -07002283 if (!stream->isConfiguring()) {
2284 CLOGE("Stream %d was already fully configured.", streamId);
2285 return INVALID_OPERATION;
2286 }
Zhijun He5d677d12016-05-29 16:52:39 -07002287
Shuzhen Wang0129d522016-10-30 22:43:41 -07002288 res = stream->finishConfiguration();
2289 if (res != OK) {
Shuzhen Wang210ba5c2018-07-25 16:47:40 -07002290 // If finishConfiguration fails due to abandoned surface, do not set
2291 // device to error state.
2292 bool isSurfaceAbandoned =
2293 (res == NO_INIT || res == DEAD_OBJECT) && stream->isAbandoned();
2294 if (!isSurfaceAbandoned) {
2295 SET_ERR_L("Can't finish configuring output stream %d: %s (%d)",
2296 stream->getId(), strerror(-res), res);
2297 }
Shuzhen Wang0129d522016-10-30 22:43:41 -07002298 return res;
2299 }
Zhijun He5d677d12016-05-29 16:52:39 -07002300 }
2301
2302 return OK;
2303}
2304
Emilian Peev40ead602017-09-26 15:46:36 +01002305status_t Camera3Device::updateStream(int streamId, const std::vector<sp<Surface>> &newSurfaces,
2306 const std::vector<OutputStreamInfo> &outputInfo,
2307 const std::vector<size_t> &removedSurfaceIds, KeyedVector<sp<Surface>, size_t> *outputMap) {
2308 Mutex::Autolock il(mInterfaceLock);
2309 Mutex::Autolock l(mLock);
2310
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002311 sp<Camera3OutputStreamInterface> stream = mOutputStreams.get(streamId);
2312 if (stream == nullptr) {
Emilian Peev40ead602017-09-26 15:46:36 +01002313 CLOGE("Stream %d is unknown", streamId);
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002314 return BAD_VALUE;
Emilian Peev40ead602017-09-26 15:46:36 +01002315 }
2316
2317 for (const auto &it : removedSurfaceIds) {
2318 if (mRequestThread->isOutputSurfacePending(streamId, it)) {
2319 CLOGE("Shared surface still part of a pending request!");
2320 return -EBUSY;
2321 }
2322 }
2323
Emilian Peev40ead602017-09-26 15:46:36 +01002324 status_t res = stream->updateStream(newSurfaces, outputInfo, removedSurfaceIds, outputMap);
2325 if (res != OK) {
2326 CLOGE("Stream %d failed to update stream (error %d %s) ",
2327 streamId, res, strerror(-res));
2328 if (res == UNKNOWN_ERROR) {
2329 SET_ERR_L("%s: Stream update failed to revert to previous output configuration!",
2330 __FUNCTION__);
2331 }
2332 return res;
2333 }
2334
2335 return res;
2336}
2337
Chien-Yu Chena936ac22017-10-23 15:59:49 -07002338status_t Camera3Device::dropStreamBuffers(bool dropping, int streamId) {
2339 Mutex::Autolock il(mInterfaceLock);
2340 Mutex::Autolock l(mLock);
2341
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002342 sp<Camera3OutputStreamInterface> stream = mOutputStreams.get(streamId);
2343 if (stream == nullptr) {
Chien-Yu Chena936ac22017-10-23 15:59:49 -07002344 ALOGE("%s: Stream %d is not found.", __FUNCTION__, streamId);
2345 return BAD_VALUE;
2346 }
Shuzhen Wang316781a2020-08-18 18:11:01 -07002347
2348 if (dropping) {
2349 mSessionStatsBuilder.stopCounter(streamId);
2350 } else {
2351 mSessionStatsBuilder.startCounter(streamId);
2352 }
Chien-Yu Chena936ac22017-10-23 15:59:49 -07002353 return stream->dropBuffers(dropping);
2354}
2355
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002356/**
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002357 * Camera3Device private methods
2358 */
2359
2360sp<Camera3Device::CaptureRequest> Camera3Device::createCaptureRequest(
Emilian Peevaebbe412018-01-15 13:53:24 +00002361 const PhysicalCameraSettingsList &request, const SurfaceMap &surfaceMap) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002362 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002363
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08002364 sp<CaptureRequest> newRequest = new CaptureRequest();
Emilian Peevaebbe412018-01-15 13:53:24 +00002365 newRequest->mSettingsList = request;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002366
2367 camera_metadata_entry_t inputStreams =
Emilian Peevaebbe412018-01-15 13:53:24 +00002368 newRequest->mSettingsList.begin()->metadata.find(ANDROID_REQUEST_INPUT_STREAMS);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002369 if (inputStreams.count > 0) {
2370 if (mInputStream == NULL ||
Zhijun Hed1d64672013-09-06 15:00:01 -07002371 mInputStream->getId() != inputStreams.data.i32[0]) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002372 CLOGE("Request references unknown input stream %d",
2373 inputStreams.data.u8[0]);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002374 return NULL;
2375 }
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002376
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002377 if (mInputStream->isConfiguring()) {
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002378 SET_ERR_L("%s: input stream %d is not configured!",
2379 __FUNCTION__, mInputStream->getId());
2380 return NULL;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002381 }
Shuzhen Wangb3a0fb52018-09-13 17:24:08 -07002382 // Check if stream prepare is blocking requests.
2383 if (mInputStream->isBlockedByPrepare()) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002384 CLOGE("Request references an input stream that's being prepared!");
2385 return NULL;
2386 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002387
2388 newRequest->mInputStream = mInputStream;
Emilian Peevaebbe412018-01-15 13:53:24 +00002389 newRequest->mSettingsList.begin()->metadata.erase(ANDROID_REQUEST_INPUT_STREAMS);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002390 }
2391
2392 camera_metadata_entry_t streams =
Emilian Peevaebbe412018-01-15 13:53:24 +00002393 newRequest->mSettingsList.begin()->metadata.find(ANDROID_REQUEST_OUTPUT_STREAMS);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002394 if (streams.count == 0) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002395 CLOGE("Zero output streams specified!");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002396 return NULL;
2397 }
2398
2399 for (size_t i = 0; i < streams.count; i++) {
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002400 sp<Camera3OutputStreamInterface> stream = mOutputStreams.get(streams.data.i32[i]);
2401 if (stream == nullptr) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002402 CLOGE("Request references unknown stream %d",
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002403 streams.data.i32[i]);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002404 return NULL;
2405 }
Zhijun He5d677d12016-05-29 16:52:39 -07002406 // It is illegal to include a deferred consumer output stream into a request
Shuzhen Wang0129d522016-10-30 22:43:41 -07002407 auto iter = surfaceMap.find(streams.data.i32[i]);
2408 if (iter != surfaceMap.end()) {
2409 const std::vector<size_t>& surfaces = iter->second;
2410 for (const auto& surface : surfaces) {
2411 if (stream->isConsumerConfigurationDeferred(surface)) {
2412 CLOGE("Stream %d surface %zu hasn't finished configuration yet "
2413 "due to deferred consumer", stream->getId(), surface);
2414 return NULL;
2415 }
2416 }
Yin-Chia Yeh0b287572018-10-15 12:38:13 -07002417 newRequest->mOutputSurfaces[streams.data.i32[i]] = surfaces;
Zhijun He5d677d12016-05-29 16:52:39 -07002418 }
2419
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002420 if (stream->isConfiguring()) {
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002421 SET_ERR_L("%s: stream %d is not configured!", __FUNCTION__, stream->getId());
2422 return NULL;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002423 }
Shuzhen Wangb3a0fb52018-09-13 17:24:08 -07002424 // Check if stream prepare is blocking requests.
2425 if (stream->isBlockedByPrepare()) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002426 CLOGE("Request references an output stream that's being prepared!");
2427 return NULL;
2428 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002429
2430 newRequest->mOutputStreams.push(stream);
2431 }
Emilian Peevaebbe412018-01-15 13:53:24 +00002432 newRequest->mSettingsList.begin()->metadata.erase(ANDROID_REQUEST_OUTPUT_STREAMS);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07002433 newRequest->mBatchSize = 1;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002434
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08002435 auto rotateAndCropEntry =
2436 newRequest->mSettingsList.begin()->metadata.find(ANDROID_SCALER_ROTATE_AND_CROP);
2437 if (rotateAndCropEntry.count > 0 &&
2438 rotateAndCropEntry.data.u8[0] == ANDROID_SCALER_ROTATE_AND_CROP_AUTO) {
2439 newRequest->mRotateAndCropAuto = true;
2440 } else {
2441 newRequest->mRotateAndCropAuto = false;
2442 }
2443
Shuzhen Wangd1d051a2020-08-20 15:42:23 -07002444 auto zoomRatioEntry =
2445 newRequest->mSettingsList.begin()->metadata.find(ANDROID_CONTROL_ZOOM_RATIO);
2446 if (zoomRatioEntry.count > 0 &&
2447 zoomRatioEntry.data.f[0] == 1.0f) {
2448 newRequest->mZoomRatioIs1x = true;
2449 } else {
2450 newRequest->mZoomRatioIs1x = false;
2451 }
2452
Eino-Ville Talvala305cec62020-11-12 14:18:17 -08002453 if (mSupportCameraMute) {
2454 auto testPatternModeEntry =
2455 newRequest->mSettingsList.begin()->metadata.find(ANDROID_SENSOR_TEST_PATTERN_MODE);
2456 newRequest->mOriginalTestPatternMode = testPatternModeEntry.count > 0 ?
2457 testPatternModeEntry.data.i32[0] :
2458 ANDROID_SENSOR_TEST_PATTERN_MODE_OFF;
2459
2460 auto testPatternDataEntry =
2461 newRequest->mSettingsList.begin()->metadata.find(ANDROID_SENSOR_TEST_PATTERN_DATA);
2462 if (testPatternDataEntry.count > 0) {
2463 memcpy(newRequest->mOriginalTestPatternData, testPatternModeEntry.data.i32,
2464 sizeof(newRequest->mOriginalTestPatternData));
2465 } else {
2466 newRequest->mOriginalTestPatternData[0] = 0;
2467 newRequest->mOriginalTestPatternData[1] = 0;
2468 newRequest->mOriginalTestPatternData[2] = 0;
2469 newRequest->mOriginalTestPatternData[3] = 0;
2470 }
2471 }
2472
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002473 return newRequest;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002474}
2475
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002476void Camera3Device::cancelStreamsConfigurationLocked() {
2477 int res = OK;
2478 if (mInputStream != NULL && mInputStream->isConfiguring()) {
2479 res = mInputStream->cancelConfiguration();
2480 if (res != OK) {
2481 CLOGE("Can't cancel configuring input stream %d: %s (%d)",
2482 mInputStream->getId(), strerror(-res), res);
2483 }
2484 }
2485
2486 for (size_t i = 0; i < mOutputStreams.size(); i++) {
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002487 sp<Camera3OutputStreamInterface> outputStream = mOutputStreams[i];
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002488 if (outputStream->isConfiguring()) {
2489 res = outputStream->cancelConfiguration();
2490 if (res != OK) {
2491 CLOGE("Can't cancel configuring output stream %d: %s (%d)",
2492 outputStream->getId(), strerror(-res), res);
2493 }
2494 }
2495 }
2496
2497 // Return state to that at start of call, so that future configures
2498 // properly clean things up
2499 internalUpdateStatusLocked(STATUS_UNCONFIGURED);
2500 mNeedConfig = true;
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002501
2502 res = mPreparerThread->resume();
2503 if (res != OK) {
2504 ALOGE("%s: Camera %s: Preparer thread failed to resume!", __FUNCTION__, mId.string());
2505 }
2506}
2507
Emilian Peev0d0191e2020-04-21 17:01:18 -07002508bool Camera3Device::checkAbandonedStreamsLocked() {
2509 if ((mInputStream.get() != nullptr) && (mInputStream->isAbandoned())) {
2510 return true;
2511 }
2512
2513 for (size_t i = 0; i < mOutputStreams.size(); i++) {
2514 auto stream = mOutputStreams[i];
2515 if ((stream.get() != nullptr) && (stream->isAbandoned())) {
2516 return true;
2517 }
2518 }
2519
2520 return false;
2521}
2522
Emilian Peev3bead5f2020-05-28 17:29:08 -07002523bool Camera3Device::reconfigureCamera(const CameraMetadata& sessionParams, int clientStatusId) {
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002524 ATRACE_CALL();
2525 bool ret = false;
2526
Shuzhen Wang316781a2020-08-18 18:11:01 -07002527 nsecs_t startTime = systemTime();
2528
Jayant Chowdhary646c31b2020-01-30 13:09:59 -08002529 Mutex::Autolock il(mInterfaceLock);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002530 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
2531
2532 Mutex::Autolock l(mLock);
Emilian Peev0d0191e2020-04-21 17:01:18 -07002533 if (checkAbandonedStreamsLocked()) {
2534 ALOGW("%s: Abandoned stream detected, session parameters can't be applied correctly!",
2535 __FUNCTION__);
2536 return true;
2537 }
2538
Emilian Peev3bead5f2020-05-28 17:29:08 -07002539 status_t rc = NO_ERROR;
2540 bool markClientActive = false;
2541 if (mStatus == STATUS_ACTIVE) {
2542 markClientActive = true;
2543 mPauseStateNotify = true;
2544 mStatusTracker->markComponentIdle(clientStatusId, Fence::NO_FENCE);
2545
2546 rc = internalPauseAndWaitLocked(maxExpectedDuration);
2547 }
2548
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002549 if (rc == NO_ERROR) {
2550 mNeedConfig = true;
2551 rc = configureStreamsLocked(mOperatingMode, sessionParams, /*notifyRequestThread*/ false);
2552 if (rc == NO_ERROR) {
2553 ret = true;
2554 mPauseStateNotify = false;
2555 //Moving to active state while holding 'mLock' is important.
2556 //There could be pending calls to 'create-/deleteStream' which
2557 //will trigger another stream configuration while the already
2558 //present streams end up with outstanding buffers that will
2559 //not get drained.
2560 internalUpdateStatusLocked(STATUS_ACTIVE);
Shuzhen Wang210ba5c2018-07-25 16:47:40 -07002561 } else if (rc == DEAD_OBJECT) {
2562 // DEAD_OBJECT can be returned if either the consumer surface is
2563 // abandoned, or the HAL has died.
2564 // - If the HAL has died, configureStreamsLocked call will set
2565 // device to error state,
2566 // - If surface is abandoned, we should not set device to error
2567 // state.
2568 ALOGE("Failed to re-configure camera due to abandoned surface");
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002569 } else {
Shuzhen Wang210ba5c2018-07-25 16:47:40 -07002570 SET_ERR_L("Failed to re-configure camera: %d", rc);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002571 }
2572 } else {
2573 ALOGE("%s: Failed to pause streaming: %d", __FUNCTION__, rc);
2574 }
2575
Shuzhen Wang316781a2020-08-18 18:11:01 -07002576 CameraServiceProxyWrapper::logStreamConfigured(mId, mOperatingMode, true /*internalReconfig*/,
2577 ns2ms(systemTime() - startTime));
2578
Emilian Peev3bead5f2020-05-28 17:29:08 -07002579 if (markClientActive) {
2580 mStatusTracker->markComponentActive(clientStatusId);
2581 }
2582
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002583 return ret;
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002584}
2585
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01002586status_t Camera3Device::configureStreamsLocked(int operatingMode,
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002587 const CameraMetadata& sessionParams, bool notifyRequestThread) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002588 ATRACE_CALL();
2589 status_t res;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002590
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002591 if (mStatus != STATUS_UNCONFIGURED && mStatus != STATUS_CONFIGURED) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002592 CLOGE("Not idle");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002593 return INVALID_OPERATION;
2594 }
2595
Eino-Ville Talvalae7091aa2017-03-07 15:23:06 -08002596 if (operatingMode < 0) {
2597 CLOGE("Invalid operating mode: %d", operatingMode);
2598 return BAD_VALUE;
2599 }
2600
2601 bool isConstrainedHighSpeed =
2602 static_cast<int>(StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE) ==
2603 operatingMode;
2604
2605 if (mOperatingMode != operatingMode) {
2606 mNeedConfig = true;
2607 mIsConstrainedHighSpeedConfiguration = isConstrainedHighSpeed;
2608 mOperatingMode = operatingMode;
2609 }
2610
Shuzhen Wang0cf01cb2019-09-05 13:33:06 -07002611 // In case called from configureStreams, abort queued input buffers not belonging to
2612 // any pending requests.
2613 if (mInputStream != NULL && notifyRequestThread) {
2614 while (true) {
Emilian Peevf4816702020-04-03 15:44:51 -07002615 camera_stream_buffer_t inputBuffer;
Shuzhen Wang83bff122020-11-20 15:51:39 -08002616 camera3::Size inputBufferSize;
Shuzhen Wang0cf01cb2019-09-05 13:33:06 -07002617 status_t res = mInputStream->getInputBuffer(&inputBuffer,
Shuzhen Wang83bff122020-11-20 15:51:39 -08002618 &inputBufferSize, /*respectHalLimit*/ false);
Shuzhen Wang0cf01cb2019-09-05 13:33:06 -07002619 if (res != OK) {
2620 // Exhausted acquiring all input buffers.
2621 break;
2622 }
2623
Emilian Peevf4816702020-04-03 15:44:51 -07002624 inputBuffer.status = CAMERA_BUFFER_STATUS_ERROR;
Shuzhen Wang0cf01cb2019-09-05 13:33:06 -07002625 res = mInputStream->returnInputBuffer(inputBuffer);
2626 if (res != OK) {
2627 ALOGE("%s: %d: couldn't return input buffer while clearing input queue: "
2628 "%s (%d)", __FUNCTION__, __LINE__, strerror(-res), res);
2629 }
2630 }
2631 }
2632
Eino-Ville Talvalaea26c772013-06-11 16:04:06 -07002633 if (!mNeedConfig) {
2634 ALOGV("%s: Skipping config, no stream changes", __FUNCTION__);
2635 return OK;
2636 }
2637
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002638 // Workaround for device HALv3.2 or older spec bug - zero streams requires
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -04002639 // adding a fake stream instead.
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002640 // TODO: Bug: 17321404 for fixing the HAL spec and removing this workaround.
2641 if (mOutputStreams.size() == 0) {
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -04002642 addFakeStreamLocked();
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002643 } else {
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -04002644 tryRemoveFakeStreamLocked();
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002645 }
2646
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002647 // Start configuring the streams
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002648 ALOGV("%s: Camera %s: Starting stream configuration", __FUNCTION__, mId.string());
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002649
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002650 mPreparerThread->pause();
2651
Emilian Peevf4816702020-04-03 15:44:51 -07002652 camera_stream_configuration config;
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -08002653 config.operation_mode = mOperatingMode;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002654 config.num_streams = (mInputStream != NULL) + mOutputStreams.size();
Shuzhen Wang83bff122020-11-20 15:51:39 -08002655 config.input_is_multi_resolution = false;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002656
Emilian Peevf4816702020-04-03 15:44:51 -07002657 Vector<camera3::camera_stream_t*> streams;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002658 streams.setCapacity(config.num_streams);
Emilian Peev192ee832018-01-31 14:46:47 +00002659 std::vector<uint32_t> bufferSizes(config.num_streams, 0);
Yin-Chia Yehfb6e55b2018-01-25 10:50:26 -08002660
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002661
2662 if (mInputStream != NULL) {
Emilian Peevf4816702020-04-03 15:44:51 -07002663 camera3::camera_stream_t *inputStream;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002664 inputStream = mInputStream->startConfiguration();
2665 if (inputStream == NULL) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002666 CLOGE("Can't start input stream configuration");
2667 cancelStreamsConfigurationLocked();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002668 return INVALID_OPERATION;
2669 }
2670 streams.add(inputStream);
Shuzhen Wang83bff122020-11-20 15:51:39 -08002671
2672 config.input_is_multi_resolution = mIsInputStreamMultiResolution;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002673 }
2674
Shuzhen Wang99080502021-03-07 21:08:20 -08002675 mGroupIdPhysicalCameraMap.clear();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002676 for (size_t i = 0; i < mOutputStreams.size(); i++) {
Igor Murashkin2fba5842013-04-22 14:03:54 -07002677
2678 // Don't configure bidi streams twice, nor add them twice to the list
2679 if (mOutputStreams[i].get() ==
2680 static_cast<Camera3StreamInterface*>(mInputStream.get())) {
2681
2682 config.num_streams--;
2683 continue;
2684 }
2685
Emilian Peevf4816702020-04-03 15:44:51 -07002686 camera3::camera_stream_t *outputStream;
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002687 outputStream = mOutputStreams[i]->startConfiguration();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002688 if (outputStream == NULL) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002689 CLOGE("Can't start output stream configuration");
2690 cancelStreamsConfigurationLocked();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002691 return INVALID_OPERATION;
2692 }
2693 streams.add(outputStream);
Yin-Chia Yehfb6e55b2018-01-25 10:50:26 -08002694
Shuzhen Wangb7ab1e42019-02-20 15:42:23 -08002695 if (outputStream->format == HAL_PIXEL_FORMAT_BLOB) {
Emilian Peev192ee832018-01-31 14:46:47 +00002696 size_t k = i + ((mInputStream != nullptr) ? 1 : 0); // Input stream if present should
2697 // always occupy the initial entry.
Shuzhen Wangb7ab1e42019-02-20 15:42:23 -08002698 if (outputStream->data_space == HAL_DATASPACE_V0_JFIF) {
2699 bufferSizes[k] = static_cast<uint32_t>(
2700 getJpegBufferSize(outputStream->width, outputStream->height));
2701 } else if (outputStream->data_space ==
2702 static_cast<android_dataspace>(HAL_DATASPACE_JPEG_APP_SEGMENTS)) {
2703 bufferSizes[k] = outputStream->width * outputStream->height;
2704 } else {
2705 ALOGW("%s: Blob dataSpace %d not supported",
2706 __FUNCTION__, outputStream->data_space);
2707 }
Yin-Chia Yehfb6e55b2018-01-25 10:50:26 -08002708 }
Shuzhen Wang99080502021-03-07 21:08:20 -08002709
2710 if (mOutputStreams[i]->isMultiResolution()) {
2711 int32_t streamGroupId = mOutputStreams[i]->getHalStreamGroupId();
2712 const String8& physicalCameraId = mOutputStreams[i]->getPhysicalCameraId();
2713 mGroupIdPhysicalCameraMap[streamGroupId].insert(physicalCameraId);
2714 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002715 }
2716
2717 config.streams = streams.editArray();
2718
2719 // Do the HAL configuration; will potentially touch stream
Shuzhen Wang92653952019-05-07 15:11:43 -07002720 // max_buffers, usage, and priv fields, as well as data_space and format
2721 // fields for IMPLEMENTATION_DEFINED formats.
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002722
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01002723 const camera_metadata_t *sessionBuffer = sessionParams.getAndLock();
Emilian Peev192ee832018-01-31 14:46:47 +00002724 res = mInterface->configureStreams(sessionBuffer, &config, bufferSizes);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01002725 sessionParams.unlock(sessionBuffer);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002726
Eino-Ville Talvala17543512014-08-06 14:32:02 -07002727 if (res == BAD_VALUE) {
2728 // HAL rejected this set of streams as unsupported, clean up config
2729 // attempt and return to unconfigured state
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002730 CLOGE("Set of requested inputs/outputs not supported by HAL");
2731 cancelStreamsConfigurationLocked();
Eino-Ville Talvala17543512014-08-06 14:32:02 -07002732 return BAD_VALUE;
2733 } else if (res != OK) {
2734 // Some other kind of error from configure_streams - this is not
2735 // expected
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002736 SET_ERR_L("Unable to configure streams with HAL: %s (%d)",
2737 strerror(-res), res);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002738 return res;
2739 }
2740
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002741 // Finish all stream configuration immediately.
2742 // TODO: Try to relax this later back to lazy completion, which should be
2743 // faster
2744
Igor Murashkin073f8572013-05-02 14:59:28 -07002745 if (mInputStream != NULL && mInputStream->isConfiguring()) {
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002746 bool streamReConfigured = false;
2747 res = mInputStream->finishConfiguration(&streamReConfigured);
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002748 if (res != OK) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002749 CLOGE("Can't finish configuring input stream %d: %s (%d)",
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002750 mInputStream->getId(), strerror(-res), res);
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002751 cancelStreamsConfigurationLocked();
Shuzhen Wang210ba5c2018-07-25 16:47:40 -07002752 if ((res == NO_INIT || res == DEAD_OBJECT) && mInputStream->isAbandoned()) {
2753 return DEAD_OBJECT;
2754 }
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002755 return BAD_VALUE;
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002756 }
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002757 if (streamReConfigured) {
2758 mInterface->onStreamReConfigured(mInputStream->getId());
2759 }
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002760 }
2761
2762 for (size_t i = 0; i < mOutputStreams.size(); i++) {
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002763 sp<Camera3OutputStreamInterface> outputStream = mOutputStreams[i];
Zhijun He5d677d12016-05-29 16:52:39 -07002764 if (outputStream->isConfiguring() && !outputStream->isConsumerConfigurationDeferred()) {
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002765 bool streamReConfigured = false;
2766 res = outputStream->finishConfiguration(&streamReConfigured);
Igor Murashkin073f8572013-05-02 14:59:28 -07002767 if (res != OK) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002768 CLOGE("Can't finish configuring output stream %d: %s (%d)",
Igor Murashkin073f8572013-05-02 14:59:28 -07002769 outputStream->getId(), strerror(-res), res);
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002770 cancelStreamsConfigurationLocked();
Shuzhen Wang210ba5c2018-07-25 16:47:40 -07002771 if ((res == NO_INIT || res == DEAD_OBJECT) && outputStream->isAbandoned()) {
2772 return DEAD_OBJECT;
2773 }
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002774 return BAD_VALUE;
Igor Murashkin073f8572013-05-02 14:59:28 -07002775 }
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002776 if (streamReConfigured) {
2777 mInterface->onStreamReConfigured(outputStream->getId());
2778 }
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002779 }
2780 }
2781
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002782 // Request thread needs to know to avoid using repeat-last-settings protocol
2783 // across configure_streams() calls
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002784 if (notifyRequestThread) {
Shuzhen Wang99080502021-03-07 21:08:20 -08002785 mRequestThread->configurationComplete(mIsConstrainedHighSpeedConfiguration,
2786 sessionParams, mGroupIdPhysicalCameraMap);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002787 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002788
Zhijun He90f7c372016-08-16 16:19:43 -07002789 char value[PROPERTY_VALUE_MAX];
2790 property_get("camera.fifo.disable", value, "0");
2791 int32_t disableFifo = atoi(value);
2792 if (disableFifo != 1) {
2793 // Boost priority of request thread to SCHED_FIFO.
2794 pid_t requestThreadTid = mRequestThread->getTid();
2795 res = requestPriority(getpid(), requestThreadTid,
Mikhail Naganov83f04272017-02-07 10:45:09 -08002796 kRequestThreadPriority, /*isForApp*/ false, /*asynchronous*/ false);
Zhijun He90f7c372016-08-16 16:19:43 -07002797 if (res != OK) {
2798 ALOGW("Can't set realtime priority for request processing thread: %s (%d)",
2799 strerror(-res), res);
2800 } else {
2801 ALOGD("Set real time priority for request queue thread (tid %d)", requestThreadTid);
2802 }
Eino-Ville Talvalaf99498e2015-09-25 16:52:55 -07002803 }
2804
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002805 // Update device state
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01002806 const camera_metadata_t *newSessionParams = sessionParams.getAndLock();
2807 const camera_metadata_t *currentSessionParams = mSessionParams.getAndLock();
2808 bool updateSessionParams = (newSessionParams != currentSessionParams) ? true : false;
2809 sessionParams.unlock(newSessionParams);
2810 mSessionParams.unlock(currentSessionParams);
2811 if (updateSessionParams) {
2812 mSessionParams = sessionParams;
2813 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002814
Eino-Ville Talvalaea26c772013-06-11 16:04:06 -07002815 mNeedConfig = false;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002816
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -04002817 internalUpdateStatusLocked((mFakeStreamId == NO_STREAM) ?
Ruben Brunk183f0562015-08-12 12:55:02 -07002818 STATUS_CONFIGURED : STATUS_UNCONFIGURED);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002819
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002820 ALOGV("%s: Camera %s: Stream configuration complete", __FUNCTION__, mId.string());
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002821
Zhijun He0a210512014-07-24 13:45:15 -07002822 // tear down the deleted streams after configure streams.
2823 mDeletedStreams.clear();
2824
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002825 auto rc = mPreparerThread->resume();
2826 if (rc != OK) {
2827 SET_ERR_L("%s: Camera %s: Preparer thread failed to resume!", __FUNCTION__, mId.string());
2828 return rc;
2829 }
2830
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -04002831 if (mFakeStreamId == NO_STREAM) {
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07002832 mRequestBufferSM.onStreamsConfigured();
2833 }
2834
Cliff Wuc2ad9c82021-04-21 00:58:58 +08002835 // Since the streams configuration of the injection camera is based on the internal camera, we
2836 // must wait until the internal camera configure streams before calling injectCamera() to
2837 // configure the injection streams.
2838 if (mInjectionMethods->isInjecting()) {
2839 ALOGV("%s: Injection camera %s: Start to configure streams.",
2840 __FUNCTION__, mInjectionMethods->getInjectedCamId().string());
2841 res = mInjectionMethods->injectCamera(config, bufferSizes);
2842 if (res != OK) {
2843 ALOGE("Can't finish inject camera process!");
2844 return res;
2845 }
2846 }
2847
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002848 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002849}
2850
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -04002851status_t Camera3Device::addFakeStreamLocked() {
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002852 ATRACE_CALL();
2853 status_t res;
2854
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -04002855 if (mFakeStreamId != NO_STREAM) {
2856 // Should never be adding a second fake stream when one is already
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002857 // active
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -04002858 SET_ERR_L("%s: Camera %s: A fake stream already exists!",
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002859 __FUNCTION__, mId.string());
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002860 return INVALID_OPERATION;
2861 }
2862
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -04002863 ALOGV("%s: Camera %s: Adding a fake stream", __FUNCTION__, mId.string());
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002864
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -04002865 sp<Camera3OutputStreamInterface> fakeStream =
2866 new Camera3FakeStream(mNextStreamId);
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002867
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -04002868 res = mOutputStreams.add(mNextStreamId, fakeStream);
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002869 if (res < 0) {
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -04002870 SET_ERR_L("Can't add fake stream to set: %s (%d)", strerror(-res), res);
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002871 return res;
2872 }
2873
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -04002874 mFakeStreamId = mNextStreamId;
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002875 mNextStreamId++;
2876
2877 return OK;
2878}
2879
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -04002880status_t Camera3Device::tryRemoveFakeStreamLocked() {
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002881 ATRACE_CALL();
2882 status_t res;
2883
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -04002884 if (mFakeStreamId == NO_STREAM) return OK;
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002885 if (mOutputStreams.size() == 1) return OK;
2886
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -04002887 ALOGV("%s: Camera %s: Removing the fake stream", __FUNCTION__, mId.string());
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002888
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -04002889 // Ok, have a fake stream and there's at least one other output stream,
2890 // so remove the fake
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002891
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -04002892 sp<Camera3StreamInterface> deletedStream = mOutputStreams.get(mFakeStreamId);
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002893 if (deletedStream == nullptr) {
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -04002894 SET_ERR_L("Fake stream %d does not appear to exist", mFakeStreamId);
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002895 return INVALID_OPERATION;
2896 }
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -04002897 mOutputStreams.remove(mFakeStreamId);
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002898
2899 // Free up the stream endpoint so that it can be used by some other stream
2900 res = deletedStream->disconnect();
2901 if (res != OK) {
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -04002902 SET_ERR_L("Can't disconnect deleted fake stream %d", mFakeStreamId);
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002903 // fall through since we want to still list the stream as deleted.
2904 }
2905 mDeletedStreams.add(deletedStream);
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -04002906 mFakeStreamId = NO_STREAM;
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002907
2908 return res;
2909}
2910
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002911void Camera3Device::setErrorState(const char *fmt, ...) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07002912 ATRACE_CALL();
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002913 Mutex::Autolock l(mLock);
2914 va_list args;
2915 va_start(args, fmt);
2916
2917 setErrorStateLockedV(fmt, args);
2918
2919 va_end(args);
2920}
2921
2922void Camera3Device::setErrorStateV(const char *fmt, va_list args) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07002923 ATRACE_CALL();
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002924 Mutex::Autolock l(mLock);
2925 setErrorStateLockedV(fmt, args);
2926}
2927
2928void Camera3Device::setErrorStateLocked(const char *fmt, ...) {
2929 va_list args;
2930 va_start(args, fmt);
2931
2932 setErrorStateLockedV(fmt, args);
2933
2934 va_end(args);
2935}
2936
2937void Camera3Device::setErrorStateLockedV(const char *fmt, va_list args) {
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002938 // Print out all error messages to log
2939 String8 errorCause = String8::formatV(fmt, args);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002940 ALOGE("Camera %s: %s", mId.string(), errorCause.string());
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002941
2942 // But only do error state transition steps for the first error
Zhijun Heb05eeae2013-06-06 13:51:22 -07002943 if (mStatus == STATUS_ERROR || mStatus == STATUS_UNINITIALIZED) return;
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002944
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002945 mErrorCause = errorCause;
2946
Yin-Chia Yeh3d145ae2017-07-27 12:47:03 -07002947 if (mRequestThread != nullptr) {
2948 mRequestThread->setPaused(true);
2949 }
Ruben Brunk183f0562015-08-12 12:55:02 -07002950 internalUpdateStatusLocked(STATUS_ERROR);
Eino-Ville Talvala17543512014-08-06 14:32:02 -07002951
2952 // Notify upstream about a device error
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07002953 sp<NotificationListener> listener = mListener.promote();
2954 if (listener != NULL) {
2955 listener->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
Eino-Ville Talvala17543512014-08-06 14:32:02 -07002956 CaptureResultExtras());
Shuzhen Wang316781a2020-08-18 18:11:01 -07002957 mSessionStatsBuilder.onDeviceError();
Eino-Ville Talvala17543512014-08-06 14:32:02 -07002958 }
2959
2960 // Save stack trace. View by dumping it later.
2961 CameraTraces::saveTrace();
2962 // TODO: consider adding errorCause and client pid/procname
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002963}
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002964
2965/**
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002966 * In-flight request management
2967 */
2968
Jianing Weicb0652e2014-03-12 18:29:36 -07002969status_t Camera3Device::registerInFlight(uint32_t frameNumber,
Chien-Yu Chend196d612015-06-22 19:49:01 -07002970 int32_t numBuffers, CaptureResultExtras resultExtras, bool hasInput,
Shuzhen Wang5c22c152017-12-31 17:12:25 -08002971 bool hasAppCallback, nsecs_t maxExpectedDuration,
Shuzhen Wang99080502021-03-07 21:08:20 -08002972 const std::set<std::set<String8>>& physicalCameraIds,
2973 bool isStillCapture, bool isZslCapture, bool rotateAndCropAuto,
2974 const std::set<std::string>& cameraIdsWithZoom,
Shuzhen Wang316781a2020-08-18 18:11:01 -07002975 const SurfaceMap& outputSurfaces, nsecs_t requestTimeNs) {
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002976 ATRACE_CALL();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002977 std::lock_guard<std::mutex> l(mInFlightLock);
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002978
2979 ssize_t res;
Chien-Yu Chend196d612015-06-22 19:49:01 -07002980 res = mInFlightMap.add(frameNumber, InFlightRequest(numBuffers, resultExtras, hasInput,
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07002981 hasAppCallback, maxExpectedDuration, physicalCameraIds, isStillCapture, isZslCapture,
Shuzhen Wang316781a2020-08-18 18:11:01 -07002982 rotateAndCropAuto, cameraIdsWithZoom, requestTimeNs, outputSurfaces));
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002983 if (res < 0) return res;
2984
Eino-Ville Talvala24b366e2016-07-21 12:53:07 -07002985 if (mInFlightMap.size() == 1) {
Emilian Peev26d975d2018-07-05 14:52:57 +01002986 // Hold a separate dedicated tracker lock to prevent race with disconnect and also
2987 // avoid a deadlock during reprocess requests.
2988 Mutex::Autolock l(mTrackerLock);
Yin-Chia Yeh38dfde52017-06-27 17:13:33 -07002989 if (mStatusTracker != nullptr) {
2990 mStatusTracker->markComponentActive(mInFlightStatusId);
2991 }
Eino-Ville Talvala24b366e2016-07-21 12:53:07 -07002992 }
2993
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07002994 mExpectedInflightDuration += maxExpectedDuration;
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002995 return OK;
2996}
2997
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002998void Camera3Device::onInflightEntryRemovedLocked(nsecs_t duration) {
Shuzhen Wangcadb3302016-11-04 14:17:56 -07002999 // Indicate idle inFlightMap to the status tracker
3000 if (mInFlightMap.size() == 0) {
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07003001 mRequestBufferSM.onInflightMapEmpty();
Emilian Peev26d975d2018-07-05 14:52:57 +01003002 // Hold a separate dedicated tracker lock to prevent race with disconnect and also
3003 // avoid a deadlock during reprocess requests.
3004 Mutex::Autolock l(mTrackerLock);
Yin-Chia Yeh38dfde52017-06-27 17:13:33 -07003005 if (mStatusTracker != nullptr) {
3006 mStatusTracker->markComponentIdle(mInFlightStatusId, Fence::NO_FENCE);
3007 }
Shuzhen Wangcadb3302016-11-04 14:17:56 -07003008 }
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07003009 mExpectedInflightDuration -= duration;
Shuzhen Wangcadb3302016-11-04 14:17:56 -07003010}
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08003011
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003012void Camera3Device::checkInflightMapLengthLocked() {
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -04003013 // Validation check - if we have too many in-flight frames with long total inflight duration,
Yin-Chia Yeh99fd0972019-06-27 14:22:44 -07003014 // something has likely gone wrong. This might still be legit only if application send in
3015 // a long burst of long exposure requests.
3016 if (mExpectedInflightDuration > kMinWarnInflightDuration) {
3017 if (!mIsConstrainedHighSpeedConfiguration && mInFlightMap.size() > kInFlightWarnLimit) {
3018 CLOGW("In-flight list too large: %zu, total inflight duration %" PRIu64,
3019 mInFlightMap.size(), mExpectedInflightDuration);
3020 } else if (mIsConstrainedHighSpeedConfiguration && mInFlightMap.size() >
3021 kInFlightWarnLimitHighSpeed) {
3022 CLOGW("In-flight list too large for high speed configuration: %zu,"
3023 "total inflight duration %" PRIu64,
3024 mInFlightMap.size(), mExpectedInflightDuration);
3025 }
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08003026 }
3027}
3028
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003029void Camera3Device::onInflightMapFlushedLocked() {
3030 mExpectedInflightDuration = 0;
3031}
3032
3033void Camera3Device::removeInFlightMapEntryLocked(int idx) {
Jayant Chowdharyd4776262020-06-23 23:45:57 -07003034 ATRACE_HFR_CALL();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003035 nsecs_t duration = mInFlightMap.valueAt(idx).maxExpectedDuration;
3036 mInFlightMap.removeItemsAt(idx, 1);
3037
3038 onInflightEntryRemovedLocked(duration);
3039}
3040
3041
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07003042void Camera3Device::flushInflightRequests() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003043 ATRACE_CALL();
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07003044 sp<NotificationListener> listener;
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07003045 {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003046 std::lock_guard<std::mutex> l(mOutputLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07003047 listener = mListener.promote();
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07003048 }
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08003049
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003050 FlushInflightReqStates states {
3051 mId, mInFlightLock, mInFlightMap, mUseHalBufManager,
Shuzhen Wang316781a2020-08-18 18:11:01 -07003052 listener, *this, *mInterface, *this, mSessionStatsBuilder};
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07003053
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003054 camera3::flushInflightRequests(states);
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003055}
3056
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07003057CameraMetadata Camera3Device::getLatestRequestLocked() {
Igor Murashkin1e479c02013-09-06 16:55:14 -07003058 ALOGV("%s", __FUNCTION__);
3059
Igor Murashkin1e479c02013-09-06 16:55:14 -07003060 CameraMetadata retVal;
3061
3062 if (mRequestThread != NULL) {
3063 retVal = mRequestThread->getLatestRequest();
3064 }
3065
Igor Murashkin1e479c02013-09-06 16:55:14 -07003066 return retVal;
3067}
3068
Eino-Ville Talvala4d453832016-07-15 11:56:53 -07003069void Camera3Device::monitorMetadata(TagMonitor::eventSource source,
Shuzhen Wangc2cba122018-05-17 18:10:24 -07003070 int64_t frameNumber, nsecs_t timestamp, const CameraMetadata& metadata,
3071 const std::unordered_map<std::string, CameraMetadata>& physicalMetadata) {
3072
3073 mTagMonitor.monitorMetadata(source, frameNumber, timestamp, metadata,
3074 physicalMetadata);
Eino-Ville Talvala4d453832016-07-15 11:56:53 -07003075}
3076
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08003077/**
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003078 * HalInterface inner class methods
3079 */
3080
Yifan Hongf79b5542017-04-11 14:44:25 -07003081Camera3Device::HalInterface::HalInterface(
3082 sp<ICameraDeviceSession> &session,
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003083 std::shared_ptr<RequestMetadataQueue> queue,
Yin-Chia Yehb978c382019-10-30 00:22:37 -07003084 bool useHalBufManager, bool supportOfflineProcessing) :
Yifan Hongf79b5542017-04-11 14:44:25 -07003085 mHidlSession(session),
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003086 mRequestMetadataQueue(queue),
Emilian Peev4ec17882019-01-24 17:16:58 -08003087 mUseHalBufManager(useHalBufManager),
Yin-Chia Yehb978c382019-10-30 00:22:37 -07003088 mIsReconfigurationQuerySupported(true),
3089 mSupportOfflineProcessing(supportOfflineProcessing) {
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08003090 // Check with hardware service manager if we can downcast these interfaces
3091 // Somewhat expensive, so cache the results at startup
Shuzhen Wang83bff122020-11-20 15:51:39 -08003092 auto castResult_3_7 = device::V3_7::ICameraDeviceSession::castFrom(mHidlSession);
3093 if (castResult_3_7.isOk()) {
3094 mHidlSession_3_7 = castResult_3_7;
3095 }
Yin-Chia Yehb978c382019-10-30 00:22:37 -07003096 auto castResult_3_6 = device::V3_6::ICameraDeviceSession::castFrom(mHidlSession);
3097 if (castResult_3_6.isOk()) {
3098 mHidlSession_3_6 = castResult_3_6;
3099 }
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07003100 auto castResult_3_5 = device::V3_5::ICameraDeviceSession::castFrom(mHidlSession);
3101 if (castResult_3_5.isOk()) {
3102 mHidlSession_3_5 = castResult_3_5;
3103 }
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08003104 auto castResult_3_4 = device::V3_4::ICameraDeviceSession::castFrom(mHidlSession);
3105 if (castResult_3_4.isOk()) {
3106 mHidlSession_3_4 = castResult_3_4;
3107 }
3108 auto castResult_3_3 = device::V3_3::ICameraDeviceSession::castFrom(mHidlSession);
3109 if (castResult_3_3.isOk()) {
3110 mHidlSession_3_3 = castResult_3_3;
3111 }
3112}
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003113
Yin-Chia Yehb978c382019-10-30 00:22:37 -07003114Camera3Device::HalInterface::HalInterface() :
3115 mUseHalBufManager(false),
3116 mSupportOfflineProcessing(false) {}
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003117
3118Camera3Device::HalInterface::HalInterface(const HalInterface& other) :
Yifan Hongf79b5542017-04-11 14:44:25 -07003119 mHidlSession(other.mHidlSession),
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003120 mRequestMetadataQueue(other.mRequestMetadataQueue),
Yin-Chia Yehb978c382019-10-30 00:22:37 -07003121 mUseHalBufManager(other.mUseHalBufManager),
3122 mSupportOfflineProcessing(other.mSupportOfflineProcessing) {}
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003123
3124bool Camera3Device::HalInterface::valid() {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003125 return (mHidlSession != nullptr);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003126}
3127
3128void Camera3Device::HalInterface::clear() {
Shuzhen Wang83bff122020-11-20 15:51:39 -08003129 mHidlSession_3_7.clear();
Yin-Chia Yehb978c382019-10-30 00:22:37 -07003130 mHidlSession_3_6.clear();
Emilian Peev644a3e12018-11-23 13:52:39 +00003131 mHidlSession_3_5.clear();
Emilian Peev9e740b02018-01-30 18:28:03 +00003132 mHidlSession_3_4.clear();
3133 mHidlSession_3_3.clear();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003134 mHidlSession.clear();
3135}
3136
3137status_t Camera3Device::HalInterface::constructDefaultRequestSettings(
Emilian Peevf4816702020-04-03 15:44:51 -07003138 camera_request_template_t templateId,
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003139 /*out*/ camera_metadata_t **requestTemplate) {
3140 ATRACE_NAME("CameraHal::constructDefaultRequestSettings");
3141 if (!valid()) return INVALID_OPERATION;
3142 status_t res = OK;
3143
Emilian Peev31abd0a2017-05-11 18:37:46 +01003144 common::V1_0::Status status;
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08003145
3146 auto requestCallback = [&status, &requestTemplate]
Emilian Peev31abd0a2017-05-11 18:37:46 +01003147 (common::V1_0::Status s, const device::V3_2::CameraMetadata& request) {
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08003148 status = s;
3149 if (status == common::V1_0::Status::OK) {
3150 const camera_metadata *r =
3151 reinterpret_cast<const camera_metadata_t*>(request.data());
3152 size_t expectedSize = request.size();
3153 int ret = validate_camera_metadata_structure(r, &expectedSize);
3154 if (ret == OK || ret == CAMERA_METADATA_VALIDATION_SHIFTED) {
3155 *requestTemplate = clone_camera_metadata(r);
3156 if (*requestTemplate == nullptr) {
3157 ALOGE("%s: Unable to clone camera metadata received from HAL",
3158 __FUNCTION__);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003159 status = common::V1_0::Status::INTERNAL_ERROR;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003160 }
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08003161 } else {
3162 ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
3163 status = common::V1_0::Status::INTERNAL_ERROR;
Emilian Peev31abd0a2017-05-11 18:37:46 +01003164 }
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08003165 }
3166 };
3167 hardware::Return<void> err;
Eino-Ville Talvala96441462018-02-06 11:41:55 -08003168 RequestTemplate id;
3169 switch (templateId) {
Emilian Peevf4816702020-04-03 15:44:51 -07003170 case CAMERA_TEMPLATE_PREVIEW:
Eino-Ville Talvala96441462018-02-06 11:41:55 -08003171 id = RequestTemplate::PREVIEW;
3172 break;
Emilian Peevf4816702020-04-03 15:44:51 -07003173 case CAMERA_TEMPLATE_STILL_CAPTURE:
Eino-Ville Talvala96441462018-02-06 11:41:55 -08003174 id = RequestTemplate::STILL_CAPTURE;
3175 break;
Emilian Peevf4816702020-04-03 15:44:51 -07003176 case CAMERA_TEMPLATE_VIDEO_RECORD:
Eino-Ville Talvala96441462018-02-06 11:41:55 -08003177 id = RequestTemplate::VIDEO_RECORD;
3178 break;
Emilian Peevf4816702020-04-03 15:44:51 -07003179 case CAMERA_TEMPLATE_VIDEO_SNAPSHOT:
Eino-Ville Talvala96441462018-02-06 11:41:55 -08003180 id = RequestTemplate::VIDEO_SNAPSHOT;
3181 break;
Emilian Peevf4816702020-04-03 15:44:51 -07003182 case CAMERA_TEMPLATE_ZERO_SHUTTER_LAG:
Eino-Ville Talvala96441462018-02-06 11:41:55 -08003183 id = RequestTemplate::ZERO_SHUTTER_LAG;
3184 break;
Emilian Peevf4816702020-04-03 15:44:51 -07003185 case CAMERA_TEMPLATE_MANUAL:
Eino-Ville Talvala96441462018-02-06 11:41:55 -08003186 id = RequestTemplate::MANUAL;
3187 break;
3188 default:
3189 // Unknown template ID, or this HAL is too old to support it
3190 return BAD_VALUE;
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08003191 }
Eino-Ville Talvala96441462018-02-06 11:41:55 -08003192 err = mHidlSession->constructDefaultRequestSettings(id, requestCallback);
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08003193
Emilian Peev31abd0a2017-05-11 18:37:46 +01003194 if (!err.isOk()) {
3195 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3196 res = DEAD_OBJECT;
3197 } else {
3198 res = CameraProviderManager::mapToStatusT(status);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003199 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003200
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003201 return res;
3202}
3203
Emilian Peev4ec17882019-01-24 17:16:58 -08003204bool Camera3Device::HalInterface::isReconfigurationRequired(CameraMetadata& oldSessionParams,
3205 CameraMetadata& newSessionParams) {
3206 // We do reconfiguration by default;
3207 bool ret = true;
3208 if ((mHidlSession_3_5 != nullptr) && mIsReconfigurationQuerySupported) {
3209 android::hardware::hidl_vec<uint8_t> oldParams, newParams;
3210 camera_metadata_t* oldSessioMeta = const_cast<camera_metadata_t*>(
3211 oldSessionParams.getAndLock());
3212 camera_metadata_t* newSessioMeta = const_cast<camera_metadata_t*>(
3213 newSessionParams.getAndLock());
3214 oldParams.setToExternal(reinterpret_cast<uint8_t*>(oldSessioMeta),
3215 get_camera_metadata_size(oldSessioMeta));
3216 newParams.setToExternal(reinterpret_cast<uint8_t*>(newSessioMeta),
3217 get_camera_metadata_size(newSessioMeta));
3218 hardware::camera::common::V1_0::Status callStatus;
3219 bool required;
3220 auto hidlCb = [&callStatus, &required] (hardware::camera::common::V1_0::Status s,
3221 bool requiredFlag) {
3222 callStatus = s;
3223 required = requiredFlag;
3224 };
3225 auto err = mHidlSession_3_5->isReconfigurationRequired(oldParams, newParams, hidlCb);
3226 oldSessionParams.unlock(oldSessioMeta);
3227 newSessionParams.unlock(newSessioMeta);
3228 if (err.isOk()) {
3229 switch (callStatus) {
3230 case hardware::camera::common::V1_0::Status::OK:
3231 ret = required;
3232 break;
3233 case hardware::camera::common::V1_0::Status::METHOD_NOT_SUPPORTED:
3234 mIsReconfigurationQuerySupported = false;
3235 ret = true;
3236 break;
3237 default:
3238 ALOGV("%s: Reconfiguration query failed: %d", __FUNCTION__, callStatus);
3239 ret = true;
3240 }
3241 } else {
3242 ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, err.description().c_str());
3243 ret = true;
3244 }
3245 }
3246
3247 return ret;
3248}
3249
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01003250status_t Camera3Device::HalInterface::configureStreams(const camera_metadata_t *sessionParams,
Emilian Peevf4816702020-04-03 15:44:51 -07003251 camera_stream_configuration *config, const std::vector<uint32_t>& bufferSizes) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003252 ATRACE_NAME("CameraHal::configureStreams");
3253 if (!valid()) return INVALID_OPERATION;
3254 status_t res = OK;
3255
Shuzhen Wang83bff122020-11-20 15:51:39 -08003256 if (config->input_is_multi_resolution && mHidlSession_3_7 == nullptr) {
3257 ALOGE("%s: Camera device doesn't support multi-resolution input stream", __FUNCTION__);
3258 return BAD_VALUE;
3259 }
3260
Emilian Peev31abd0a2017-05-11 18:37:46 +01003261 // Convert stream config to HIDL
3262 std::set<int> activeStreams;
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003263 device::V3_2::StreamConfiguration requestedConfiguration3_2;
3264 device::V3_4::StreamConfiguration requestedConfiguration3_4;
Shuzhen Wang83bff122020-11-20 15:51:39 -08003265 device::V3_7::StreamConfiguration requestedConfiguration3_7;
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003266 requestedConfiguration3_2.streams.resize(config->num_streams);
3267 requestedConfiguration3_4.streams.resize(config->num_streams);
Shuzhen Wang83bff122020-11-20 15:51:39 -08003268 requestedConfiguration3_7.streams.resize(config->num_streams);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003269 for (size_t i = 0; i < config->num_streams; i++) {
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003270 device::V3_2::Stream &dst3_2 = requestedConfiguration3_2.streams[i];
3271 device::V3_4::Stream &dst3_4 = requestedConfiguration3_4.streams[i];
Shuzhen Wang83bff122020-11-20 15:51:39 -08003272 device::V3_7::Stream &dst3_7 = requestedConfiguration3_7.streams[i];
Emilian Peevf4816702020-04-03 15:44:51 -07003273 camera3::camera_stream_t *src = config->streams[i];
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003274
Emilian Peev31abd0a2017-05-11 18:37:46 +01003275 Camera3Stream* cam3stream = Camera3Stream::cast(src);
3276 cam3stream->setBufferFreedListener(this);
3277 int streamId = cam3stream->getId();
3278 StreamType streamType;
3279 switch (src->stream_type) {
Emilian Peevf4816702020-04-03 15:44:51 -07003280 case CAMERA_STREAM_OUTPUT:
Emilian Peev31abd0a2017-05-11 18:37:46 +01003281 streamType = StreamType::OUTPUT;
3282 break;
Emilian Peevf4816702020-04-03 15:44:51 -07003283 case CAMERA_STREAM_INPUT:
Emilian Peev31abd0a2017-05-11 18:37:46 +01003284 streamType = StreamType::INPUT;
3285 break;
3286 default:
3287 ALOGE("%s: Stream %d: Unsupported stream type %d",
3288 __FUNCTION__, streamId, config->streams[i]->stream_type);
3289 return BAD_VALUE;
3290 }
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003291 dst3_2.id = streamId;
3292 dst3_2.streamType = streamType;
3293 dst3_2.width = src->width;
3294 dst3_2.height = src->height;
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003295 dst3_2.usage = mapToConsumerUsage(cam3stream->getUsage());
Emilian Peevf4816702020-04-03 15:44:51 -07003296 dst3_2.rotation = mapToStreamRotation((camera_stream_rotation_t) src->rotation);
Shuzhen Wang92653952019-05-07 15:11:43 -07003297 // For HidlSession version 3.5 or newer, the format and dataSpace sent
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08003298 // to HAL are original, not the overridden ones.
Shuzhen Wang92653952019-05-07 15:11:43 -07003299 if (mHidlSession_3_5 != nullptr) {
3300 dst3_2.format = mapToPixelFormat(cam3stream->isFormatOverridden() ?
3301 cam3stream->getOriginalFormat() : src->format);
3302 dst3_2.dataSpace = mapToHidlDataspace(cam3stream->isDataSpaceOverridden() ?
3303 cam3stream->getOriginalDataSpace() : src->data_space);
3304 } else {
3305 dst3_2.format = mapToPixelFormat(src->format);
3306 dst3_2.dataSpace = mapToHidlDataspace(src->data_space);
3307 }
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003308 dst3_4.v3_2 = dst3_2;
Emilian Peev192ee832018-01-31 14:46:47 +00003309 dst3_4.bufferSize = bufferSizes[i];
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003310 if (src->physical_camera_id != nullptr) {
3311 dst3_4.physicalCameraId = src->physical_camera_id;
3312 }
Shuzhen Wang83bff122020-11-20 15:51:39 -08003313 dst3_7.v3_4 = dst3_4;
3314 dst3_7.groupId = cam3stream->getHalStreamGroupId();
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08003315 dst3_7.sensorPixelModesUsed.resize(src->sensor_pixel_modes_used.size());
3316 size_t j = 0;
3317 for (int mode : src->sensor_pixel_modes_used) {
3318 dst3_7.sensorPixelModesUsed[j++] =
3319 static_cast<CameraMetadataEnumAndroidSensorPixelMode>(mode);
3320 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003321 activeStreams.insert(streamId);
3322 // Create Buffer ID map if necessary
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003323 mBufferRecords.tryCreateBufferCache(streamId);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003324 }
3325 // remove BufferIdMap for deleted streams
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003326 mBufferRecords.removeInactiveBufferCaches(activeStreams);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003327
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003328 StreamConfigurationMode operationMode;
Emilian Peev31abd0a2017-05-11 18:37:46 +01003329 res = mapToStreamConfigurationMode(
Emilian Peevf4816702020-04-03 15:44:51 -07003330 (camera_stream_configuration_mode_t) config->operation_mode,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003331 /*out*/ &operationMode);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003332 if (res != OK) {
3333 return res;
3334 }
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003335 requestedConfiguration3_2.operationMode = operationMode;
3336 requestedConfiguration3_4.operationMode = operationMode;
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08003337 requestedConfiguration3_7.operationMode = operationMode;
3338 size_t sessionParamSize = get_camera_metadata_size(sessionParams);
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003339 requestedConfiguration3_4.sessionParams.setToExternal(
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01003340 reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams)),
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08003341 sessionParamSize);
Shuzhen Wang83bff122020-11-20 15:51:39 -08003342 requestedConfiguration3_7.operationMode = operationMode;
3343 requestedConfiguration3_7.sessionParams.setToExternal(
3344 reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams)),
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -08003345 sessionParamSize);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01003346
Emilian Peev31abd0a2017-05-11 18:37:46 +01003347 // Invoke configureStreams
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003348 device::V3_3::HalStreamConfiguration finalConfiguration;
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003349 device::V3_4::HalStreamConfiguration finalConfiguration3_4;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003350 device::V3_6::HalStreamConfiguration finalConfiguration3_6;
Emilian Peev31abd0a2017-05-11 18:37:46 +01003351 common::V1_0::Status status;
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003352
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003353 auto configStream34Cb = [&status, &finalConfiguration3_4]
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003354 (common::V1_0::Status s, const device::V3_4::HalStreamConfiguration& halConfiguration) {
3355 finalConfiguration3_4 = halConfiguration;
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01003356 status = s;
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003357 };
3358
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003359 auto configStream36Cb = [&status, &finalConfiguration3_6]
3360 (common::V1_0::Status s, const device::V3_6::HalStreamConfiguration& halConfiguration) {
3361 finalConfiguration3_6 = halConfiguration;
3362 status = s;
3363 };
3364
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003365 auto postprocConfigStream34 = [&finalConfiguration, &finalConfiguration3_4]
3366 (hardware::Return<void>& err) -> status_t {
3367 if (!err.isOk()) {
3368 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3369 return DEAD_OBJECT;
3370 }
3371 finalConfiguration.streams.resize(finalConfiguration3_4.streams.size());
3372 for (size_t i = 0; i < finalConfiguration3_4.streams.size(); i++) {
3373 finalConfiguration.streams[i] = finalConfiguration3_4.streams[i].v3_3;
3374 }
3375 return OK;
3376 };
3377
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003378 auto postprocConfigStream36 = [&finalConfiguration, &finalConfiguration3_6]
3379 (hardware::Return<void>& err) -> status_t {
3380 if (!err.isOk()) {
3381 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3382 return DEAD_OBJECT;
3383 }
3384 finalConfiguration.streams.resize(finalConfiguration3_6.streams.size());
3385 for (size_t i = 0; i < finalConfiguration3_6.streams.size(); i++) {
3386 finalConfiguration.streams[i] = finalConfiguration3_6.streams[i].v3_4.v3_3;
3387 }
3388 return OK;
3389 };
3390
Shuzhen Wang92653952019-05-07 15:11:43 -07003391 // See which version of HAL we have
Shuzhen Wang83bff122020-11-20 15:51:39 -08003392 if (mHidlSession_3_7 != nullptr) {
3393 ALOGV("%s: v3.7 device found", __FUNCTION__);
3394 requestedConfiguration3_7.streamConfigCounter = mNextStreamConfigCounter++;
3395 requestedConfiguration3_7.multiResolutionInputImage = config->input_is_multi_resolution;
3396 auto err = mHidlSession_3_7->configureStreams_3_7(
3397 requestedConfiguration3_7, configStream36Cb);
3398 res = postprocConfigStream36(err);
3399 if (res != OK) {
3400 return res;
3401 }
3402 } else if (mHidlSession_3_6 != nullptr) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003403 ALOGV("%s: v3.6 device found", __FUNCTION__);
3404 device::V3_5::StreamConfiguration requestedConfiguration3_5;
3405 requestedConfiguration3_5.v3_4 = requestedConfiguration3_4;
3406 requestedConfiguration3_5.streamConfigCounter = mNextStreamConfigCounter++;
3407 auto err = mHidlSession_3_6->configureStreams_3_6(
3408 requestedConfiguration3_5, configStream36Cb);
3409 res = postprocConfigStream36(err);
3410 if (res != OK) {
3411 return res;
3412 }
3413 } else if (mHidlSession_3_5 != nullptr) {
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003414 ALOGV("%s: v3.5 device found", __FUNCTION__);
3415 device::V3_5::StreamConfiguration requestedConfiguration3_5;
3416 requestedConfiguration3_5.v3_4 = requestedConfiguration3_4;
3417 requestedConfiguration3_5.streamConfigCounter = mNextStreamConfigCounter++;
3418 auto err = mHidlSession_3_5->configureStreams_3_5(
3419 requestedConfiguration3_5, configStream34Cb);
3420 res = postprocConfigStream34(err);
3421 if (res != OK) {
3422 return res;
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01003423 }
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003424 } else if (mHidlSession_3_4 != nullptr) {
3425 // We do; use v3.4 for the call
3426 ALOGV("%s: v3.4 device found", __FUNCTION__);
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003427 auto err = mHidlSession_3_4->configureStreams_3_4(
3428 requestedConfiguration3_4, configStream34Cb);
3429 res = postprocConfigStream34(err);
3430 if (res != OK) {
3431 return res;
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003432 }
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08003433 } else if (mHidlSession_3_3 != nullptr) {
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003434 // We do; use v3.3 for the call
3435 ALOGV("%s: v3.3 device found", __FUNCTION__);
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08003436 auto err = mHidlSession_3_3->configureStreams_3_3(requestedConfiguration3_2,
Emilian Peev31abd0a2017-05-11 18:37:46 +01003437 [&status, &finalConfiguration]
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003438 (common::V1_0::Status s, const device::V3_3::HalStreamConfiguration& halConfiguration) {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003439 finalConfiguration = halConfiguration;
3440 status = s;
3441 });
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003442 if (!err.isOk()) {
3443 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3444 return DEAD_OBJECT;
3445 }
3446 } else {
3447 // We don't; use v3.2 call and construct a v3.3 HalStreamConfiguration
3448 ALOGV("%s: v3.2 device found", __FUNCTION__);
3449 HalStreamConfiguration finalConfiguration_3_2;
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003450 auto err = mHidlSession->configureStreams(requestedConfiguration3_2,
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003451 [&status, &finalConfiguration_3_2]
3452 (common::V1_0::Status s, const HalStreamConfiguration& halConfiguration) {
3453 finalConfiguration_3_2 = halConfiguration;
3454 status = s;
3455 });
3456 if (!err.isOk()) {
3457 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3458 return DEAD_OBJECT;
3459 }
3460 finalConfiguration.streams.resize(finalConfiguration_3_2.streams.size());
3461 for (size_t i = 0; i < finalConfiguration_3_2.streams.size(); i++) {
3462 finalConfiguration.streams[i].v3_2 = finalConfiguration_3_2.streams[i];
3463 finalConfiguration.streams[i].overrideDataSpace =
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003464 requestedConfiguration3_2.streams[i].dataSpace;
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003465 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003466 }
3467
3468 if (status != common::V1_0::Status::OK ) {
3469 return CameraProviderManager::mapToStatusT(status);
3470 }
3471
3472 // And convert output stream configuration from HIDL
3473
3474 for (size_t i = 0; i < config->num_streams; i++) {
Emilian Peevf4816702020-04-03 15:44:51 -07003475 camera3::camera_stream_t *dst = config->streams[i];
Emilian Peev31abd0a2017-05-11 18:37:46 +01003476 int streamId = Camera3Stream::cast(dst)->getId();
3477
3478 // Start scan at i, with the assumption that the stream order matches
3479 size_t realIdx = i;
3480 bool found = false;
Eino-Ville Talvala370875f2019-04-12 12:40:27 -07003481 size_t halStreamCount = finalConfiguration.streams.size();
3482 for (size_t idx = 0; idx < halStreamCount; idx++) {
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003483 if (finalConfiguration.streams[realIdx].v3_2.id == streamId) {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003484 found = true;
3485 break;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003486 }
Eino-Ville Talvala370875f2019-04-12 12:40:27 -07003487 realIdx = (realIdx >= halStreamCount - 1) ? 0 : realIdx + 1;
Emilian Peev31abd0a2017-05-11 18:37:46 +01003488 }
3489 if (!found) {
3490 ALOGE("%s: Stream %d not found in stream configuration response from HAL",
3491 __FUNCTION__, streamId);
3492 return INVALID_OPERATION;
3493 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003494 device::V3_3::HalStream &src = finalConfiguration.streams[realIdx];
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003495 device::V3_6::HalStream &src_36 = finalConfiguration3_6.streams[realIdx];
Yin-Chia Yeh77327052017-01-09 18:23:07 -08003496
Emilian Peev710c1422017-08-30 11:19:38 +01003497 Camera3Stream* dstStream = Camera3Stream::cast(dst);
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003498 int overrideFormat = mapToFrameworkFormat(src.v3_2.overrideFormat);
3499 android_dataspace overrideDataSpace = mapToFrameworkDataspace(src.overrideDataSpace);
3500
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003501 if (mHidlSession_3_6 != nullptr) {
3502 dstStream->setOfflineProcessingSupport(src_36.supportOffline);
3503 }
3504
Yin-Chia Yeh90667662019-07-01 15:45:00 -07003505 if (dstStream->getOriginalFormat() != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
Shuzhen Wang92653952019-05-07 15:11:43 -07003506 dstStream->setFormatOverride(false);
3507 dstStream->setDataSpaceOverride(false);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003508 if (dst->format != overrideFormat) {
3509 ALOGE("%s: Stream %d: Format override not allowed for format 0x%x", __FUNCTION__,
3510 streamId, dst->format);
Yin-Chia Yeh77327052017-01-09 18:23:07 -08003511 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003512 if (dst->data_space != overrideDataSpace) {
3513 ALOGE("%s: Stream %d: DataSpace override not allowed for format 0x%x", __FUNCTION__,
3514 streamId, dst->format);
3515 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003516 } else {
Shuzhen Wang92653952019-05-07 15:11:43 -07003517 bool needFormatOverride =
3518 requestedConfiguration3_2.streams[i].format != src.v3_2.overrideFormat;
3519 bool needDataspaceOverride =
3520 requestedConfiguration3_2.streams[i].dataSpace != src.overrideDataSpace;
Emilian Peev31abd0a2017-05-11 18:37:46 +01003521 // Override allowed with IMPLEMENTATION_DEFINED
Shuzhen Wang92653952019-05-07 15:11:43 -07003522 dstStream->setFormatOverride(needFormatOverride);
3523 dstStream->setDataSpaceOverride(needDataspaceOverride);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003524 dst->format = overrideFormat;
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003525 dst->data_space = overrideDataSpace;
Yin-Chia Yeh77327052017-01-09 18:23:07 -08003526 }
3527
Emilian Peevf4816702020-04-03 15:44:51 -07003528 if (dst->stream_type == CAMERA_STREAM_INPUT) {
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003529 if (src.v3_2.producerUsage != 0) {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003530 ALOGE("%s: Stream %d: INPUT streams must have 0 for producer usage",
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003531 __FUNCTION__, streamId);
3532 return INVALID_OPERATION;
3533 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003534 dstStream->setUsage(
3535 mapConsumerToFrameworkUsage(src.v3_2.consumerUsage));
Emilian Peev31abd0a2017-05-11 18:37:46 +01003536 } else {
3537 // OUTPUT
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003538 if (src.v3_2.consumerUsage != 0) {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003539 ALOGE("%s: Stream %d: OUTPUT streams must have 0 for consumer usage",
3540 __FUNCTION__, streamId);
3541 return INVALID_OPERATION;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003542 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003543 dstStream->setUsage(
3544 mapProducerToFrameworkUsage(src.v3_2.producerUsage));
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003545 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003546 dst->max_buffers = src.v3_2.maxBuffers;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003547 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003548
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003549 return res;
3550}
3551
Cliff Wuc2ad9c82021-04-21 00:58:58 +08003552status_t Camera3Device::HalInterface::configureInjectedStreams(
3553 const camera_metadata_t* sessionParams, camera_stream_configuration* config,
3554 const std::vector<uint32_t>& bufferSizes,
3555 const CameraMetadata& cameraCharacteristics) {
3556 ATRACE_NAME("InjectionCameraHal::configureStreams");
3557 if (!valid()) return INVALID_OPERATION;
3558 status_t res = OK;
3559
3560 if (config->input_is_multi_resolution) {
3561 ALOGE("%s: Injection camera device doesn't support multi-resolution input "
3562 "stream", __FUNCTION__);
3563 return BAD_VALUE;
3564 }
3565
3566 // Convert stream config to HIDL
3567 std::set<int> activeStreams;
3568 device::V3_2::StreamConfiguration requestedConfiguration3_2;
3569 device::V3_4::StreamConfiguration requestedConfiguration3_4;
3570 device::V3_7::StreamConfiguration requestedConfiguration3_7;
3571 requestedConfiguration3_2.streams.resize(config->num_streams);
3572 requestedConfiguration3_4.streams.resize(config->num_streams);
3573 requestedConfiguration3_7.streams.resize(config->num_streams);
3574 for (size_t i = 0; i < config->num_streams; i++) {
3575 device::V3_2::Stream& dst3_2 = requestedConfiguration3_2.streams[i];
3576 device::V3_4::Stream& dst3_4 = requestedConfiguration3_4.streams[i];
3577 device::V3_7::Stream& dst3_7 = requestedConfiguration3_7.streams[i];
3578 camera3::camera_stream_t* src = config->streams[i];
3579
3580 Camera3Stream* cam3stream = Camera3Stream::cast(src);
3581 cam3stream->setBufferFreedListener(this);
3582 int streamId = cam3stream->getId();
3583 StreamType streamType;
3584 switch (src->stream_type) {
3585 case CAMERA_STREAM_OUTPUT:
3586 streamType = StreamType::OUTPUT;
3587 break;
3588 case CAMERA_STREAM_INPUT:
3589 streamType = StreamType::INPUT;
3590 break;
3591 default:
3592 ALOGE("%s: Stream %d: Unsupported stream type %d", __FUNCTION__,
3593 streamId, config->streams[i]->stream_type);
3594 return BAD_VALUE;
3595 }
3596 dst3_2.id = streamId;
3597 dst3_2.streamType = streamType;
3598 dst3_2.width = src->width;
3599 dst3_2.height = src->height;
3600 dst3_2.usage = mapToConsumerUsage(cam3stream->getUsage());
3601 dst3_2.rotation =
3602 mapToStreamRotation((camera_stream_rotation_t)src->rotation);
3603 // For HidlSession version 3.5 or newer, the format and dataSpace sent
3604 // to HAL are original, not the overridden ones.
3605 if (mHidlSession_3_5 != nullptr) {
3606 dst3_2.format = mapToPixelFormat(cam3stream->isFormatOverridden()
3607 ? cam3stream->getOriginalFormat()
3608 : src->format);
3609 dst3_2.dataSpace =
3610 mapToHidlDataspace(cam3stream->isDataSpaceOverridden()
3611 ? cam3stream->getOriginalDataSpace()
3612 : src->data_space);
3613 } else {
3614 dst3_2.format = mapToPixelFormat(src->format);
3615 dst3_2.dataSpace = mapToHidlDataspace(src->data_space);
3616 }
3617 dst3_4.v3_2 = dst3_2;
3618 dst3_4.bufferSize = bufferSizes[i];
3619 if (src->physical_camera_id != nullptr) {
3620 dst3_4.physicalCameraId = src->physical_camera_id;
3621 }
3622 dst3_7.v3_4 = dst3_4;
3623 dst3_7.groupId = cam3stream->getHalStreamGroupId();
3624 dst3_7.sensorPixelModesUsed.resize(src->sensor_pixel_modes_used.size());
3625 size_t j = 0;
3626 for (int mode : src->sensor_pixel_modes_used) {
3627 dst3_7.sensorPixelModesUsed[j++] =
3628 static_cast<CameraMetadataEnumAndroidSensorPixelMode>(mode);
3629 }
3630 activeStreams.insert(streamId);
3631 // Create Buffer ID map if necessary
3632 mBufferRecords.tryCreateBufferCache(streamId);
3633 }
3634 // remove BufferIdMap for deleted streams
3635 mBufferRecords.removeInactiveBufferCaches(activeStreams);
3636
3637 StreamConfigurationMode operationMode;
3638 res = mapToStreamConfigurationMode(
3639 (camera_stream_configuration_mode_t)config->operation_mode,
3640 /*out*/ &operationMode);
3641 if (res != OK) {
3642 return res;
3643 }
3644 requestedConfiguration3_7.operationMode = operationMode;
3645 size_t sessionParamSize = get_camera_metadata_size(sessionParams);
3646 requestedConfiguration3_7.operationMode = operationMode;
3647 requestedConfiguration3_7.sessionParams.setToExternal(
3648 reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams)),
3649 sessionParamSize);
3650
3651 // See which version of HAL we have
3652 if (mHidlSession_3_7 != nullptr) {
3653 requestedConfiguration3_7.streamConfigCounter = mNextStreamConfigCounter++;
3654 requestedConfiguration3_7.multiResolutionInputImage =
3655 config->input_is_multi_resolution;
3656
3657 const camera_metadata_t* rawMetadata = cameraCharacteristics.getAndLock();
3658 ::android::hardware::camera::device::V3_2::CameraMetadata hidlChars = {};
3659 hidlChars.setToExternal(
3660 reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(rawMetadata)),
3661 get_camera_metadata_size(rawMetadata));
3662 cameraCharacteristics.unlock(rawMetadata);
3663
3664 sp<hardware::camera::device::V3_7::ICameraInjectionSession>
3665 hidlInjectionSession_3_7;
3666 auto castInjectionResult_3_7 =
3667 device::V3_7::ICameraInjectionSession::castFrom(mHidlSession_3_7);
3668 if (castInjectionResult_3_7.isOk()) {
3669 hidlInjectionSession_3_7 = castInjectionResult_3_7;
3670 } else {
3671 ALOGE("%s: Transaction error: %s", __FUNCTION__,
3672 castInjectionResult_3_7.description().c_str());
3673 return DEAD_OBJECT;
3674 }
3675
3676 auto err = hidlInjectionSession_3_7->configureInjectionStreams(
3677 requestedConfiguration3_7, hidlChars);
3678 if (!err.isOk()) {
3679 ALOGE("%s: Transaction error: %s", __FUNCTION__,
3680 err.description().c_str());
3681 return DEAD_OBJECT;
3682 }
3683 } else {
3684 ALOGE("%s: mHidlSession_3_7 does not exist, the lowest version of injection "
3685 "session is 3.7", __FUNCTION__);
3686 return DEAD_OBJECT;
3687 }
3688
3689 return res;
3690}
3691
Emilian Peevf4816702020-04-03 15:44:51 -07003692status_t Camera3Device::HalInterface::wrapAsHidlRequest(camera_capture_request_t* request,
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003693 /*out*/device::V3_2::CaptureRequest* captureRequest,
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003694 /*out*/std::vector<native_handle_t*>* handlesCreated,
3695 /*out*/std::vector<std::pair<int32_t, int32_t>>* inflightBuffers) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003696 ATRACE_CALL();
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003697 if (captureRequest == nullptr || handlesCreated == nullptr || inflightBuffers == nullptr) {
3698 ALOGE("%s: captureRequest (%p), handlesCreated (%p), and inflightBuffers(%p) "
3699 "must not be null", __FUNCTION__, captureRequest, handlesCreated, inflightBuffers);
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003700 return BAD_VALUE;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003701 }
3702
3703 captureRequest->frameNumber = request->frame_number;
Yifan Hongf79b5542017-04-11 14:44:25 -07003704
3705 captureRequest->fmqSettingsSize = 0;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003706
3707 {
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003708 if (request->input_buffer != nullptr) {
3709 int32_t streamId = Camera3Stream::cast(request->input_buffer->stream)->getId();
3710 buffer_handle_t buf = *(request->input_buffer->buffer);
3711 auto pair = getBufferId(buf, streamId);
3712 bool isNewBuffer = pair.first;
3713 uint64_t bufferId = pair.second;
3714 captureRequest->inputBuffer.streamId = streamId;
3715 captureRequest->inputBuffer.bufferId = bufferId;
3716 captureRequest->inputBuffer.buffer = (isNewBuffer) ? buf : nullptr;
3717 captureRequest->inputBuffer.status = BufferStatus::OK;
3718 native_handle_t *acquireFence = nullptr;
3719 if (request->input_buffer->acquire_fence != -1) {
3720 acquireFence = native_handle_create(1,0);
3721 acquireFence->data[0] = request->input_buffer->acquire_fence;
3722 handlesCreated->push_back(acquireFence);
3723 }
3724 captureRequest->inputBuffer.acquireFence = acquireFence;
3725 captureRequest->inputBuffer.releaseFence = nullptr;
3726
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003727 mBufferRecords.pushInflightBuffer(captureRequest->frameNumber, streamId,
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003728 request->input_buffer->buffer);
3729 inflightBuffers->push_back(std::make_pair(captureRequest->frameNumber, streamId));
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003730 } else {
3731 captureRequest->inputBuffer.streamId = -1;
3732 captureRequest->inputBuffer.bufferId = BUFFER_ID_NO_BUFFER;
3733 }
3734
3735 captureRequest->outputBuffers.resize(request->num_output_buffers);
3736 for (size_t i = 0; i < request->num_output_buffers; i++) {
Emilian Peevf4816702020-04-03 15:44:51 -07003737 const camera_stream_buffer_t *src = request->output_buffers + i;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003738 StreamBuffer &dst = captureRequest->outputBuffers[i];
3739 int32_t streamId = Camera3Stream::cast(src->stream)->getId();
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003740 if (src->buffer != nullptr) {
3741 buffer_handle_t buf = *(src->buffer);
3742 auto pair = getBufferId(buf, streamId);
3743 bool isNewBuffer = pair.first;
3744 dst.bufferId = pair.second;
3745 dst.buffer = isNewBuffer ? buf : nullptr;
3746 native_handle_t *acquireFence = nullptr;
3747 if (src->acquire_fence != -1) {
3748 acquireFence = native_handle_create(1,0);
3749 acquireFence->data[0] = src->acquire_fence;
3750 handlesCreated->push_back(acquireFence);
3751 }
3752 dst.acquireFence = acquireFence;
3753 } else if (mUseHalBufManager) {
3754 // HAL buffer management path
3755 dst.bufferId = BUFFER_ID_NO_BUFFER;
3756 dst.buffer = nullptr;
3757 dst.acquireFence = nullptr;
3758 } else {
3759 ALOGE("%s: cannot send a null buffer in capture request!", __FUNCTION__);
3760 return BAD_VALUE;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003761 }
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003762 dst.streamId = streamId;
3763 dst.status = BufferStatus::OK;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003764 dst.releaseFence = nullptr;
3765
Yin-Chia Yeh5f840f82019-03-05 11:59:04 -08003766 // Output buffers are empty when using HAL buffer manager
3767 if (!mUseHalBufManager) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003768 mBufferRecords.pushInflightBuffer(
3769 captureRequest->frameNumber, streamId, src->buffer);
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003770 inflightBuffers->push_back(std::make_pair(captureRequest->frameNumber, streamId));
Yin-Chia Yeh5f840f82019-03-05 11:59:04 -08003771 }
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003772 }
3773 }
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003774 return OK;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003775}
3776
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003777void Camera3Device::HalInterface::cleanupNativeHandles(
3778 std::vector<native_handle_t*> *handles, bool closeFd) {
3779 if (handles == nullptr) {
3780 return;
3781 }
3782 if (closeFd) {
3783 for (auto& handle : *handles) {
3784 native_handle_close(handle);
3785 }
3786 }
3787 for (auto& handle : *handles) {
3788 native_handle_delete(handle);
3789 }
3790 handles->clear();
3791 return;
3792}
3793
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003794status_t Camera3Device::HalInterface::processBatchCaptureRequests(
Emilian Peevf4816702020-04-03 15:44:51 -07003795 std::vector<camera_capture_request_t*>& requests,/*out*/uint32_t* numRequestProcessed) {
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003796 ATRACE_NAME("CameraHal::processBatchCaptureRequests");
3797 if (!valid()) return INVALID_OPERATION;
3798
Emilian Peevaebbe412018-01-15 13:53:24 +00003799 sp<device::V3_4::ICameraDeviceSession> hidlSession_3_4;
Shuzhen Wang83bff122020-11-20 15:51:39 -08003800 sp<device::V3_7::ICameraDeviceSession> hidlSession_3_7;
3801 auto castResult_3_7 = device::V3_7::ICameraDeviceSession::castFrom(mHidlSession);
3802 if (castResult_3_7.isOk()) {
3803 hidlSession_3_7 = castResult_3_7;
3804 }
Emilian Peevaebbe412018-01-15 13:53:24 +00003805 auto castResult_3_4 = device::V3_4::ICameraDeviceSession::castFrom(mHidlSession);
3806 if (castResult_3_4.isOk()) {
3807 hidlSession_3_4 = castResult_3_4;
3808 }
3809
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003810 hardware::hidl_vec<device::V3_2::CaptureRequest> captureRequests;
Emilian Peevaebbe412018-01-15 13:53:24 +00003811 hardware::hidl_vec<device::V3_4::CaptureRequest> captureRequests_3_4;
Shuzhen Wang83bff122020-11-20 15:51:39 -08003812 hardware::hidl_vec<device::V3_7::CaptureRequest> captureRequests_3_7;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003813 size_t batchSize = requests.size();
Shuzhen Wang83bff122020-11-20 15:51:39 -08003814 if (hidlSession_3_7 != nullptr) {
3815 captureRequests_3_7.resize(batchSize);
3816 } else if (hidlSession_3_4 != nullptr) {
Emilian Peevaebbe412018-01-15 13:53:24 +00003817 captureRequests_3_4.resize(batchSize);
3818 } else {
3819 captureRequests.resize(batchSize);
3820 }
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003821 std::vector<native_handle_t*> handlesCreated;
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003822 std::vector<std::pair<int32_t, int32_t>> inflightBuffers;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003823
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003824 status_t res = OK;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003825 for (size_t i = 0; i < batchSize; i++) {
Shuzhen Wang83bff122020-11-20 15:51:39 -08003826 if (hidlSession_3_7 != nullptr) {
3827 res = wrapAsHidlRequest(requests[i], /*out*/&captureRequests_3_7[i].v3_4.v3_2,
3828 /*out*/&handlesCreated, /*out*/&inflightBuffers);
3829 } else if (hidlSession_3_4 != nullptr) {
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003830 res = wrapAsHidlRequest(requests[i], /*out*/&captureRequests_3_4[i].v3_2,
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003831 /*out*/&handlesCreated, /*out*/&inflightBuffers);
Emilian Peevaebbe412018-01-15 13:53:24 +00003832 } else {
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003833 res = wrapAsHidlRequest(requests[i], /*out*/&captureRequests[i],
3834 /*out*/&handlesCreated, /*out*/&inflightBuffers);
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003835 }
3836 if (res != OK) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003837 mBufferRecords.popInflightBuffers(inflightBuffers);
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003838 cleanupNativeHandles(&handlesCreated);
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003839 return res;
Emilian Peevaebbe412018-01-15 13:53:24 +00003840 }
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003841 }
3842
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003843 std::vector<device::V3_2::BufferCache> cachesToRemove;
3844 {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003845 std::lock_guard<std::mutex> lock(mFreedBuffersLock);
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003846 for (auto& pair : mFreedBuffers) {
3847 // The stream might have been removed since onBufferFreed
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003848 if (mBufferRecords.isStreamCached(pair.first)) {
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003849 cachesToRemove.push_back({pair.first, pair.second});
3850 }
3851 }
3852 mFreedBuffers.clear();
3853 }
3854
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003855 common::V1_0::Status status = common::V1_0::Status::INTERNAL_ERROR;
3856 *numRequestProcessed = 0;
Yifan Hongf79b5542017-04-11 14:44:25 -07003857
3858 // Write metadata to FMQ.
3859 for (size_t i = 0; i < batchSize; i++) {
Emilian Peevf4816702020-04-03 15:44:51 -07003860 camera_capture_request_t* request = requests[i];
Emilian Peevaebbe412018-01-15 13:53:24 +00003861 device::V3_2::CaptureRequest* captureRequest;
Shuzhen Wang83bff122020-11-20 15:51:39 -08003862 if (hidlSession_3_7 != nullptr) {
3863 captureRequest = &captureRequests_3_7[i].v3_4.v3_2;
3864 } else if (hidlSession_3_4 != nullptr) {
Emilian Peevaebbe412018-01-15 13:53:24 +00003865 captureRequest = &captureRequests_3_4[i].v3_2;
3866 } else {
3867 captureRequest = &captureRequests[i];
3868 }
Yifan Hongf79b5542017-04-11 14:44:25 -07003869
3870 if (request->settings != nullptr) {
3871 size_t settingsSize = get_camera_metadata_size(request->settings);
3872 if (mRequestMetadataQueue != nullptr && mRequestMetadataQueue->write(
3873 reinterpret_cast<const uint8_t*>(request->settings), settingsSize)) {
3874 captureRequest->settings.resize(0);
3875 captureRequest->fmqSettingsSize = settingsSize;
3876 } else {
3877 if (mRequestMetadataQueue != nullptr) {
3878 ALOGW("%s: couldn't utilize fmq, fallback to hwbinder", __FUNCTION__);
3879 }
3880 captureRequest->settings.setToExternal(
3881 reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(request->settings)),
3882 get_camera_metadata_size(request->settings));
3883 captureRequest->fmqSettingsSize = 0u;
3884 }
3885 } else {
3886 // A null request settings maps to a size-0 CameraMetadata
3887 captureRequest->settings.resize(0);
3888 captureRequest->fmqSettingsSize = 0u;
3889 }
Emilian Peevaebbe412018-01-15 13:53:24 +00003890
Shuzhen Wang83bff122020-11-20 15:51:39 -08003891 // hidl session 3.7 specific handling.
3892 if (hidlSession_3_7 != nullptr) {
3893 captureRequests_3_7[i].inputWidth = request->input_width;
3894 captureRequests_3_7[i].inputHeight = request->input_height;
3895 }
3896
3897 // hidl session 3.7 and 3.4 specific handling.
3898 if (hidlSession_3_7 != nullptr || hidlSession_3_4 != nullptr) {
3899 hardware::hidl_vec<device::V3_4::PhysicalCameraSetting>& physicalCameraSettings =
3900 (hidlSession_3_7 != nullptr) ?
3901 captureRequests_3_7[i].v3_4.physicalCameraSettings :
3902 captureRequests_3_4[i].physicalCameraSettings;
3903 physicalCameraSettings.resize(request->num_physcam_settings);
Emilian Peevaebbe412018-01-15 13:53:24 +00003904 for (size_t j = 0; j < request->num_physcam_settings; j++) {
Emilian Peev00420d22018-02-05 21:33:13 +00003905 if (request->physcam_settings != nullptr) {
3906 size_t settingsSize = get_camera_metadata_size(request->physcam_settings[j]);
3907 if (mRequestMetadataQueue != nullptr && mRequestMetadataQueue->write(
3908 reinterpret_cast<const uint8_t*>(request->physcam_settings[j]),
3909 settingsSize)) {
Shuzhen Wang83bff122020-11-20 15:51:39 -08003910 physicalCameraSettings[j].settings.resize(0);
3911 physicalCameraSettings[j].fmqSettingsSize = settingsSize;
Emilian Peev00420d22018-02-05 21:33:13 +00003912 } else {
3913 if (mRequestMetadataQueue != nullptr) {
3914 ALOGW("%s: couldn't utilize fmq, fallback to hwbinder", __FUNCTION__);
3915 }
Shuzhen Wang83bff122020-11-20 15:51:39 -08003916 physicalCameraSettings[j].settings.setToExternal(
Emilian Peev00420d22018-02-05 21:33:13 +00003917 reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(
3918 request->physcam_settings[j])),
3919 get_camera_metadata_size(request->physcam_settings[j]));
Shuzhen Wang83bff122020-11-20 15:51:39 -08003920 physicalCameraSettings[j].fmqSettingsSize = 0u;
Emilian Peevaebbe412018-01-15 13:53:24 +00003921 }
Emilian Peev00420d22018-02-05 21:33:13 +00003922 } else {
Yin-Chia Yeha2849702021-03-10 10:11:33 -08003923 physicalCameraSettings[j].fmqSettingsSize = 0u;
3924 physicalCameraSettings[j].settings.resize(0);
Emilian Peevaebbe412018-01-15 13:53:24 +00003925 }
Shuzhen Wang83bff122020-11-20 15:51:39 -08003926 physicalCameraSettings[j].physicalCameraId = request->physcam_id[j];
Emilian Peevaebbe412018-01-15 13:53:24 +00003927 }
3928 }
Yifan Hongf79b5542017-04-11 14:44:25 -07003929 }
Emilian Peevaebbe412018-01-15 13:53:24 +00003930
3931 hardware::details::return_status err;
Jayant Chowdharyc8d581e2018-07-16 14:46:23 -07003932 auto resultCallback =
3933 [&status, &numRequestProcessed] (auto s, uint32_t n) {
3934 status = s;
3935 *numRequestProcessed = n;
3936 };
Shuzhen Wang83bff122020-11-20 15:51:39 -08003937 if (hidlSession_3_7 != nullptr) {
3938 err = hidlSession_3_7->processCaptureRequest_3_7(captureRequests_3_7, cachesToRemove,
3939 resultCallback);
3940 } else if (hidlSession_3_4 != nullptr) {
Emilian Peevaebbe412018-01-15 13:53:24 +00003941 err = hidlSession_3_4->processCaptureRequest_3_4(captureRequests_3_4, cachesToRemove,
Jayant Chowdharyc8d581e2018-07-16 14:46:23 -07003942 resultCallback);
Emilian Peevaebbe412018-01-15 13:53:24 +00003943 } else {
3944 err = mHidlSession->processCaptureRequest(captureRequests, cachesToRemove,
Jayant Chowdharyc8d581e2018-07-16 14:46:23 -07003945 resultCallback);
Emilian Peevaebbe412018-01-15 13:53:24 +00003946 }
Eino-Ville Talvalac5cbb872017-04-27 12:48:33 -07003947 if (!err.isOk()) {
3948 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003949 status = common::V1_0::Status::CAMERA_DISCONNECTED;
Eino-Ville Talvalac5cbb872017-04-27 12:48:33 -07003950 }
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003951
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003952 if (status == common::V1_0::Status::OK && *numRequestProcessed != batchSize) {
3953 ALOGE("%s: processCaptureRequest returns OK but processed %d/%zu requests",
3954 __FUNCTION__, *numRequestProcessed, batchSize);
3955 status = common::V1_0::Status::INTERNAL_ERROR;
3956 }
3957
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003958 res = CameraProviderManager::mapToStatusT(status);
3959 if (res == OK) {
3960 if (mHidlSession->isRemote()) {
3961 // Only close acquire fence FDs when the HIDL transaction succeeds (so the FDs have been
3962 // sent to camera HAL processes)
3963 cleanupNativeHandles(&handlesCreated, /*closeFd*/true);
3964 } else {
3965 // In passthrough mode the FDs are now owned by HAL
3966 cleanupNativeHandles(&handlesCreated);
3967 }
3968 } else {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003969 mBufferRecords.popInflightBuffers(inflightBuffers);
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003970 cleanupNativeHandles(&handlesCreated);
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003971 }
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003972 return res;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003973}
3974
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003975status_t Camera3Device::HalInterface::flush() {
3976 ATRACE_NAME("CameraHal::flush");
3977 if (!valid()) return INVALID_OPERATION;
3978 status_t res = OK;
3979
Emilian Peev31abd0a2017-05-11 18:37:46 +01003980 auto err = mHidlSession->flush();
3981 if (!err.isOk()) {
3982 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3983 res = DEAD_OBJECT;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003984 } else {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003985 res = CameraProviderManager::mapToStatusT(err);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003986 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003987
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003988 return res;
3989}
3990
Emilian Peev31abd0a2017-05-11 18:37:46 +01003991status_t Camera3Device::HalInterface::dump(int /*fd*/) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003992 ATRACE_NAME("CameraHal::dump");
3993 if (!valid()) return INVALID_OPERATION;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003994
Emilian Peev31abd0a2017-05-11 18:37:46 +01003995 // Handled by CameraProviderManager::dump
3996
3997 return OK;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003998}
3999
4000status_t Camera3Device::HalInterface::close() {
4001 ATRACE_NAME("CameraHal::close()");
4002 if (!valid()) return INVALID_OPERATION;
4003 status_t res = OK;
4004
Emilian Peev31abd0a2017-05-11 18:37:46 +01004005 auto err = mHidlSession->close();
4006 // Interface will be dead shortly anyway, so don't log errors
4007 if (!err.isOk()) {
4008 res = DEAD_OBJECT;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08004009 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01004010
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08004011 return res;
4012}
4013
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07004014void Camera3Device::HalInterface::signalPipelineDrain(const std::vector<int>& streamIds) {
4015 ATRACE_NAME("CameraHal::signalPipelineDrain");
4016 if (!valid() || mHidlSession_3_5 == nullptr) {
4017 ALOGE("%s called on invalid camera!", __FUNCTION__);
4018 return;
4019 }
4020
Yin-Chia Yehc300a072019-02-13 14:56:57 -08004021 auto err = mHidlSession_3_5->signalStreamFlush(streamIds, mNextStreamConfigCounter - 1);
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07004022 if (!err.isOk()) {
4023 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
4024 return;
4025 }
4026}
4027
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004028status_t Camera3Device::HalInterface::switchToOffline(
4029 const std::vector<int32_t>& streamsToKeep,
4030 /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004031 /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
4032 /*out*/camera3::BufferRecords* bufferRecords) {
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004033 ATRACE_NAME("CameraHal::switchToOffline");
4034 if (!valid() || mHidlSession_3_6 == nullptr) {
4035 ALOGE("%s called on invalid camera!", __FUNCTION__);
4036 return INVALID_OPERATION;
4037 }
4038
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004039 if (offlineSessionInfo == nullptr || offlineSession == nullptr || bufferRecords == nullptr) {
4040 ALOGE("%s: output arguments must not be null!", __FUNCTION__);
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004041 return INVALID_OPERATION;
4042 }
4043
4044 common::V1_0::Status status = common::V1_0::Status::INTERNAL_ERROR;
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004045 auto resultCallback =
4046 [&status, &offlineSessionInfo, &offlineSession] (auto s, auto info, auto session) {
4047 status = s;
4048 *offlineSessionInfo = info;
4049 *offlineSession = session;
4050 };
4051 auto err = mHidlSession_3_6->switchToOffline(streamsToKeep, resultCallback);
4052
4053 if (!err.isOk()) {
4054 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
4055 return DEAD_OBJECT;
4056 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004057
4058 status_t ret = CameraProviderManager::mapToStatusT(status);
4059 if (ret != OK) {
4060 return ret;
4061 }
4062
4063 // TODO: assert no ongoing requestBuffer/returnBuffer call here
4064 // TODO: update RequestBufferStateMachine to block requestBuffer/returnBuffer once HAL
4065 // returns from switchToOffline.
4066
4067
4068 // Validate buffer caches
4069 std::vector<int32_t> streams;
4070 streams.reserve(offlineSessionInfo->offlineStreams.size());
4071 for (auto offlineStream : offlineSessionInfo->offlineStreams) {
4072 int32_t id = offlineStream.id;
4073 streams.push_back(id);
4074 // Verify buffer caches
4075 std::vector<uint64_t> bufIds(offlineStream.circulatingBufferIds.begin(),
4076 offlineStream.circulatingBufferIds.end());
4077 if (!verifyBufferIds(id, bufIds)) {
4078 ALOGE("%s: stream ID %d buffer cache records mismatch!", __FUNCTION__, id);
4079 return UNKNOWN_ERROR;
4080 }
4081 }
4082
4083 // Move buffer records
4084 bufferRecords->takeBufferCaches(mBufferRecords, streams);
4085 bufferRecords->takeInflightBufferMap(mBufferRecords);
4086 bufferRecords->takeRequestedBufferMap(mBufferRecords);
4087 return ret;
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004088}
4089
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07004090void Camera3Device::HalInterface::getInflightBufferKeys(
4091 std::vector<std::pair<int32_t, int32_t>>* out) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004092 mBufferRecords.getInflightBufferKeys(out);
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07004093 return;
4094}
4095
Yin-Chia Yeh84be5782019-03-01 11:47:02 -08004096void Camera3Device::HalInterface::getInflightRequestBufferKeys(
4097 std::vector<uint64_t>* out) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004098 mBufferRecords.getInflightRequestBufferKeys(out);
Yin-Chia Yeh84be5782019-03-01 11:47:02 -08004099 return;
4100}
4101
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004102bool Camera3Device::HalInterface::verifyBufferIds(
4103 int32_t streamId, std::vector<uint64_t>& bufIds) {
4104 return mBufferRecords.verifyBufferIds(streamId, bufIds);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08004105}
4106
4107status_t Camera3Device::HalInterface::popInflightBuffer(
Yin-Chia Yehf4650602017-01-10 13:13:39 -08004108 int32_t frameNumber, int32_t streamId,
4109 /*out*/ buffer_handle_t **buffer) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004110 return mBufferRecords.popInflightBuffer(frameNumber, streamId, buffer);
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07004111}
4112
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07004113status_t Camera3Device::HalInterface::pushInflightRequestBuffer(
Yin-Chia Yeh84be5782019-03-01 11:47:02 -08004114 uint64_t bufferId, buffer_handle_t* buf, int32_t streamId) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004115 return mBufferRecords.pushInflightRequestBuffer(bufferId, buf, streamId);
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07004116}
4117
4118// Find and pop a buffer_handle_t based on bufferId
4119status_t Camera3Device::HalInterface::popInflightRequestBuffer(
Yin-Chia Yeh84be5782019-03-01 11:47:02 -08004120 uint64_t bufferId,
4121 /*out*/ buffer_handle_t** buffer,
4122 /*optional out*/ int32_t* streamId) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004123 return mBufferRecords.popInflightRequestBuffer(bufferId, buffer, streamId);
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07004124}
4125
Yin-Chia Yeh77327052017-01-09 18:23:07 -08004126std::pair<bool, uint64_t> Camera3Device::HalInterface::getBufferId(
4127 const buffer_handle_t& buf, int streamId) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004128 return mBufferRecords.getBufferId(buf, streamId);
Yin-Chia Yeh77327052017-01-09 18:23:07 -08004129}
4130
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07004131void Camera3Device::HalInterface::onBufferFreed(
4132 int streamId, const native_handle_t* handle) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004133 uint32_t bufferId = mBufferRecords.removeOneBufferCache(streamId, handle);
4134 std::lock_guard<std::mutex> lock(mFreedBuffersLock);
4135 if (bufferId != BUFFER_ID_NO_BUFFER) {
4136 mFreedBuffers.push_back(std::make_pair(streamId, bufferId));
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07004137 }
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07004138}
4139
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07004140void Camera3Device::HalInterface::onStreamReConfigured(int streamId) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004141 std::vector<uint64_t> bufIds = mBufferRecords.clearBufferCaches(streamId);
4142 std::lock_guard<std::mutex> lock(mFreedBuffersLock);
4143 for (auto bufferId : bufIds) {
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07004144 mFreedBuffers.push_back(std::make_pair(streamId, bufferId));
4145 }
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07004146}
4147
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08004148/**
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004149 * RequestThread inner class methods
4150 */
4151
4152Camera3Device::RequestThread::RequestThread(wp<Camera3Device> parent,
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004153 sp<StatusTracker> statusTracker,
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07004154 sp<HalInterface> interface, const Vector<int32_t>& sessionParamKeys,
4155 bool useHalBufManager) :
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07004156 Thread(/*canCallJava*/false),
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004157 mParent(parent),
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004158 mStatusTracker(statusTracker),
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08004159 mInterface(interface),
Eino-Ville Talvala77c1a352016-06-13 12:32:43 -07004160 mListener(nullptr),
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07004161 mId(getId(parent)),
Shuzhen Wang316781a2020-08-18 18:11:01 -07004162 mFirstRepeating(false),
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004163 mReconfigured(false),
4164 mDoPause(false),
4165 mPaused(true),
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07004166 mNotifyPipelineDrain(false),
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004167 mFrameNumber(0),
Jianing Weicb0652e2014-03-12 18:29:36 -07004168 mLatestRequestId(NAME_NOT_FOUND),
Yin-Chia Yehc00a25c2014-08-21 14:27:44 -07004169 mCurrentAfTriggerId(0),
4170 mCurrentPreCaptureTriggerId(0),
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08004171 mRotateAndCropOverride(ANDROID_SCALER_ROTATE_AND_CROP_NONE),
Eino-Ville Talvala11afe4f2021-05-27 14:45:31 -07004172 mCameraMute(ANDROID_SENSOR_TEST_PATTERN_MODE_OFF),
Eino-Ville Talvala305cec62020-11-12 14:18:17 -08004173 mCameraMuteChanged(false),
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08004174 mRepeatingLastFrameNumber(
4175 hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES),
Shuzhen Wang686f6442017-06-20 16:16:04 -07004176 mPrepareVideoStream(false),
Emilian Peeva14b4dd2018-05-15 11:00:31 +01004177 mConstrainedMode(false),
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004178 mRequestLatency(kRequestLatencyBinSize),
4179 mSessionParamKeys(sessionParamKeys),
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07004180 mLatestSessionParams(sessionParamKeys.size()),
4181 mUseHalBufManager(useHalBufManager) {
Yin-Chia Yeh87b3ec02019-06-03 10:44:39 -07004182 mStatusId = statusTracker->addComponent("RequestThread");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004183}
4184
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08004185Camera3Device::RequestThread::~RequestThread() {}
4186
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07004187void Camera3Device::RequestThread::setNotificationListener(
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07004188 wp<NotificationListener> listener) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004189 ATRACE_CALL();
Eino-Ville Talvala17543512014-08-06 14:32:02 -07004190 Mutex::Autolock l(mRequestLock);
4191 mListener = listener;
4192}
4193
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004194void Camera3Device::RequestThread::configurationComplete(bool isConstrainedHighSpeed,
Shuzhen Wang99080502021-03-07 21:08:20 -08004195 const CameraMetadata& sessionParams,
4196 const std::map<int32_t, std::set<String8>>& groupIdPhysicalCameraMap) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004197 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004198 Mutex::Autolock l(mRequestLock);
4199 mReconfigured = true;
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004200 mLatestSessionParams = sessionParams;
Shuzhen Wang99080502021-03-07 21:08:20 -08004201 mGroupIdPhysicalCameraMap = groupIdPhysicalCameraMap;
Chien-Yu Chenc66969b2016-05-19 16:37:51 -07004202 // Prepare video stream for high speed recording.
4203 mPrepareVideoStream = isConstrainedHighSpeed;
Emilian Peeva14b4dd2018-05-15 11:00:31 +01004204 mConstrainedMode = isConstrainedHighSpeed;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004205}
4206
Jianing Wei90e59c92014-03-12 18:29:36 -07004207status_t Camera3Device::RequestThread::queueRequestList(
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07004208 List<sp<CaptureRequest> > &requests,
4209 /*out*/
4210 int64_t *lastFrameNumber) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004211 ATRACE_CALL();
Jianing Wei90e59c92014-03-12 18:29:36 -07004212 Mutex::Autolock l(mRequestLock);
4213 for (List<sp<CaptureRequest> >::iterator it = requests.begin(); it != requests.end();
4214 ++it) {
4215 mRequestQueue.push_back(*it);
4216 }
4217
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07004218 if (lastFrameNumber != NULL) {
4219 *lastFrameNumber = mFrameNumber + mRequestQueue.size() - 1;
4220 ALOGV("%s: requestId %d, mFrameNumber %" PRId32 ", lastFrameNumber %" PRId64 ".",
4221 __FUNCTION__, (*(requests.begin()))->mResultExtras.requestId, mFrameNumber,
4222 *lastFrameNumber);
4223 }
Jianing Weicb0652e2014-03-12 18:29:36 -07004224
Jianing Wei90e59c92014-03-12 18:29:36 -07004225 unpauseForNewRequests();
4226
4227 return OK;
4228}
4229
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004230
4231status_t Camera3Device::RequestThread::queueTrigger(
4232 RequestTrigger trigger[],
4233 size_t count) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004234 ATRACE_CALL();
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004235 Mutex::Autolock l(mTriggerMutex);
4236 status_t ret;
4237
4238 for (size_t i = 0; i < count; ++i) {
4239 ret = queueTriggerLocked(trigger[i]);
4240
4241 if (ret != OK) {
4242 return ret;
4243 }
4244 }
4245
4246 return OK;
4247}
4248
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08004249const String8& Camera3Device::RequestThread::getId(const wp<Camera3Device> &device) {
4250 static String8 deadId("<DeadDevice>");
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07004251 sp<Camera3Device> d = device.promote();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08004252 if (d != nullptr) return d->mId;
4253 return deadId;
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07004254}
4255
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004256status_t Camera3Device::RequestThread::queueTriggerLocked(
4257 RequestTrigger trigger) {
4258
4259 uint32_t tag = trigger.metadataTag;
4260 ssize_t index = mTriggerMap.indexOfKey(tag);
4261
4262 switch (trigger.getTagType()) {
4263 case TYPE_BYTE:
4264 // fall-through
4265 case TYPE_INT32:
4266 break;
4267 default:
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07004268 ALOGE("%s: Type not supported: 0x%x", __FUNCTION__,
4269 trigger.getTagType());
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004270 return INVALID_OPERATION;
4271 }
4272
4273 /**
4274 * Collect only the latest trigger, since we only have 1 field
4275 * in the request settings per trigger tag, and can't send more than 1
4276 * trigger per request.
4277 */
4278 if (index != NAME_NOT_FOUND) {
4279 mTriggerMap.editValueAt(index) = trigger;
4280 } else {
4281 mTriggerMap.add(tag, trigger);
4282 }
4283
4284 return OK;
4285}
4286
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004287status_t Camera3Device::RequestThread::setRepeatingRequests(
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07004288 const RequestList &requests,
4289 /*out*/
4290 int64_t *lastFrameNumber) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004291 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004292 Mutex::Autolock l(mRequestLock);
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07004293 if (lastFrameNumber != NULL) {
4294 *lastFrameNumber = mRepeatingLastFrameNumber;
4295 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004296 mRepeatingRequests.clear();
Shuzhen Wang316781a2020-08-18 18:11:01 -07004297 mFirstRepeating = true;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004298 mRepeatingRequests.insert(mRepeatingRequests.begin(),
4299 requests.begin(), requests.end());
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07004300
4301 unpauseForNewRequests();
4302
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08004303 mRepeatingLastFrameNumber = hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004304 return OK;
4305}
4306
Chih-Hung Hsieh8b0b9712016-08-09 14:25:53 -07004307bool Camera3Device::RequestThread::isRepeatingRequestLocked(const sp<CaptureRequest>& requestIn) {
Yin-Chia Yeh8684b7f2014-06-13 14:53:05 -07004308 if (mRepeatingRequests.empty()) {
4309 return false;
4310 }
4311 int32_t requestId = requestIn->mResultExtras.requestId;
4312 const RequestList &repeatRequests = mRepeatingRequests;
4313 // All repeating requests are guaranteed to have same id so only check first quest
4314 const sp<CaptureRequest> firstRequest = *repeatRequests.begin();
4315 return (firstRequest->mResultExtras.requestId == requestId);
4316}
4317
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07004318status_t Camera3Device::RequestThread::clearRepeatingRequests(/*out*/int64_t *lastFrameNumber) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004319 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004320 Mutex::Autolock l(mRequestLock);
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07004321 return clearRepeatingRequestsLocked(lastFrameNumber);
4322
4323}
4324
4325status_t Camera3Device::RequestThread::clearRepeatingRequestsLocked(/*out*/int64_t *lastFrameNumber) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004326 mRepeatingRequests.clear();
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07004327 if (lastFrameNumber != NULL) {
4328 *lastFrameNumber = mRepeatingLastFrameNumber;
4329 }
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08004330 mRepeatingLastFrameNumber = hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004331 return OK;
4332}
4333
Eino-Ville Talvala17543512014-08-06 14:32:02 -07004334status_t Camera3Device::RequestThread::clear(
Eino-Ville Talvala17543512014-08-06 14:32:02 -07004335 /*out*/int64_t *lastFrameNumber) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004336 ATRACE_CALL();
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07004337 Mutex::Autolock l(mRequestLock);
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07004338 ALOGV("RequestThread::%s:", __FUNCTION__);
Eino-Ville Talvala17543512014-08-06 14:32:02 -07004339
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07004340 mRepeatingRequests.clear();
Yin-Chia Yeh8684b7f2014-06-13 14:53:05 -07004341
Eino-Ville Talvala17543512014-08-06 14:32:02 -07004342 // Send errors for all requests pending in the request queue, including
4343 // pending repeating requests
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07004344 sp<NotificationListener> listener = mListener.promote();
Eino-Ville Talvala17543512014-08-06 14:32:02 -07004345 if (listener != NULL) {
4346 for (RequestList::iterator it = mRequestQueue.begin();
4347 it != mRequestQueue.end(); ++it) {
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07004348 // Abort the input buffers for reprocess requests.
4349 if ((*it)->mInputStream != NULL) {
Emilian Peevf4816702020-04-03 15:44:51 -07004350 camera_stream_buffer_t inputBuffer;
Shuzhen Wang83bff122020-11-20 15:51:39 -08004351 camera3::Size inputBufferSize;
Eino-Ville Talvalaba435252017-06-21 16:07:25 -07004352 status_t res = (*it)->mInputStream->getInputBuffer(&inputBuffer,
Shuzhen Wang83bff122020-11-20 15:51:39 -08004353 &inputBufferSize, /*respectHalLimit*/ false);
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07004354 if (res != OK) {
4355 ALOGW("%s: %d: couldn't get input buffer while clearing the request "
4356 "list: %s (%d)", __FUNCTION__, __LINE__, strerror(-res), res);
4357 } else {
Emilian Peevf4816702020-04-03 15:44:51 -07004358 inputBuffer.status = CAMERA_BUFFER_STATUS_ERROR;
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07004359 res = (*it)->mInputStream->returnInputBuffer(inputBuffer);
4360 if (res != OK) {
4361 ALOGE("%s: %d: couldn't return input buffer while clearing the request "
4362 "list: %s (%d)", __FUNCTION__, __LINE__, strerror(-res), res);
4363 }
4364 }
4365 }
Eino-Ville Talvala17543512014-08-06 14:32:02 -07004366 // Set the frame number this request would have had, if it
4367 // had been submitted; this frame number will not be reused.
4368 // The requestId and burstId fields were set when the request was
4369 // submitted originally (in convertMetadataListToRequestListLocked)
4370 (*it)->mResultExtras.frameNumber = mFrameNumber++;
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08004371 listener->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
Eino-Ville Talvala17543512014-08-06 14:32:02 -07004372 (*it)->mResultExtras);
Yin-Chia Yeh8684b7f2014-06-13 14:53:05 -07004373 }
4374 }
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07004375 mRequestQueue.clear();
Jinguang Dongb26e7a02016-11-14 16:04:02 +08004376
4377 Mutex::Autolock al(mTriggerMutex);
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07004378 mTriggerMap.clear();
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07004379 if (lastFrameNumber != NULL) {
4380 *lastFrameNumber = mRepeatingLastFrameNumber;
4381 }
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08004382 mRepeatingLastFrameNumber = hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES;
Emilian Peev8dae54c2019-12-02 15:17:17 -08004383 mRequestSignal.signal();
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07004384 return OK;
4385}
4386
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004387status_t Camera3Device::RequestThread::flush() {
4388 ATRACE_CALL();
4389 Mutex::Autolock l(mFlushLock);
4390
Emilian Peev08dd2452017-04-06 16:55:14 +01004391 return mInterface->flush();
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004392}
4393
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004394void Camera3Device::RequestThread::setPaused(bool paused) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004395 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004396 Mutex::Autolock l(mPauseLock);
4397 mDoPause = paused;
4398 mDoPauseSignal.signal();
4399}
4400
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004401status_t Camera3Device::RequestThread::waitUntilRequestProcessed(
4402 int32_t requestId, nsecs_t timeout) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004403 ATRACE_CALL();
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004404 Mutex::Autolock l(mLatestRequestMutex);
4405 status_t res;
4406 while (mLatestRequestId != requestId) {
4407 nsecs_t startTime = systemTime();
4408
4409 res = mLatestRequestSignal.waitRelative(mLatestRequestMutex, timeout);
4410 if (res != OK) return res;
4411
4412 timeout -= (systemTime() - startTime);
4413 }
4414
4415 return OK;
4416}
4417
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004418void Camera3Device::RequestThread::requestExit() {
4419 // Call parent to set up shutdown
4420 Thread::requestExit();
4421 // The exit from any possible waits
4422 mDoPauseSignal.signal();
4423 mRequestSignal.signal();
Shuzhen Wang686f6442017-06-20 16:16:04 -07004424
4425 mRequestLatency.log("ProcessCaptureRequest latency histogram");
4426 mRequestLatency.reset();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004427}
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004428
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07004429void Camera3Device::RequestThread::checkAndStopRepeatingRequest() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004430 ATRACE_CALL();
Yin-Chia Yeh473fad92016-05-23 15:54:41 -07004431 bool surfaceAbandoned = false;
4432 int64_t lastFrameNumber = 0;
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07004433 sp<NotificationListener> listener;
Yin-Chia Yeh473fad92016-05-23 15:54:41 -07004434 {
4435 Mutex::Autolock l(mRequestLock);
4436 // Check all streams needed by repeating requests are still valid. Otherwise, stop
4437 // repeating requests.
4438 for (const auto& request : mRepeatingRequests) {
4439 for (const auto& s : request->mOutputStreams) {
4440 if (s->isAbandoned()) {
4441 surfaceAbandoned = true;
4442 clearRepeatingRequestsLocked(&lastFrameNumber);
4443 break;
4444 }
4445 }
4446 if (surfaceAbandoned) {
4447 break;
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07004448 }
4449 }
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07004450 listener = mListener.promote();
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07004451 }
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07004452
4453 if (listener != NULL && surfaceAbandoned) {
4454 listener->notifyRepeatingRequestError(lastFrameNumber);
Yin-Chia Yeh473fad92016-05-23 15:54:41 -07004455 }
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07004456}
4457
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004458bool Camera3Device::RequestThread::sendRequestsBatch() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004459 ATRACE_CALL();
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004460 status_t res;
4461 size_t batchSize = mNextRequests.size();
Emilian Peevf4816702020-04-03 15:44:51 -07004462 std::vector<camera_capture_request_t*> requests(batchSize);
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004463 uint32_t numRequestProcessed = 0;
4464 for (size_t i = 0; i < batchSize; i++) {
4465 requests[i] = &mNextRequests.editItemAt(i).halRequest;
Yin-Chia Yeh885691c2018-05-01 15:54:24 -07004466 ATRACE_ASYNC_BEGIN("frame capture", mNextRequests[i].halRequest.frame_number);
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004467 }
4468
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004469 res = mInterface->processBatchCaptureRequests(requests, &numRequestProcessed);
4470
4471 bool triggerRemoveFailed = false;
4472 NextRequest& triggerFailedRequest = mNextRequests.editItemAt(0);
4473 for (size_t i = 0; i < numRequestProcessed; i++) {
4474 NextRequest& nextRequest = mNextRequests.editItemAt(i);
4475 nextRequest.submitted = true;
4476
Shuzhen Wangc2cba122018-05-17 18:10:24 -07004477 updateNextRequest(nextRequest);
Emilian Peevaebbe412018-01-15 13:53:24 +00004478
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004479 if (!triggerRemoveFailed) {
4480 // Remove any previously queued triggers (after unlock)
4481 status_t removeTriggerRes = removeTriggers(mPrevRequest);
4482 if (removeTriggerRes != OK) {
4483 triggerRemoveFailed = true;
4484 triggerFailedRequest = nextRequest;
4485 }
4486 }
4487 }
4488
4489 if (triggerRemoveFailed) {
4490 SET_ERR("RequestThread: Unable to remove triggers "
4491 "(capture request %d, HAL device: %s (%d)",
4492 triggerFailedRequest.halRequest.frame_number, strerror(-res), res);
4493 cleanUpFailedRequests(/*sendRequestError*/ false);
4494 return false;
4495 }
4496
4497 if (res != OK) {
4498 // Should only get a failure here for malformed requests or device-level
4499 // errors, so consider all errors fatal. Bad metadata failures should
4500 // come through notify.
4501 SET_ERR("RequestThread: Unable to submit capture request %d to HAL device: %s (%d)",
4502 mNextRequests[numRequestProcessed].halRequest.frame_number,
4503 strerror(-res), res);
4504 cleanUpFailedRequests(/*sendRequestError*/ false);
4505 return false;
4506 }
4507 return true;
4508}
4509
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07004510nsecs_t Camera3Device::RequestThread::calculateMaxExpectedDuration(const camera_metadata_t *request) {
4511 nsecs_t maxExpectedDuration = kDefaultExpectedDuration;
4512 camera_metadata_ro_entry_t e = camera_metadata_ro_entry_t();
4513 find_camera_metadata_ro_entry(request,
4514 ANDROID_CONTROL_AE_MODE,
4515 &e);
4516 if (e.count == 0) return maxExpectedDuration;
4517
4518 switch (e.data.u8[0]) {
4519 case ANDROID_CONTROL_AE_MODE_OFF:
4520 find_camera_metadata_ro_entry(request,
4521 ANDROID_SENSOR_EXPOSURE_TIME,
4522 &e);
4523 if (e.count > 0) {
4524 maxExpectedDuration = e.data.i64[0];
4525 }
4526 find_camera_metadata_ro_entry(request,
4527 ANDROID_SENSOR_FRAME_DURATION,
4528 &e);
4529 if (e.count > 0) {
4530 maxExpectedDuration = std::max(e.data.i64[0], maxExpectedDuration);
4531 }
4532 break;
4533 default:
4534 find_camera_metadata_ro_entry(request,
4535 ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
4536 &e);
4537 if (e.count > 1) {
4538 maxExpectedDuration = 1e9 / e.data.u8[0];
4539 }
4540 break;
4541 }
4542
4543 return maxExpectedDuration;
4544}
4545
Emilian Peeva14b4dd2018-05-15 11:00:31 +01004546bool Camera3Device::RequestThread::skipHFRTargetFPSUpdate(int32_t tag,
4547 const camera_metadata_ro_entry_t& newEntry, const camera_metadata_entry_t& currentEntry) {
4548 if (mConstrainedMode && (ANDROID_CONTROL_AE_TARGET_FPS_RANGE == tag) &&
4549 (newEntry.count == currentEntry.count) && (currentEntry.count == 2) &&
4550 (currentEntry.data.i32[1] == newEntry.data.i32[1])) {
4551 return true;
4552 }
4553
4554 return false;
4555}
4556
Shuzhen Wangc2cba122018-05-17 18:10:24 -07004557void Camera3Device::RequestThread::updateNextRequest(NextRequest& nextRequest) {
4558 // Update the latest request sent to HAL
Shuzhen Wang83bff122020-11-20 15:51:39 -08004559 camera_capture_request_t& halRequest = nextRequest.halRequest;
4560 if (halRequest.settings != NULL) { // Don't update if they were unchanged
Shuzhen Wangc2cba122018-05-17 18:10:24 -07004561 Mutex::Autolock al(mLatestRequestMutex);
4562
Shuzhen Wang83bff122020-11-20 15:51:39 -08004563 camera_metadata_t* cloned = clone_camera_metadata(halRequest.settings);
Shuzhen Wangc2cba122018-05-17 18:10:24 -07004564 mLatestRequest.acquire(cloned);
4565
4566 mLatestPhysicalRequest.clear();
Shuzhen Wang83bff122020-11-20 15:51:39 -08004567 for (uint32_t i = 0; i < halRequest.num_physcam_settings; i++) {
4568 cloned = clone_camera_metadata(halRequest.physcam_settings[i]);
4569 mLatestPhysicalRequest.emplace(halRequest.physcam_id[i],
Shuzhen Wangc2cba122018-05-17 18:10:24 -07004570 CameraMetadata(cloned));
4571 }
4572
4573 sp<Camera3Device> parent = mParent.promote();
4574 if (parent != NULL) {
4575 parent->monitorMetadata(TagMonitor::REQUEST,
Shuzhen Wang83bff122020-11-20 15:51:39 -08004576 halRequest.frame_number,
Shuzhen Wangc2cba122018-05-17 18:10:24 -07004577 0, mLatestRequest, mLatestPhysicalRequest);
4578 }
4579 }
4580
Shuzhen Wang83bff122020-11-20 15:51:39 -08004581 if (halRequest.settings != NULL) {
Shuzhen Wangc2cba122018-05-17 18:10:24 -07004582 nextRequest.captureRequest->mSettingsList.begin()->metadata.unlock(
Shuzhen Wang83bff122020-11-20 15:51:39 -08004583 halRequest.settings);
Shuzhen Wangc2cba122018-05-17 18:10:24 -07004584 }
4585
Shuzhen Wang83bff122020-11-20 15:51:39 -08004586 cleanupPhysicalSettings(nextRequest.captureRequest, &halRequest);
Shuzhen Wangc2cba122018-05-17 18:10:24 -07004587}
4588
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004589bool Camera3Device::RequestThread::updateSessionParameters(const CameraMetadata& settings) {
4590 ATRACE_CALL();
4591 bool updatesDetected = false;
4592
Emilian Peev4ec17882019-01-24 17:16:58 -08004593 CameraMetadata updatedParams(mLatestSessionParams);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004594 for (auto tag : mSessionParamKeys) {
4595 camera_metadata_ro_entry entry = settings.find(tag);
Emilian Peev4ec17882019-01-24 17:16:58 -08004596 camera_metadata_entry lastEntry = updatedParams.find(tag);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004597
4598 if (entry.count > 0) {
4599 bool isDifferent = false;
4600 if (lastEntry.count > 0) {
4601 // Have a last value, compare to see if changed
4602 if (lastEntry.type == entry.type &&
4603 lastEntry.count == entry.count) {
4604 // Same type and count, compare values
4605 size_t bytesPerValue = camera_metadata_type_size[lastEntry.type];
4606 size_t entryBytes = bytesPerValue * lastEntry.count;
4607 int cmp = memcmp(entry.data.u8, lastEntry.data.u8, entryBytes);
4608 if (cmp != 0) {
4609 isDifferent = true;
4610 }
4611 } else {
4612 // Count or type has changed
4613 isDifferent = true;
4614 }
4615 } else {
4616 // No last entry, so always consider to be different
4617 isDifferent = true;
4618 }
4619
4620 if (isDifferent) {
4621 ALOGV("%s: Session parameter tag id %d changed", __FUNCTION__, tag);
Emilian Peeva14b4dd2018-05-15 11:00:31 +01004622 if (!skipHFRTargetFPSUpdate(tag, entry, lastEntry)) {
4623 updatesDetected = true;
4624 }
Emilian Peev4ec17882019-01-24 17:16:58 -08004625 updatedParams.update(entry);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004626 }
4627 } else if (lastEntry.count > 0) {
4628 // Value has been removed
4629 ALOGV("%s: Session parameter tag id %d removed", __FUNCTION__, tag);
Emilian Peev4ec17882019-01-24 17:16:58 -08004630 updatedParams.erase(tag);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004631 updatesDetected = true;
4632 }
4633 }
4634
Emilian Peev4ec17882019-01-24 17:16:58 -08004635 bool reconfigureRequired;
4636 if (updatesDetected) {
4637 reconfigureRequired = mInterface->isReconfigurationRequired(mLatestSessionParams,
4638 updatedParams);
4639 mLatestSessionParams = updatedParams;
4640 } else {
4641 reconfigureRequired = false;
4642 }
4643
4644 return reconfigureRequired;
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004645}
4646
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004647bool Camera3Device::RequestThread::threadLoop() {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004648 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004649 status_t res;
Jayant Chowdhary37eca242019-11-18 08:55:56 -08004650 // Any function called from threadLoop() must not hold mInterfaceLock since
4651 // it could lead to deadlocks (disconnect() -> hold mInterfaceMutex -> wait for request thread
4652 // to finish -> request thread waits on mInterfaceMutex) http://b/143513518
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004653
4654 // Handle paused state.
4655 if (waitIfPaused()) {
4656 return true;
4657 }
4658
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004659 // Wait for the next batch of requests.
4660 waitForNextRequestBatch();
4661 if (mNextRequests.size() == 0) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004662 return true;
4663 }
4664
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004665 // Get the latest request ID, if any
4666 int latestRequestId;
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004667 camera_metadata_entry_t requestIdEntry = mNextRequests[mNextRequests.size() - 1].
Emilian Peevaebbe412018-01-15 13:53:24 +00004668 captureRequest->mSettingsList.begin()->metadata.find(ANDROID_REQUEST_ID);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004669 if (requestIdEntry.count > 0) {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004670 latestRequestId = requestIdEntry.data.i32[0];
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004671 } else {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004672 ALOGW("%s: Did not have android.request.id set in the request.", __FUNCTION__);
4673 latestRequestId = NAME_NOT_FOUND;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004674 }
4675
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004676 // 'mNextRequests' will at this point contain either a set of HFR batched requests
4677 // or a single request from streaming or burst. In either case the first element
4678 // should contain the latest camera settings that we need to check for any session
4679 // parameter updates.
Emilian Peevaebbe412018-01-15 13:53:24 +00004680 if (updateSessionParameters(mNextRequests[0].captureRequest->mSettingsList.begin()->metadata)) {
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004681 res = OK;
4682
4683 //Input stream buffers are already acquired at this point so an input stream
4684 //will not be able to move to idle state unless we force it.
4685 if (mNextRequests[0].captureRequest->mInputStream != nullptr) {
4686 res = mNextRequests[0].captureRequest->mInputStream->forceToIdle();
4687 if (res != OK) {
4688 ALOGE("%s: Failed to force idle input stream: %d", __FUNCTION__, res);
4689 cleanUpFailedRequests(/*sendRequestError*/ false);
4690 return false;
4691 }
4692 }
4693
4694 if (res == OK) {
Emilian Peev3bead5f2020-05-28 17:29:08 -07004695 sp<Camera3Device> parent = mParent.promote();
4696 if (parent != nullptr) {
4697 mReconfigured |= parent->reconfigureCamera(mLatestSessionParams, mStatusId);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004698 }
Emilian Peev3bead5f2020-05-28 17:29:08 -07004699 setPaused(false);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004700
4701 if (mNextRequests[0].captureRequest->mInputStream != nullptr) {
4702 mNextRequests[0].captureRequest->mInputStream->restoreConfiguredState();
4703 if (res != OK) {
4704 ALOGE("%s: Failed to restore configured input stream: %d", __FUNCTION__, res);
4705 cleanUpFailedRequests(/*sendRequestError*/ false);
4706 return false;
4707 }
4708 }
4709 }
4710 }
4711
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004712 // Prepare a batch of HAL requests and output buffers.
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004713 res = prepareHalRequests();
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004714 if (res == TIMED_OUT) {
4715 // Not a fatal error if getting output buffers time out.
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004716 cleanUpFailedRequests(/*sendRequestError*/ true);
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07004717 // Check if any stream is abandoned.
4718 checkAndStopRepeatingRequest();
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004719 return true;
4720 } else if (res != OK) {
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004721 cleanUpFailedRequests(/*sendRequestError*/ false);
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07004722 return false;
4723 }
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004724
Zhijun Hecc27e112013-10-03 16:12:43 -07004725 // Inform waitUntilRequestProcessed thread of a new request ID
4726 {
4727 Mutex::Autolock al(mLatestRequestMutex);
4728
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004729 mLatestRequestId = latestRequestId;
Zhijun Hecc27e112013-10-03 16:12:43 -07004730 mLatestRequestSignal.signal();
4731 }
4732
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004733 // Submit a batch of requests to HAL.
4734 // Use flush lock only when submitting multilple requests in a batch.
4735 // TODO: The problem with flush lock is flush() will be blocked by process_capture_request()
4736 // which may take a long time to finish so synchronizing flush() and
4737 // process_capture_request() defeats the purpose of cancelling requests ASAP with flush().
4738 // For now, only synchronize for high speed recording and we should figure something out for
4739 // removing the synchronization.
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004740 bool useFlushLock = mNextRequests.size() > 1;
Eino-Ville Talvala17a61ad2013-06-03 16:53:32 -07004741
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004742 if (useFlushLock) {
4743 mFlushLock.lock();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004744 }
4745
Zhijun Hef0645c12016-08-02 00:58:11 -07004746 ALOGVV("%s: %d: submitting %zu requests in a batch.", __FUNCTION__, __LINE__,
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004747 mNextRequests.size());
Igor Murashkin1e479c02013-09-06 16:55:14 -07004748
Yin-Chia Yehcd333fe2019-02-08 13:45:41 -08004749 sp<Camera3Device> parent = mParent.promote();
4750 if (parent != nullptr) {
4751 parent->mRequestBufferSM.onSubmittingRequest();
4752 }
4753
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004754 bool submitRequestSuccess = false;
Shuzhen Wang686f6442017-06-20 16:16:04 -07004755 nsecs_t tRequestStart = systemTime(SYSTEM_TIME_MONOTONIC);
Yin-Chia Yeh11648852019-05-16 10:42:54 -07004756 submitRequestSuccess = sendRequestsBatch();
4757
Shuzhen Wang686f6442017-06-20 16:16:04 -07004758 nsecs_t tRequestEnd = systemTime(SYSTEM_TIME_MONOTONIC);
4759 mRequestLatency.add(tRequestStart, tRequestEnd);
Igor Murashkin1e479c02013-09-06 16:55:14 -07004760
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004761 if (useFlushLock) {
4762 mFlushLock.unlock();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004763 }
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004764
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004765 // Unset as current request
4766 {
4767 Mutex::Autolock l(mRequestLock);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004768 mNextRequests.clear();
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004769 }
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004770 mRequestSubmittedSignal.signal();
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004771
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004772 return submitRequestSuccess;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004773}
4774
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004775status_t Camera3Device::RequestThread::prepareHalRequests() {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004776 ATRACE_CALL();
4777
Yin-Chia Yehd07b11e2018-06-01 12:50:02 -07004778 bool batchedRequest = mNextRequests[0].captureRequest->mBatchSize > 1;
Shuzhen Wang4a472662017-02-26 23:29:04 -08004779 for (size_t i = 0; i < mNextRequests.size(); i++) {
4780 auto& nextRequest = mNextRequests.editItemAt(i);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004781 sp<CaptureRequest> captureRequest = nextRequest.captureRequest;
Emilian Peevf4816702020-04-03 15:44:51 -07004782 camera_capture_request_t* halRequest = &nextRequest.halRequest;
4783 Vector<camera_stream_buffer_t>* outputBuffers = &nextRequest.outputBuffers;
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004784
4785 // Prepare a request to HAL
4786 halRequest->frame_number = captureRequest->mResultExtras.frameNumber;
4787
4788 // Insert any queued triggers (before metadata is locked)
4789 status_t res = insertTriggers(captureRequest);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004790 if (res < 0) {
4791 SET_ERR("RequestThread: Unable to insert triggers "
4792 "(capture request %d, HAL device: %s (%d)",
4793 halRequest->frame_number, strerror(-res), res);
4794 return INVALID_OPERATION;
4795 }
Eino-Ville Talvala7b8a1fd2018-05-22 15:30:35 -07004796
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004797 int triggerCount = res;
4798 bool triggersMixedIn = (triggerCount > 0 || mPrevTriggers > 0);
4799 mPrevTriggers = triggerCount;
4800
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08004801 bool rotateAndCropChanged = overrideAutoRotateAndCrop(captureRequest);
Eino-Ville Talvala305cec62020-11-12 14:18:17 -08004802 bool testPatternChanged = overrideTestPattern(captureRequest);
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08004803
Eino-Ville Talvala305cec62020-11-12 14:18:17 -08004804 // If the request is the same as last, or we had triggers now or last time or
4805 // changing overrides this time
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08004806 bool newRequest =
Eino-Ville Talvala305cec62020-11-12 14:18:17 -08004807 (mPrevRequest != captureRequest || triggersMixedIn ||
4808 rotateAndCropChanged || testPatternChanged) &&
Yin-Chia Yehd07b11e2018-06-01 12:50:02 -07004809 // Request settings are all the same within one batch, so only treat the first
4810 // request in a batch as new
Zhijun He54c36822018-07-18 09:33:39 -07004811 !(batchedRequest && i > 0);
Emilian Peev00420d22018-02-05 21:33:13 +00004812 if (newRequest) {
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08004813 std::set<std::string> cameraIdsWithZoom;
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004814 /**
4815 * HAL workaround:
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -04004816 * Insert a fake trigger ID if a trigger is set but no trigger ID is
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004817 */
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -04004818 res = addFakeTriggerIds(captureRequest);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004819 if (res != OK) {
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -04004820 SET_ERR("RequestThread: Unable to insert fake trigger IDs "
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004821 "(capture request %d, HAL device: %s (%d)",
4822 halRequest->frame_number, strerror(-res), res);
4823 return INVALID_OPERATION;
4824 }
4825
Eino-Ville Talvala7b8a1fd2018-05-22 15:30:35 -07004826 {
4827 // Correct metadata regions for distortion correction if enabled
4828 sp<Camera3Device> parent = mParent.promote();
4829 if (parent != nullptr) {
Shuzhen Wang4f6fa9d2019-03-29 10:40:35 -07004830 List<PhysicalCameraSettings>::iterator it;
4831 for (it = captureRequest->mSettingsList.begin();
4832 it != captureRequest->mSettingsList.end(); it++) {
4833 if (parent->mDistortionMappers.find(it->cameraId) ==
4834 parent->mDistortionMappers.end()) {
4835 continue;
4836 }
Shuzhen Wangd1d051a2020-08-20 15:42:23 -07004837
4838 if (!captureRequest->mDistortionCorrectionUpdated) {
4839 res = parent->mDistortionMappers[it->cameraId].correctCaptureRequest(
4840 &(it->metadata));
4841 if (res != OK) {
4842 SET_ERR("RequestThread: Unable to correct capture requests "
4843 "for lens distortion for request %d: %s (%d)",
4844 halRequest->frame_number, strerror(-res), res);
4845 return INVALID_OPERATION;
4846 }
4847 captureRequest->mDistortionCorrectionUpdated = true;
Shuzhen Wang4f6fa9d2019-03-29 10:40:35 -07004848 }
Eino-Ville Talvala7b8a1fd2018-05-22 15:30:35 -07004849 }
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08004850
4851 for (it = captureRequest->mSettingsList.begin();
4852 it != captureRequest->mSettingsList.end(); it++) {
4853 if (parent->mZoomRatioMappers.find(it->cameraId) ==
4854 parent->mZoomRatioMappers.end()) {
4855 continue;
4856 }
4857
Shuzhen Wangd1d051a2020-08-20 15:42:23 -07004858 if (!captureRequest->mZoomRatioIs1x) {
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08004859 cameraIdsWithZoom.insert(it->cameraId);
4860 }
4861
Shuzhen Wangd1d051a2020-08-20 15:42:23 -07004862 if (!captureRequest->mZoomRatioUpdated) {
4863 res = parent->mZoomRatioMappers[it->cameraId].updateCaptureRequest(
4864 &(it->metadata));
4865 if (res != OK) {
4866 SET_ERR("RequestThread: Unable to correct capture requests "
4867 "for zoom ratio for request %d: %s (%d)",
4868 halRequest->frame_number, strerror(-res), res);
4869 return INVALID_OPERATION;
4870 }
4871 captureRequest->mZoomRatioUpdated = true;
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08004872 }
4873 }
Shuzhen Wangd1d051a2020-08-20 15:42:23 -07004874 if (captureRequest->mRotateAndCropAuto &&
4875 !captureRequest->mRotationAndCropUpdated) {
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08004876 for (it = captureRequest->mSettingsList.begin();
4877 it != captureRequest->mSettingsList.end(); it++) {
4878 auto mapper = parent->mRotateAndCropMappers.find(it->cameraId);
4879 if (mapper != parent->mRotateAndCropMappers.end()) {
4880 res = mapper->second.updateCaptureRequest(&(it->metadata));
4881 if (res != OK) {
4882 SET_ERR("RequestThread: Unable to correct capture requests "
4883 "for rotate-and-crop for request %d: %s (%d)",
4884 halRequest->frame_number, strerror(-res), res);
4885 return INVALID_OPERATION;
4886 }
4887 }
4888 }
Shuzhen Wangd1d051a2020-08-20 15:42:23 -07004889 captureRequest->mRotationAndCropUpdated = true;
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08004890 }
Eino-Ville Talvala7b8a1fd2018-05-22 15:30:35 -07004891 }
4892 }
4893
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004894 /**
4895 * The request should be presorted so accesses in HAL
4896 * are O(logn). Sidenote, sorting a sorted metadata is nop.
4897 */
Emilian Peevaebbe412018-01-15 13:53:24 +00004898 captureRequest->mSettingsList.begin()->metadata.sort();
4899 halRequest->settings = captureRequest->mSettingsList.begin()->metadata.getAndLock();
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004900 mPrevRequest = captureRequest;
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08004901 mPrevCameraIdsWithZoom = cameraIdsWithZoom;
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004902 ALOGVV("%s: Request settings are NEW", __FUNCTION__);
4903
4904 IF_ALOGV() {
4905 camera_metadata_ro_entry_t e = camera_metadata_ro_entry_t();
4906 find_camera_metadata_ro_entry(
4907 halRequest->settings,
4908 ANDROID_CONTROL_AF_TRIGGER,
4909 &e
4910 );
4911 if (e.count > 0) {
4912 ALOGV("%s: Request (frame num %d) had AF trigger 0x%x",
4913 __FUNCTION__,
4914 halRequest->frame_number,
4915 e.data.u8[0]);
4916 }
4917 }
4918 } else {
4919 // leave request.settings NULL to indicate 'reuse latest given'
4920 ALOGVV("%s: Request settings are REUSED",
4921 __FUNCTION__);
4922 }
4923
Emilian Peevaebbe412018-01-15 13:53:24 +00004924 if (captureRequest->mSettingsList.size() > 1) {
4925 halRequest->num_physcam_settings = captureRequest->mSettingsList.size() - 1;
4926 halRequest->physcam_id = new const char* [halRequest->num_physcam_settings];
Emilian Peev00420d22018-02-05 21:33:13 +00004927 if (newRequest) {
4928 halRequest->physcam_settings =
4929 new const camera_metadata* [halRequest->num_physcam_settings];
4930 } else {
4931 halRequest->physcam_settings = nullptr;
4932 }
Emilian Peevaebbe412018-01-15 13:53:24 +00004933 auto it = ++captureRequest->mSettingsList.begin();
4934 size_t i = 0;
4935 for (; it != captureRequest->mSettingsList.end(); it++, i++) {
4936 halRequest->physcam_id[i] = it->cameraId.c_str();
Emilian Peev00420d22018-02-05 21:33:13 +00004937 if (newRequest) {
4938 it->metadata.sort();
4939 halRequest->physcam_settings[i] = it->metadata.getAndLock();
4940 }
Emilian Peevaebbe412018-01-15 13:53:24 +00004941 }
4942 }
4943
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004944 uint32_t totalNumBuffers = 0;
4945
4946 // Fill in buffers
4947 if (captureRequest->mInputStream != NULL) {
4948 halRequest->input_buffer = &captureRequest->mInputBuffer;
Shuzhen Wang83bff122020-11-20 15:51:39 -08004949
4950 halRequest->input_width = captureRequest->mInputBufferSize.width;
4951 halRequest->input_height = captureRequest->mInputBufferSize.height;
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004952 totalNumBuffers += 1;
4953 } else {
4954 halRequest->input_buffer = NULL;
4955 }
4956
Emilian Peevf4816702020-04-03 15:44:51 -07004957 outputBuffers->insertAt(camera_stream_buffer_t(), 0,
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004958 captureRequest->mOutputStreams.size());
4959 halRequest->output_buffers = outputBuffers->array();
Shuzhen Wang99080502021-03-07 21:08:20 -08004960 std::set<std::set<String8>> requestedPhysicalCameras;
Yin-Chia Yehb3a80b12018-09-04 12:13:05 -07004961
4962 sp<Camera3Device> parent = mParent.promote();
4963 if (parent == NULL) {
4964 // Should not happen, and nowhere to send errors to, so just log it
4965 CLOGE("RequestThread: Parent is gone");
4966 return INVALID_OPERATION;
4967 }
4968 nsecs_t waitDuration = kBaseGetBufferWait + parent->getExpectedInFlightDuration();
4969
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004970 SurfaceMap uniqueSurfaceIdMap;
Shuzhen Wang4a472662017-02-26 23:29:04 -08004971 for (size_t j = 0; j < captureRequest->mOutputStreams.size(); j++) {
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004972 sp<Camera3OutputStreamInterface> outputStream =
4973 captureRequest->mOutputStreams.editItemAt(j);
4974 int streamId = outputStream->getId();
Chien-Yu Chenc66969b2016-05-19 16:37:51 -07004975
4976 // Prepare video buffers for high speed recording on the first video request.
4977 if (mPrepareVideoStream && outputStream->isVideoStream()) {
4978 // Only try to prepare video stream on the first video request.
4979 mPrepareVideoStream = false;
4980
Shuzhen Wangb3a0fb52018-09-13 17:24:08 -07004981 res = outputStream->startPrepare(Camera3StreamInterface::ALLOCATE_PIPELINE_MAX,
4982 false /*blockRequest*/);
Chien-Yu Chenc66969b2016-05-19 16:37:51 -07004983 while (res == NOT_ENOUGH_DATA) {
4984 res = outputStream->prepareNextBuffer();
4985 }
4986 if (res != OK) {
4987 ALOGW("%s: Preparing video buffers for high speed failed: %s (%d)",
4988 __FUNCTION__, strerror(-res), res);
4989 outputStream->cancelPrepare();
4990 }
4991 }
4992
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004993 std::vector<size_t> uniqueSurfaceIds;
4994 res = outputStream->getUniqueSurfaceIds(
4995 captureRequest->mOutputSurfaces[streamId],
4996 &uniqueSurfaceIds);
4997 // INVALID_OPERATION is normal output for streams not supporting surfaceIds
4998 if (res != OK && res != INVALID_OPERATION) {
4999 ALOGE("%s: failed to query stream %d unique surface IDs",
5000 __FUNCTION__, streamId);
5001 return res;
5002 }
5003 if (res == OK) {
5004 uniqueSurfaceIdMap.insert({streamId, std::move(uniqueSurfaceIds)});
5005 }
5006
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07005007 if (mUseHalBufManager) {
Yin-Chia Yeh110342b2018-11-19 11:47:46 -08005008 if (outputStream->isAbandoned()) {
Yin-Chia Yeha1b56c82019-03-27 15:50:39 -07005009 ALOGV("%s: stream %d is abandoned, skipping request", __FUNCTION__, streamId);
Yin-Chia Yeh110342b2018-11-19 11:47:46 -08005010 return TIMED_OUT;
5011 }
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07005012 // HAL will request buffer through requestStreamBuffer API
Emilian Peevf4816702020-04-03 15:44:51 -07005013 camera_stream_buffer_t& buffer = outputBuffers->editItemAt(j);
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07005014 buffer.stream = outputStream->asHalStream();
5015 buffer.buffer = nullptr;
Emilian Peevf4816702020-04-03 15:44:51 -07005016 buffer.status = CAMERA_BUFFER_STATUS_OK;
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07005017 buffer.acquire_fence = -1;
5018 buffer.release_fence = -1;
Emilian Peevf0348ae2021-01-13 13:39:45 -08005019 // Mark the output stream as unpreparable to block clients from calling
5020 // 'prepare' after this request reaches CameraHal and before the respective
5021 // buffers are requested.
5022 outputStream->markUnpreparable();
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07005023 } else {
5024 res = outputStream->getBuffer(&outputBuffers->editItemAt(j),
5025 waitDuration,
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07005026 captureRequest->mOutputSurfaces[streamId]);
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07005027 if (res != OK) {
5028 // Can't get output buffer from gralloc queue - this could be due to
5029 // abandoned queue or other consumer misbehavior, so not a fatal
5030 // error
Yin-Chia Yeha1b56c82019-03-27 15:50:39 -07005031 ALOGV("RequestThread: Can't get output buffer, skipping request:"
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07005032 " %s (%d)", strerror(-res), res);
5033
5034 return TIMED_OUT;
5035 }
Chien-Yu Chen85a64552015-08-28 15:46:12 -07005036 }
Shuzhen Wang68ac7ad2019-01-30 14:03:28 -08005037
5038 {
5039 sp<Camera3Device> parent = mParent.promote();
5040 if (parent != nullptr) {
5041 const String8& streamCameraId = outputStream->getPhysicalCameraId();
5042 for (const auto& settings : captureRequest->mSettingsList) {
5043 if ((streamCameraId.isEmpty() &&
5044 parent->getId() == settings.cameraId.c_str()) ||
5045 streamCameraId == settings.cameraId.c_str()) {
5046 outputStream->fireBufferRequestForFrameNumber(
5047 captureRequest->mResultExtras.frameNumber,
5048 settings.metadata);
5049 }
5050 }
5051 }
5052 }
Shuzhen Wang0129d522016-10-30 22:43:41 -07005053
Shuzhen Wang5c22c152017-12-31 17:12:25 -08005054 String8 physicalCameraId = outputStream->getPhysicalCameraId();
Shuzhen Wang99080502021-03-07 21:08:20 -08005055 int32_t streamGroupId = outputStream->getHalStreamGroupId();
5056 if (streamGroupId != -1 && mGroupIdPhysicalCameraMap.count(streamGroupId) == 1) {
5057 requestedPhysicalCameras.insert(mGroupIdPhysicalCameraMap[streamGroupId]);
5058 } else if (!physicalCameraId.isEmpty()) {
5059 requestedPhysicalCameras.insert(std::set<String8>({physicalCameraId}));
Shuzhen Wang5c22c152017-12-31 17:12:25 -08005060 }
5061 halRequest->num_output_buffers++;
Chien-Yu Chen85a64552015-08-28 15:46:12 -07005062 }
5063 totalNumBuffers += halRequest->num_output_buffers;
5064
5065 // Log request in the in-flight queue
Shuzhen Wang4a472662017-02-26 23:29:04 -08005066 // If this request list is for constrained high speed recording (not
5067 // preview), and the current request is not the last one in the batch,
5068 // do not send callback to the app.
5069 bool hasCallback = true;
Yin-Chia Yehd07b11e2018-06-01 12:50:02 -07005070 if (batchedRequest && i != mNextRequests.size()-1) {
Shuzhen Wang4a472662017-02-26 23:29:04 -08005071 hasCallback = false;
5072 }
Emilian Peev9dd21f42018-08-03 13:39:29 +01005073 bool isStillCapture = false;
Shuzhen Wang26abaf42018-08-28 15:41:20 -07005074 bool isZslCapture = false;
Yin-Chia Yehf7057ca2020-11-16 14:11:40 -08005075 const camera_metadata_t* settings = halRequest->settings;
5076 bool shouldUnlockSettings = false;
5077 if (settings == nullptr) {
5078 shouldUnlockSettings = true;
5079 settings = captureRequest->mSettingsList.begin()->metadata.getAndLock();
5080 }
Emilian Peev9dd21f42018-08-03 13:39:29 +01005081 if (!mNextRequests[0].captureRequest->mSettingsList.begin()->metadata.isEmpty()) {
5082 camera_metadata_ro_entry_t e = camera_metadata_ro_entry_t();
Yin-Chia Yehf7057ca2020-11-16 14:11:40 -08005083 find_camera_metadata_ro_entry(settings, ANDROID_CONTROL_CAPTURE_INTENT, &e);
Emilian Peev9dd21f42018-08-03 13:39:29 +01005084 if ((e.count > 0) && (e.data.u8[0] == ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE)) {
5085 isStillCapture = true;
5086 ATRACE_ASYNC_BEGIN("still capture", mNextRequests[i].halRequest.frame_number);
5087 }
Shuzhen Wang26abaf42018-08-28 15:41:20 -07005088
Emilian Peevaf8416e2021-02-04 17:52:43 -08005089 e = camera_metadata_ro_entry_t();
Yin-Chia Yehf7057ca2020-11-16 14:11:40 -08005090 find_camera_metadata_ro_entry(settings, ANDROID_CONTROL_ENABLE_ZSL, &e);
Shuzhen Wang26abaf42018-08-28 15:41:20 -07005091 if ((e.count > 0) && (e.data.u8[0] == ANDROID_CONTROL_ENABLE_ZSL_TRUE)) {
5092 isZslCapture = true;
5093 }
Emilian Peev9dd21f42018-08-03 13:39:29 +01005094 }
Chien-Yu Chen85a64552015-08-28 15:46:12 -07005095 res = parent->registerInFlight(halRequest->frame_number,
5096 totalNumBuffers, captureRequest->mResultExtras,
5097 /*hasInput*/halRequest->input_buffer != NULL,
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07005098 hasCallback,
Yin-Chia Yehf7057ca2020-11-16 14:11:40 -08005099 calculateMaxExpectedDuration(settings),
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08005100 requestedPhysicalCameras, isStillCapture, isZslCapture,
5101 captureRequest->mRotateAndCropAuto, mPrevCameraIdsWithZoom,
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07005102 (mUseHalBufManager) ? uniqueSurfaceIdMap :
Shuzhen Wang316781a2020-08-18 18:11:01 -07005103 SurfaceMap{}, captureRequest->mRequestTimeNs);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07005104 ALOGVV("%s: registered in flight requestId = %" PRId32 ", frameNumber = %" PRId64
5105 ", burstId = %" PRId32 ".",
5106 __FUNCTION__,
5107 captureRequest->mResultExtras.requestId, captureRequest->mResultExtras.frameNumber,
5108 captureRequest->mResultExtras.burstId);
Yin-Chia Yehf7057ca2020-11-16 14:11:40 -08005109
5110 if (shouldUnlockSettings) {
5111 captureRequest->mSettingsList.begin()->metadata.unlock(settings);
5112 }
5113
Chien-Yu Chen85a64552015-08-28 15:46:12 -07005114 if (res != OK) {
5115 SET_ERR("RequestThread: Unable to register new in-flight request:"
5116 " %s (%d)", strerror(-res), res);
5117 return INVALID_OPERATION;
5118 }
5119 }
5120
5121 return OK;
5122}
5123
Igor Murashkin1e479c02013-09-06 16:55:14 -07005124CameraMetadata Camera3Device::RequestThread::getLatestRequest() const {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005125 ATRACE_CALL();
Igor Murashkin1e479c02013-09-06 16:55:14 -07005126 Mutex::Autolock al(mLatestRequestMutex);
5127
5128 ALOGV("RequestThread::%s", __FUNCTION__);
5129
5130 return mLatestRequest;
5131}
5132
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005133bool Camera3Device::RequestThread::isStreamPending(
5134 sp<Camera3StreamInterface>& stream) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005135 ATRACE_CALL();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005136 Mutex::Autolock l(mRequestLock);
5137
Chien-Yu Chen85a64552015-08-28 15:46:12 -07005138 for (const auto& nextRequest : mNextRequests) {
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07005139 if (!nextRequest.submitted) {
5140 for (const auto& s : nextRequest.captureRequest->mOutputStreams) {
5141 if (stream == s) return true;
5142 }
5143 if (stream == nextRequest.captureRequest->mInputStream) return true;
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07005144 }
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07005145 }
5146
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005147 for (const auto& request : mRequestQueue) {
5148 for (const auto& s : request->mOutputStreams) {
5149 if (stream == s) return true;
5150 }
5151 if (stream == request->mInputStream) return true;
5152 }
5153
5154 for (const auto& request : mRepeatingRequests) {
5155 for (const auto& s : request->mOutputStreams) {
5156 if (stream == s) return true;
5157 }
5158 if (stream == request->mInputStream) return true;
5159 }
5160
5161 return false;
5162}
Jianing Weicb0652e2014-03-12 18:29:36 -07005163
Emilian Peev40ead602017-09-26 15:46:36 +01005164bool Camera3Device::RequestThread::isOutputSurfacePending(int streamId, size_t surfaceId) {
5165 ATRACE_CALL();
5166 Mutex::Autolock l(mRequestLock);
5167
5168 for (const auto& nextRequest : mNextRequests) {
5169 for (const auto& s : nextRequest.captureRequest->mOutputSurfaces) {
5170 if (s.first == streamId) {
5171 const auto &it = std::find(s.second.begin(), s.second.end(), surfaceId);
5172 if (it != s.second.end()) {
5173 return true;
5174 }
5175 }
5176 }
5177 }
5178
5179 for (const auto& request : mRequestQueue) {
5180 for (const auto& s : request->mOutputSurfaces) {
5181 if (s.first == streamId) {
5182 const auto &it = std::find(s.second.begin(), s.second.end(), surfaceId);
5183 if (it != s.second.end()) {
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07005184 return true;
Emilian Peev40ead602017-09-26 15:46:36 +01005185 }
5186 }
5187 }
5188 }
5189
5190 for (const auto& request : mRepeatingRequests) {
5191 for (const auto& s : request->mOutputSurfaces) {
5192 if (s.first == streamId) {
5193 const auto &it = std::find(s.second.begin(), s.second.end(), surfaceId);
5194 if (it != s.second.end()) {
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07005195 return true;
Emilian Peev40ead602017-09-26 15:46:36 +01005196 }
5197 }
5198 }
5199 }
5200
5201 return false;
5202}
5203
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07005204void Camera3Device::RequestThread::signalPipelineDrain(const std::vector<int>& streamIds) {
5205 if (!mUseHalBufManager) {
5206 ALOGE("%s called for camera device not supporting HAL buffer management", __FUNCTION__);
5207 return;
5208 }
5209
5210 Mutex::Autolock pl(mPauseLock);
5211 if (mPaused) {
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005212 mInterface->signalPipelineDrain(streamIds);
5213 return;
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07005214 }
5215 // If request thread is still busy, wait until paused then notify HAL
5216 mNotifyPipelineDrain = true;
5217 mStreamIdsToBeDrained = streamIds;
5218}
5219
Yin-Chia Yehe52b8fa2020-07-28 00:17:58 -07005220void Camera3Device::RequestThread::resetPipelineDrain() {
5221 Mutex::Autolock pl(mPauseLock);
5222 mNotifyPipelineDrain = false;
5223 mStreamIdsToBeDrained.clear();
5224}
5225
Emilian Peevc0fe54c2020-03-11 14:05:07 -07005226void Camera3Device::RequestThread::clearPreviousRequest() {
5227 Mutex::Autolock l(mRequestLock);
5228 mPrevRequest.clear();
5229}
5230
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005231status_t Camera3Device::RequestThread::switchToOffline(
5232 const std::vector<int32_t>& streamsToKeep,
5233 /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005234 /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
5235 /*out*/camera3::BufferRecords* bufferRecords) {
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005236 Mutex::Autolock l(mRequestLock);
5237 clearRepeatingRequestsLocked(/*lastFrameNumber*/nullptr);
5238
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005239 // Wait until request thread is fully stopped
5240 // TBD: check if request thread is being paused by other APIs (shouldn't be)
5241
5242 // We could also check for mRepeatingRequests.empty(), but the API interface
5243 // is serialized by Camera3Device::mInterfaceLock so no one should be able to submit any
5244 // new requests during the call; hence skip that check.
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005245 bool queueEmpty = mNextRequests.empty() && mRequestQueue.empty();
5246 while (!queueEmpty) {
5247 status_t res = mRequestSubmittedSignal.waitRelative(mRequestLock, kRequestSubmitTimeout);
5248 if (res == TIMED_OUT) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005249 ALOGE("%s: request thread failed to submit one request within timeout!", __FUNCTION__);
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005250 return res;
5251 } else if (res != OK) {
5252 ALOGE("%s: request thread failed to submit a request: %s (%d)!",
5253 __FUNCTION__, strerror(-res), res);
5254 return res;
5255 }
5256 queueEmpty = mNextRequests.empty() && mRequestQueue.empty();
5257 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005258
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005259 return mInterface->switchToOffline(
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005260 streamsToKeep, offlineSessionInfo, offlineSession, bufferRecords);
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005261}
5262
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08005263status_t Camera3Device::RequestThread::setRotateAndCropAutoBehavior(
5264 camera_metadata_enum_android_scaler_rotate_and_crop_t rotateAndCropValue) {
5265 ATRACE_CALL();
5266 Mutex::Autolock l(mTriggerMutex);
5267 if (rotateAndCropValue == ANDROID_SCALER_ROTATE_AND_CROP_AUTO) {
5268 return BAD_VALUE;
5269 }
5270 mRotateAndCropOverride = rotateAndCropValue;
5271 return OK;
5272}
5273
Eino-Ville Talvala11afe4f2021-05-27 14:45:31 -07005274status_t Camera3Device::RequestThread::setCameraMute(int32_t muteMode) {
Eino-Ville Talvala305cec62020-11-12 14:18:17 -08005275 ATRACE_CALL();
5276 Mutex::Autolock l(mTriggerMutex);
Eino-Ville Talvala11afe4f2021-05-27 14:45:31 -07005277 if (muteMode != mCameraMute) {
5278 mCameraMute = muteMode;
Eino-Ville Talvala305cec62020-11-12 14:18:17 -08005279 mCameraMuteChanged = true;
5280 }
5281 return OK;
5282}
5283
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07005284nsecs_t Camera3Device::getExpectedInFlightDuration() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005285 ATRACE_CALL();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005286 std::lock_guard<std::mutex> l(mInFlightLock);
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07005287 return mExpectedInflightDuration > kMinInflightDuration ?
5288 mExpectedInflightDuration : kMinInflightDuration;
5289}
5290
Emilian Peevaebbe412018-01-15 13:53:24 +00005291void Camera3Device::RequestThread::cleanupPhysicalSettings(sp<CaptureRequest> request,
Emilian Peevf4816702020-04-03 15:44:51 -07005292 camera_capture_request_t *halRequest) {
Emilian Peevaebbe412018-01-15 13:53:24 +00005293 if ((request == nullptr) || (halRequest == nullptr)) {
5294 ALOGE("%s: Invalid request!", __FUNCTION__);
5295 return;
5296 }
5297
5298 if (halRequest->num_physcam_settings > 0) {
5299 if (halRequest->physcam_id != nullptr) {
5300 delete [] halRequest->physcam_id;
5301 halRequest->physcam_id = nullptr;
5302 }
5303 if (halRequest->physcam_settings != nullptr) {
5304 auto it = ++(request->mSettingsList.begin());
5305 size_t i = 0;
5306 for (; it != request->mSettingsList.end(); it++, i++) {
5307 it->metadata.unlock(halRequest->physcam_settings[i]);
5308 }
5309 delete [] halRequest->physcam_settings;
5310 halRequest->physcam_settings = nullptr;
5311 }
5312 }
5313}
5314
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07005315void Camera3Device::RequestThread::cleanUpFailedRequests(bool sendRequestError) {
5316 if (mNextRequests.empty()) {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07005317 return;
5318 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005319
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07005320 for (auto& nextRequest : mNextRequests) {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07005321 // Skip the ones that have been submitted successfully.
5322 if (nextRequest.submitted) {
5323 continue;
5324 }
5325
5326 sp<CaptureRequest> captureRequest = nextRequest.captureRequest;
Emilian Peevf4816702020-04-03 15:44:51 -07005327 camera_capture_request_t* halRequest = &nextRequest.halRequest;
5328 Vector<camera_stream_buffer_t>* outputBuffers = &nextRequest.outputBuffers;
Chien-Yu Chen85a64552015-08-28 15:46:12 -07005329
5330 if (halRequest->settings != NULL) {
Emilian Peevaebbe412018-01-15 13:53:24 +00005331 captureRequest->mSettingsList.begin()->metadata.unlock(halRequest->settings);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07005332 }
5333
Emilian Peevaebbe412018-01-15 13:53:24 +00005334 cleanupPhysicalSettings(captureRequest, halRequest);
5335
Chien-Yu Chen85a64552015-08-28 15:46:12 -07005336 if (captureRequest->mInputStream != NULL) {
Emilian Peevf4816702020-04-03 15:44:51 -07005337 captureRequest->mInputBuffer.status = CAMERA_BUFFER_STATUS_ERROR;
Chien-Yu Chen85a64552015-08-28 15:46:12 -07005338 captureRequest->mInputStream->returnInputBuffer(captureRequest->mInputBuffer);
5339 }
5340
Yin-Chia Yeh21cb47b2019-01-18 15:08:17 -08005341 // No output buffer can be returned when using HAL buffer manager
5342 if (!mUseHalBufManager) {
5343 for (size_t i = 0; i < halRequest->num_output_buffers; i++) {
5344 //Buffers that failed processing could still have
5345 //valid acquire fence.
5346 int acquireFence = (*outputBuffers)[i].acquire_fence;
5347 if (0 <= acquireFence) {
5348 close(acquireFence);
5349 outputBuffers->editItemAt(i).acquire_fence = -1;
5350 }
Emilian Peevf4816702020-04-03 15:44:51 -07005351 outputBuffers->editItemAt(i).status = CAMERA_BUFFER_STATUS_ERROR;
Yin-Chia Yeh21cb47b2019-01-18 15:08:17 -08005352 captureRequest->mOutputStreams.editItemAt(i)->returnBuffer((*outputBuffers)[i], 0,
5353 /*timestampIncreasing*/true, std::vector<size_t> (),
5354 captureRequest->mResultExtras.frameNumber);
Emilian Peevc58cf4c2017-05-11 17:23:41 +01005355 }
Chien-Yu Chen85a64552015-08-28 15:46:12 -07005356 }
5357
5358 if (sendRequestError) {
5359 Mutex::Autolock l(mRequestLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005360 sp<NotificationListener> listener = mListener.promote();
5361 if (listener != NULL) {
5362 listener->notifyError(
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08005363 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
Chien-Yu Chen85a64552015-08-28 15:46:12 -07005364 captureRequest->mResultExtras);
5365 }
5366 }
Shuzhen Wangcadb3302016-11-04 14:17:56 -07005367
5368 // Remove yet-to-be submitted inflight request from inflightMap
5369 {
5370 sp<Camera3Device> parent = mParent.promote();
5371 if (parent != NULL) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005372 std::lock_guard<std::mutex> l(parent->mInFlightLock);
Shuzhen Wangcadb3302016-11-04 14:17:56 -07005373 ssize_t idx = parent->mInFlightMap.indexOfKey(captureRequest->mResultExtras.frameNumber);
5374 if (idx >= 0) {
5375 ALOGV("%s: Remove inflight request from queue: frameNumber %" PRId64,
5376 __FUNCTION__, captureRequest->mResultExtras.frameNumber);
5377 parent->removeInFlightMapEntryLocked(idx);
5378 }
5379 }
5380 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005381 }
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07005382
5383 Mutex::Autolock l(mRequestLock);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07005384 mNextRequests.clear();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005385}
5386
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07005387void Camera3Device::RequestThread::waitForNextRequestBatch() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005388 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005389 // Optimized a bit for the simple steady-state case (single repeating
5390 // request), to avoid putting that request in the queue temporarily.
5391 Mutex::Autolock l(mRequestLock);
5392
Chien-Yu Chen85a64552015-08-28 15:46:12 -07005393 assert(mNextRequests.empty());
5394
5395 NextRequest nextRequest;
5396 nextRequest.captureRequest = waitForNextRequestLocked();
5397 if (nextRequest.captureRequest == nullptr) {
5398 return;
5399 }
5400
Emilian Peevf4816702020-04-03 15:44:51 -07005401 nextRequest.halRequest = camera_capture_request_t();
Chien-Yu Chen85a64552015-08-28 15:46:12 -07005402 nextRequest.submitted = false;
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07005403 mNextRequests.add(nextRequest);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07005404
5405 // Wait for additional requests
5406 const size_t batchSize = nextRequest.captureRequest->mBatchSize;
5407
5408 for (size_t i = 1; i < batchSize; i++) {
5409 NextRequest additionalRequest;
5410 additionalRequest.captureRequest = waitForNextRequestLocked();
5411 if (additionalRequest.captureRequest == nullptr) {
5412 break;
5413 }
5414
Emilian Peevf4816702020-04-03 15:44:51 -07005415 additionalRequest.halRequest = camera_capture_request_t();
Chien-Yu Chen85a64552015-08-28 15:46:12 -07005416 additionalRequest.submitted = false;
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07005417 mNextRequests.add(additionalRequest);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07005418 }
5419
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07005420 if (mNextRequests.size() < batchSize) {
Eino-Ville Talvalad309fb92015-11-25 12:12:45 -08005421 ALOGE("RequestThread: only get %zu out of %zu requests. Skipping requests.",
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07005422 mNextRequests.size(), batchSize);
5423 cleanUpFailedRequests(/*sendRequestError*/true);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07005424 }
5425
5426 return;
5427}
5428
5429sp<Camera3Device::CaptureRequest>
5430 Camera3Device::RequestThread::waitForNextRequestLocked() {
5431 status_t res;
5432 sp<CaptureRequest> nextRequest;
5433
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005434 while (mRequestQueue.empty()) {
5435 if (!mRepeatingRequests.empty()) {
5436 // Always atomically enqueue all requests in a repeating request
5437 // list. Guarantees a complete in-sequence set of captures to
5438 // application.
5439 const RequestList &requests = mRepeatingRequests;
Shuzhen Wang316781a2020-08-18 18:11:01 -07005440 if (mFirstRepeating) {
5441 mFirstRepeating = false;
5442 } else {
5443 for (auto& request : requests) {
5444 // For repeating requests, override timestamp request using
5445 // the time a request is inserted into the request queue,
5446 // because the original repeating request will have an old
5447 // fixed timestamp.
5448 request->mRequestTimeNs = systemTime();
5449 }
5450 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005451 RequestList::const_iterator firstRequest =
5452 requests.begin();
5453 nextRequest = *firstRequest;
5454 mRequestQueue.insert(mRequestQueue.end(),
5455 ++firstRequest,
5456 requests.end());
5457 // No need to wait any longer
Jianing Weicb0652e2014-03-12 18:29:36 -07005458
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07005459 mRepeatingLastFrameNumber = mFrameNumber + requests.size() - 1;
Jianing Weicb0652e2014-03-12 18:29:36 -07005460
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005461 break;
5462 }
5463
5464 res = mRequestSignal.waitRelative(mRequestLock, kRequestTimeout);
5465
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005466 if ((mRequestQueue.empty() && mRepeatingRequests.empty()) ||
5467 exitPending()) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005468 Mutex::Autolock pl(mPauseLock);
5469 if (mPaused == false) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005470 ALOGV("%s: RequestThread: Going idle", __FUNCTION__);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005471 mPaused = true;
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07005472 if (mNotifyPipelineDrain) {
5473 mInterface->signalPipelineDrain(mStreamIdsToBeDrained);
5474 mNotifyPipelineDrain = false;
5475 mStreamIdsToBeDrained.clear();
5476 }
Yin-Chia Yehc300a072019-02-13 14:56:57 -08005477 // Let the tracker know
5478 sp<StatusTracker> statusTracker = mStatusTracker.promote();
5479 if (statusTracker != 0) {
5480 statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);
5481 }
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005482 sp<Camera3Device> parent = mParent.promote();
5483 if (parent != nullptr) {
5484 parent->mRequestBufferSM.onRequestThreadPaused();
5485 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005486 }
5487 // Stop waiting for now and let thread management happen
5488 return NULL;
5489 }
5490 }
5491
5492 if (nextRequest == NULL) {
5493 // Don't have a repeating request already in hand, so queue
5494 // must have an entry now.
5495 RequestList::iterator firstRequest =
5496 mRequestQueue.begin();
5497 nextRequest = *firstRequest;
5498 mRequestQueue.erase(firstRequest);
Shuzhen Wang9d066012016-09-30 11:30:20 -07005499 if (mRequestQueue.empty() && !nextRequest->mRepeating) {
5500 sp<NotificationListener> listener = mListener.promote();
5501 if (listener != NULL) {
5502 listener->notifyRequestQueueEmpty();
5503 }
5504 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005505 }
5506
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07005507 // In case we've been unpaused by setPaused clearing mDoPause, need to
5508 // update internal pause state (capture/setRepeatingRequest unpause
5509 // directly).
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005510 Mutex::Autolock pl(mPauseLock);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005511 if (mPaused) {
5512 ALOGV("%s: RequestThread: Unpaused", __FUNCTION__);
5513 sp<StatusTracker> statusTracker = mStatusTracker.promote();
5514 if (statusTracker != 0) {
5515 statusTracker->markComponentActive(mStatusId);
5516 }
5517 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005518 mPaused = false;
5519
5520 // Check if we've reconfigured since last time, and reset the preview
5521 // request if so. Can't use 'NULL request == repeat' across configure calls.
5522 if (mReconfigured) {
5523 mPrevRequest.clear();
5524 mReconfigured = false;
5525 }
5526
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07005527 if (nextRequest != NULL) {
5528 nextRequest->mResultExtras.frameNumber = mFrameNumber++;
Yin-Chia Yehc00a25c2014-08-21 14:27:44 -07005529 nextRequest->mResultExtras.afTriggerId = mCurrentAfTriggerId;
5530 nextRequest->mResultExtras.precaptureTriggerId = mCurrentPreCaptureTriggerId;
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07005531
5532 // Since RequestThread::clear() removes buffers from the input stream,
5533 // get the right buffer here before unlocking mRequestLock
5534 if (nextRequest->mInputStream != NULL) {
Shuzhen Wang83bff122020-11-20 15:51:39 -08005535 res = nextRequest->mInputStream->getInputBuffer(&nextRequest->mInputBuffer,
5536 &nextRequest->mInputBufferSize);
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07005537 if (res != OK) {
5538 // Can't get input buffer from gralloc queue - this could be due to
5539 // disconnected queue or other producer misbehavior, so not a fatal
5540 // error
5541 ALOGE("%s: Can't get input buffer, skipping request:"
5542 " %s (%d)", __FUNCTION__, strerror(-res), res);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005543
5544 sp<NotificationListener> listener = mListener.promote();
5545 if (listener != NULL) {
5546 listener->notifyError(
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08005547 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07005548 nextRequest->mResultExtras);
5549 }
5550 return NULL;
5551 }
5552 }
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07005553 }
Chien-Yu Chend196d612015-06-22 19:49:01 -07005554
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005555 return nextRequest;
5556}
5557
5558bool Camera3Device::RequestThread::waitIfPaused() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005559 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005560 status_t res;
5561 Mutex::Autolock l(mPauseLock);
5562 while (mDoPause) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005563 if (mPaused == false) {
5564 mPaused = true;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005565 ALOGV("%s: RequestThread: Paused", __FUNCTION__);
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07005566 if (mNotifyPipelineDrain) {
5567 mInterface->signalPipelineDrain(mStreamIdsToBeDrained);
5568 mNotifyPipelineDrain = false;
5569 mStreamIdsToBeDrained.clear();
5570 }
Yin-Chia Yehc300a072019-02-13 14:56:57 -08005571 // Let the tracker know
5572 sp<StatusTracker> statusTracker = mStatusTracker.promote();
5573 if (statusTracker != 0) {
5574 statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);
5575 }
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005576 sp<Camera3Device> parent = mParent.promote();
5577 if (parent != nullptr) {
5578 parent->mRequestBufferSM.onRequestThreadPaused();
5579 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005580 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005581
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005582 res = mDoPauseSignal.waitRelative(mPauseLock, kRequestTimeout);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005583 if (res == TIMED_OUT || exitPending()) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005584 return true;
5585 }
5586 }
5587 // We don't set mPaused to false here, because waitForNextRequest needs
5588 // to further manage the paused state in case of starvation.
5589 return false;
5590}
5591
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07005592void Camera3Device::RequestThread::unpauseForNewRequests() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005593 ATRACE_CALL();
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07005594 // With work to do, mark thread as unpaused.
5595 // If paused by request (setPaused), don't resume, to avoid
5596 // extra signaling/waiting overhead to waitUntilPaused
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005597 mRequestSignal.signal();
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07005598 Mutex::Autolock p(mPauseLock);
5599 if (!mDoPause) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005600 ALOGV("%s: RequestThread: Going active", __FUNCTION__);
5601 if (mPaused) {
5602 sp<StatusTracker> statusTracker = mStatusTracker.promote();
5603 if (statusTracker != 0) {
5604 statusTracker->markComponentActive(mStatusId);
5605 }
5606 }
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07005607 mPaused = false;
5608 }
5609}
5610
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07005611void Camera3Device::RequestThread::setErrorState(const char *fmt, ...) {
5612 sp<Camera3Device> parent = mParent.promote();
5613 if (parent != NULL) {
5614 va_list args;
5615 va_start(args, fmt);
5616
5617 parent->setErrorStateV(fmt, args);
5618
5619 va_end(args);
5620 }
5621}
5622
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005623status_t Camera3Device::RequestThread::insertTriggers(
5624 const sp<CaptureRequest> &request) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005625 ATRACE_CALL();
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005626 Mutex::Autolock al(mTriggerMutex);
5627
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07005628 sp<Camera3Device> parent = mParent.promote();
5629 if (parent == NULL) {
5630 CLOGE("RequestThread: Parent is gone");
5631 return DEAD_OBJECT;
5632 }
5633
Emilian Peevaebbe412018-01-15 13:53:24 +00005634 CameraMetadata &metadata = request->mSettingsList.begin()->metadata;
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005635 size_t count = mTriggerMap.size();
5636
5637 for (size_t i = 0; i < count; ++i) {
5638 RequestTrigger trigger = mTriggerMap.valueAt(i);
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005639 uint32_t tag = trigger.metadataTag;
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07005640
5641 if (tag == ANDROID_CONTROL_AF_TRIGGER_ID || tag == ANDROID_CONTROL_AE_PRECAPTURE_ID) {
5642 bool isAeTrigger = (trigger.metadataTag == ANDROID_CONTROL_AE_PRECAPTURE_ID);
5643 uint32_t triggerId = static_cast<uint32_t>(trigger.entryValue);
Yin-Chia Yehc00a25c2014-08-21 14:27:44 -07005644 if (isAeTrigger) {
5645 request->mResultExtras.precaptureTriggerId = triggerId;
5646 mCurrentPreCaptureTriggerId = triggerId;
5647 } else {
5648 request->mResultExtras.afTriggerId = triggerId;
5649 mCurrentAfTriggerId = triggerId;
5650 }
Emilian Peev7e25e5e2017-04-07 15:48:49 +01005651 continue;
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07005652 }
5653
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005654 camera_metadata_entry entry = metadata.find(tag);
5655
5656 if (entry.count > 0) {
5657 /**
5658 * Already has an entry for this trigger in the request.
5659 * Rewrite it with our requested trigger value.
5660 */
5661 RequestTrigger oldTrigger = trigger;
5662
5663 oldTrigger.entryValue = entry.data.u8[0];
5664
5665 mTriggerReplacedMap.add(tag, oldTrigger);
5666 } else {
5667 /**
5668 * More typical, no trigger entry, so we just add it
5669 */
5670 mTriggerRemovedMap.add(tag, trigger);
5671 }
5672
5673 status_t res;
5674
5675 switch (trigger.getTagType()) {
5676 case TYPE_BYTE: {
5677 uint8_t entryValue = static_cast<uint8_t>(trigger.entryValue);
5678 res = metadata.update(tag,
5679 &entryValue,
5680 /*count*/1);
5681 break;
5682 }
5683 case TYPE_INT32:
5684 res = metadata.update(tag,
5685 &trigger.entryValue,
5686 /*count*/1);
5687 break;
5688 default:
5689 ALOGE("%s: Type not supported: 0x%x",
5690 __FUNCTION__,
5691 trigger.getTagType());
5692 return INVALID_OPERATION;
5693 }
5694
5695 if (res != OK) {
5696 ALOGE("%s: Failed to update request metadata with trigger tag %s"
5697 ", value %d", __FUNCTION__, trigger.getTagName(),
5698 trigger.entryValue);
5699 return res;
5700 }
5701
5702 ALOGV("%s: Mixed in trigger %s, value %d", __FUNCTION__,
5703 trigger.getTagName(),
5704 trigger.entryValue);
5705 }
5706
5707 mTriggerMap.clear();
5708
5709 return count;
5710}
5711
5712status_t Camera3Device::RequestThread::removeTriggers(
5713 const sp<CaptureRequest> &request) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005714 ATRACE_CALL();
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005715 Mutex::Autolock al(mTriggerMutex);
5716
Emilian Peevaebbe412018-01-15 13:53:24 +00005717 CameraMetadata &metadata = request->mSettingsList.begin()->metadata;
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005718
5719 /**
5720 * Replace all old entries with their old values.
5721 */
5722 for (size_t i = 0; i < mTriggerReplacedMap.size(); ++i) {
5723 RequestTrigger trigger = mTriggerReplacedMap.valueAt(i);
5724
5725 status_t res;
5726
5727 uint32_t tag = trigger.metadataTag;
5728 switch (trigger.getTagType()) {
5729 case TYPE_BYTE: {
5730 uint8_t entryValue = static_cast<uint8_t>(trigger.entryValue);
5731 res = metadata.update(tag,
5732 &entryValue,
5733 /*count*/1);
5734 break;
5735 }
5736 case TYPE_INT32:
5737 res = metadata.update(tag,
5738 &trigger.entryValue,
5739 /*count*/1);
5740 break;
5741 default:
5742 ALOGE("%s: Type not supported: 0x%x",
5743 __FUNCTION__,
5744 trigger.getTagType());
5745 return INVALID_OPERATION;
5746 }
5747
5748 if (res != OK) {
5749 ALOGE("%s: Failed to restore request metadata with trigger tag %s"
5750 ", trigger value %d", __FUNCTION__,
5751 trigger.getTagName(), trigger.entryValue);
5752 return res;
5753 }
5754 }
5755 mTriggerReplacedMap.clear();
5756
5757 /**
5758 * Remove all new entries.
5759 */
5760 for (size_t i = 0; i < mTriggerRemovedMap.size(); ++i) {
5761 RequestTrigger trigger = mTriggerRemovedMap.valueAt(i);
5762 status_t res = metadata.erase(trigger.metadataTag);
5763
5764 if (res != OK) {
5765 ALOGE("%s: Failed to erase metadata with trigger tag %s"
5766 ", trigger value %d", __FUNCTION__,
5767 trigger.getTagName(), trigger.entryValue);
5768 return res;
5769 }
5770 }
5771 mTriggerRemovedMap.clear();
5772
5773 return OK;
5774}
5775
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -04005776status_t Camera3Device::RequestThread::addFakeTriggerIds(
Eino-Ville Talvala2f876f92013-09-13 11:39:24 -07005777 const sp<CaptureRequest> &request) {
Eino-Ville Talvalad309fb92015-11-25 12:12:45 -08005778 // Trigger ID 0 had special meaning in the HAL2 spec, so avoid it here
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -04005779 static const int32_t fakeTriggerId = 1;
Eino-Ville Talvala2f876f92013-09-13 11:39:24 -07005780 status_t res;
5781
Emilian Peevaebbe412018-01-15 13:53:24 +00005782 CameraMetadata &metadata = request->mSettingsList.begin()->metadata;
Eino-Ville Talvala2f876f92013-09-13 11:39:24 -07005783
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -04005784 // If AF trigger is active, insert a fake AF trigger ID if none already
Eino-Ville Talvala2f876f92013-09-13 11:39:24 -07005785 // exists
5786 camera_metadata_entry afTrigger = metadata.find(ANDROID_CONTROL_AF_TRIGGER);
5787 camera_metadata_entry afId = metadata.find(ANDROID_CONTROL_AF_TRIGGER_ID);
5788 if (afTrigger.count > 0 &&
5789 afTrigger.data.u8[0] != ANDROID_CONTROL_AF_TRIGGER_IDLE &&
5790 afId.count == 0) {
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -04005791 res = metadata.update(ANDROID_CONTROL_AF_TRIGGER_ID, &fakeTriggerId, 1);
Eino-Ville Talvala2f876f92013-09-13 11:39:24 -07005792 if (res != OK) return res;
5793 }
5794
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -04005795 // If AE precapture trigger is active, insert a fake precapture trigger ID
Eino-Ville Talvala2f876f92013-09-13 11:39:24 -07005796 // if none already exists
5797 camera_metadata_entry pcTrigger =
5798 metadata.find(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER);
5799 camera_metadata_entry pcId = metadata.find(ANDROID_CONTROL_AE_PRECAPTURE_ID);
5800 if (pcTrigger.count > 0 &&
5801 pcTrigger.data.u8[0] != ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE &&
5802 pcId.count == 0) {
5803 res = metadata.update(ANDROID_CONTROL_AE_PRECAPTURE_ID,
Ivan Lozanoc0ad82f2020-07-30 09:32:57 -04005804 &fakeTriggerId, 1);
Eino-Ville Talvala2f876f92013-09-13 11:39:24 -07005805 if (res != OK) return res;
5806 }
5807
5808 return OK;
5809}
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005810
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08005811bool Camera3Device::RequestThread::overrideAutoRotateAndCrop(
5812 const sp<CaptureRequest> &request) {
5813 ATRACE_CALL();
5814
5815 if (request->mRotateAndCropAuto) {
5816 Mutex::Autolock l(mTriggerMutex);
5817 CameraMetadata &metadata = request->mSettingsList.begin()->metadata;
5818
5819 auto rotateAndCropEntry = metadata.find(ANDROID_SCALER_ROTATE_AND_CROP);
5820 if (rotateAndCropEntry.count > 0) {
5821 if (rotateAndCropEntry.data.u8[0] == mRotateAndCropOverride) {
5822 return false;
5823 } else {
5824 rotateAndCropEntry.data.u8[0] = mRotateAndCropOverride;
5825 return true;
5826 }
5827 } else {
5828 uint8_t rotateAndCrop_u8 = mRotateAndCropOverride;
5829 metadata.update(ANDROID_SCALER_ROTATE_AND_CROP,
5830 &rotateAndCrop_u8, 1);
5831 return true;
5832 }
5833 }
5834 return false;
5835}
5836
Eino-Ville Talvala305cec62020-11-12 14:18:17 -08005837bool Camera3Device::RequestThread::overrideTestPattern(
5838 const sp<CaptureRequest> &request) {
5839 ATRACE_CALL();
5840
5841 Mutex::Autolock l(mTriggerMutex);
5842
5843 bool changed = false;
5844
5845 int32_t testPatternMode = request->mOriginalTestPatternMode;
5846 int32_t testPatternData[4] = {
5847 request->mOriginalTestPatternData[0],
5848 request->mOriginalTestPatternData[1],
5849 request->mOriginalTestPatternData[2],
5850 request->mOriginalTestPatternData[3]
5851 };
5852
Eino-Ville Talvala11afe4f2021-05-27 14:45:31 -07005853 if (mCameraMute != ANDROID_SENSOR_TEST_PATTERN_MODE_OFF) {
5854 testPatternMode = mCameraMute;
Eino-Ville Talvala305cec62020-11-12 14:18:17 -08005855 testPatternData[0] = 0;
5856 testPatternData[1] = 0;
5857 testPatternData[2] = 0;
5858 testPatternData[3] = 0;
5859 }
5860
5861 CameraMetadata &metadata = request->mSettingsList.begin()->metadata;
5862
5863 auto testPatternEntry = metadata.find(ANDROID_SENSOR_TEST_PATTERN_MODE);
5864 if (testPatternEntry.count > 0) {
5865 if (testPatternEntry.data.i32[0] != testPatternMode) {
5866 testPatternEntry.data.i32[0] = testPatternMode;
5867 changed = true;
5868 }
5869 } else {
5870 metadata.update(ANDROID_SENSOR_TEST_PATTERN_MODE,
5871 &testPatternMode, 1);
5872 changed = true;
5873 }
5874
5875 auto testPatternColor = metadata.find(ANDROID_SENSOR_TEST_PATTERN_DATA);
5876 if (testPatternColor.count > 0) {
5877 for (size_t i = 0; i < 4; i++) {
5878 if (testPatternColor.data.i32[i] != (int32_t)testPatternData[i]) {
5879 testPatternColor.data.i32[i] = testPatternData[i];
5880 changed = true;
5881 }
5882 }
5883 } else {
5884 metadata.update(ANDROID_SENSOR_TEST_PATTERN_DATA,
5885 (int32_t*)testPatternData, 4);
5886 changed = true;
5887 }
5888
5889 return changed;
5890}
5891
Cliff Wuc2ad9c82021-04-21 00:58:58 +08005892status_t Camera3Device::RequestThread::setHalInterface(
5893 sp<HalInterface> newHalInterface) {
5894 if (newHalInterface.get() == nullptr) {
5895 ALOGE("%s: The newHalInterface does not exist!", __FUNCTION__);
5896 return DEAD_OBJECT;
5897 }
5898
5899 mInterface = newHalInterface;
5900
5901 return OK;
5902}
5903
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005904/**
5905 * PreparerThread inner class methods
5906 */
5907
5908Camera3Device::PreparerThread::PreparerThread() :
Eino-Ville Talvala77c1a352016-06-13 12:32:43 -07005909 Thread(/*canCallJava*/false), mListener(nullptr),
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005910 mActive(false), mCancelNow(false), mCurrentMaxCount(0), mCurrentPrepareComplete(false) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005911}
5912
5913Camera3Device::PreparerThread::~PreparerThread() {
5914 Thread::requestExitAndWait();
5915 if (mCurrentStream != nullptr) {
5916 mCurrentStream->cancelPrepare();
5917 ATRACE_ASYNC_END("stream prepare", mCurrentStream->getId());
5918 mCurrentStream.clear();
5919 }
5920 clear();
5921}
5922
Ruben Brunkc78ac262015-08-13 17:58:46 -07005923status_t Camera3Device::PreparerThread::prepare(int maxCount, sp<Camera3StreamInterface>& stream) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005924 ATRACE_CALL();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005925 status_t res;
5926
5927 Mutex::Autolock l(mLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005928 sp<NotificationListener> listener = mListener.promote();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005929
Shuzhen Wangb3a0fb52018-09-13 17:24:08 -07005930 res = stream->startPrepare(maxCount, true /*blockRequest*/);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005931 if (res == OK) {
5932 // No preparation needed, fire listener right off
5933 ALOGV("%s: Stream %d already prepared", __FUNCTION__, stream->getId());
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005934 if (listener != NULL) {
5935 listener->notifyPrepared(stream->getId());
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005936 }
5937 return OK;
5938 } else if (res != NOT_ENOUGH_DATA) {
5939 return res;
5940 }
5941
5942 // Need to prepare, start up thread if necessary
5943 if (!mActive) {
5944 // mRunning will change to false before the thread fully shuts down, so wait to be sure it
5945 // isn't running
5946 Thread::requestExitAndWait();
5947 res = Thread::run("C3PrepThread", PRIORITY_BACKGROUND);
5948 if (res != OK) {
5949 ALOGE("%s: Unable to start preparer stream: %d (%s)", __FUNCTION__, res, strerror(-res));
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005950 if (listener != NULL) {
5951 listener->notifyPrepared(stream->getId());
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005952 }
5953 return res;
5954 }
5955 mCancelNow = false;
5956 mActive = true;
5957 ALOGV("%s: Preparer stream started", __FUNCTION__);
5958 }
5959
5960 // queue up the work
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005961 mPendingStreams.emplace(maxCount, stream);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005962 ALOGV("%s: Stream %d queued for preparing", __FUNCTION__, stream->getId());
5963
5964 return OK;
5965}
5966
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005967void Camera3Device::PreparerThread::pause() {
5968 ATRACE_CALL();
5969
5970 Mutex::Autolock l(mLock);
5971
5972 std::unordered_map<int, sp<camera3::Camera3StreamInterface> > pendingStreams;
5973 pendingStreams.insert(mPendingStreams.begin(), mPendingStreams.end());
5974 sp<camera3::Camera3StreamInterface> currentStream = mCurrentStream;
5975 int currentMaxCount = mCurrentMaxCount;
5976 mPendingStreams.clear();
5977 mCancelNow = true;
5978 while (mActive) {
5979 auto res = mThreadActiveSignal.waitRelative(mLock, kActiveTimeout);
5980 if (res == TIMED_OUT) {
5981 ALOGE("%s: Timed out waiting on prepare thread!", __FUNCTION__);
5982 return;
5983 } else if (res != OK) {
5984 ALOGE("%s: Encountered an error: %d waiting on prepare thread!", __FUNCTION__, res);
5985 return;
5986 }
5987 }
5988
5989 //Check whether the prepare thread was able to complete the current
5990 //stream. In case work is still pending emplace it along with the rest
5991 //of the streams in the pending list.
5992 if (currentStream != nullptr) {
5993 if (!mCurrentPrepareComplete) {
5994 pendingStreams.emplace(currentMaxCount, currentStream);
5995 }
5996 }
5997
5998 mPendingStreams.insert(pendingStreams.begin(), pendingStreams.end());
5999 for (const auto& it : mPendingStreams) {
6000 it.second->cancelPrepare();
6001 }
6002}
6003
6004status_t Camera3Device::PreparerThread::resume() {
6005 ATRACE_CALL();
6006 status_t res;
6007
6008 Mutex::Autolock l(mLock);
6009 sp<NotificationListener> listener = mListener.promote();
6010
6011 if (mActive) {
6012 ALOGE("%s: Trying to resume an already active prepare thread!", __FUNCTION__);
6013 return NO_INIT;
6014 }
6015
6016 auto it = mPendingStreams.begin();
6017 for (; it != mPendingStreams.end();) {
Shuzhen Wangb3a0fb52018-09-13 17:24:08 -07006018 res = it->second->startPrepare(it->first, true /*blockRequest*/);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00006019 if (res == OK) {
6020 if (listener != NULL) {
6021 listener->notifyPrepared(it->second->getId());
6022 }
6023 it = mPendingStreams.erase(it);
6024 } else if (res != NOT_ENOUGH_DATA) {
6025 ALOGE("%s: Unable to start preparer stream: %d (%s)", __FUNCTION__,
6026 res, strerror(-res));
6027 it = mPendingStreams.erase(it);
6028 } else {
6029 it++;
6030 }
6031 }
6032
6033 if (mPendingStreams.empty()) {
6034 return OK;
6035 }
6036
6037 res = Thread::run("C3PrepThread", PRIORITY_BACKGROUND);
6038 if (res != OK) {
6039 ALOGE("%s: Unable to start preparer stream: %d (%s)",
6040 __FUNCTION__, res, strerror(-res));
6041 return res;
6042 }
6043 mCancelNow = false;
6044 mActive = true;
6045 ALOGV("%s: Preparer stream started", __FUNCTION__);
6046
6047 return OK;
6048}
6049
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07006050status_t Camera3Device::PreparerThread::clear() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07006051 ATRACE_CALL();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07006052 Mutex::Autolock l(mLock);
6053
Emilian Peevac3ce6c2017-12-12 15:27:02 +00006054 for (const auto& it : mPendingStreams) {
6055 it.second->cancelPrepare();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07006056 }
6057 mPendingStreams.clear();
6058 mCancelNow = true;
6059
6060 return OK;
6061}
6062
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07006063void Camera3Device::PreparerThread::setNotificationListener(wp<NotificationListener> listener) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07006064 ATRACE_CALL();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07006065 Mutex::Autolock l(mLock);
6066 mListener = listener;
6067}
6068
6069bool Camera3Device::PreparerThread::threadLoop() {
6070 status_t res;
6071 {
6072 Mutex::Autolock l(mLock);
6073 if (mCurrentStream == nullptr) {
6074 // End thread if done with work
6075 if (mPendingStreams.empty()) {
6076 ALOGV("%s: Preparer stream out of work", __FUNCTION__);
6077 // threadLoop _must not_ re-acquire mLock after it sets mActive to false; would
6078 // cause deadlock with prepare()'s requestExitAndWait triggered by !mActive.
6079 mActive = false;
Emilian Peevac3ce6c2017-12-12 15:27:02 +00006080 mThreadActiveSignal.signal();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07006081 return false;
6082 }
6083
6084 // Get next stream to prepare
6085 auto it = mPendingStreams.begin();
Emilian Peevac3ce6c2017-12-12 15:27:02 +00006086 mCurrentStream = it->second;
6087 mCurrentMaxCount = it->first;
6088 mCurrentPrepareComplete = false;
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07006089 mPendingStreams.erase(it);
6090 ATRACE_ASYNC_BEGIN("stream prepare", mCurrentStream->getId());
6091 ALOGV("%s: Preparing stream %d", __FUNCTION__, mCurrentStream->getId());
6092 } else if (mCancelNow) {
6093 mCurrentStream->cancelPrepare();
6094 ATRACE_ASYNC_END("stream prepare", mCurrentStream->getId());
6095 ALOGV("%s: Cancelling stream %d prepare", __FUNCTION__, mCurrentStream->getId());
6096 mCurrentStream.clear();
6097 mCancelNow = false;
6098 return true;
6099 }
6100 }
6101
6102 res = mCurrentStream->prepareNextBuffer();
6103 if (res == NOT_ENOUGH_DATA) return true;
6104 if (res != OK) {
6105 // Something bad happened; try to recover by cancelling prepare and
6106 // signalling listener anyway
6107 ALOGE("%s: Stream %d returned error %d (%s) during prepare", __FUNCTION__,
6108 mCurrentStream->getId(), res, strerror(-res));
6109 mCurrentStream->cancelPrepare();
6110 }
6111
6112 // This stream has finished, notify listener
6113 Mutex::Autolock l(mLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07006114 sp<NotificationListener> listener = mListener.promote();
6115 if (listener != NULL) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07006116 ALOGV("%s: Stream %d prepare done, signaling listener", __FUNCTION__,
6117 mCurrentStream->getId());
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07006118 listener->notifyPrepared(mCurrentStream->getId());
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07006119 }
6120
6121 ATRACE_ASYNC_END("stream prepare", mCurrentStream->getId());
6122 mCurrentStream.clear();
Emilian Peevac3ce6c2017-12-12 15:27:02 +00006123 mCurrentPrepareComplete = true;
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07006124
6125 return true;
6126}
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07006127
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07006128status_t Camera3Device::RequestBufferStateMachine::initialize(
6129 sp<camera3::StatusTracker> statusTracker) {
6130 if (statusTracker == nullptr) {
6131 ALOGE("%s: statusTracker is null", __FUNCTION__);
6132 return BAD_VALUE;
6133 }
6134
6135 std::lock_guard<std::mutex> lock(mLock);
6136 mStatusTracker = statusTracker;
Yin-Chia Yeh87b3ec02019-06-03 10:44:39 -07006137 mRequestBufferStatusId = statusTracker->addComponent("BufferRequestSM");
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07006138 return OK;
6139}
6140
6141bool Camera3Device::RequestBufferStateMachine::startRequestBuffer() {
6142 std::lock_guard<std::mutex> lock(mLock);
Yin-Chia Yeh8a4ccb02018-11-16 15:43:36 -08006143 if (mStatus == RB_STATUS_READY || mStatus == RB_STATUS_PENDING_STOP) {
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07006144 mRequestBufferOngoing = true;
Yin-Chia Yeh8a4ccb02018-11-16 15:43:36 -08006145 notifyTrackerLocked(/*active*/true);
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07006146 return true;
6147 }
6148 return false;
6149}
6150
6151void Camera3Device::RequestBufferStateMachine::endRequestBuffer() {
6152 std::lock_guard<std::mutex> lock(mLock);
6153 if (!mRequestBufferOngoing) {
6154 ALOGE("%s called without a successful startRequestBuffer call first!", __FUNCTION__);
6155 return;
6156 }
6157 mRequestBufferOngoing = false;
6158 if (mStatus == RB_STATUS_PENDING_STOP) {
6159 checkSwitchToStopLocked();
6160 }
Yin-Chia Yeh8a4ccb02018-11-16 15:43:36 -08006161 notifyTrackerLocked(/*active*/false);
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07006162}
6163
6164void Camera3Device::RequestBufferStateMachine::onStreamsConfigured() {
6165 std::lock_guard<std::mutex> lock(mLock);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08006166 mSwitchedToOffline = false;
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07006167 mStatus = RB_STATUS_READY;
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07006168 return;
6169}
6170
Yin-Chia Yehcd333fe2019-02-08 13:45:41 -08006171void Camera3Device::RequestBufferStateMachine::onSubmittingRequest() {
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07006172 std::lock_guard<std::mutex> lock(mLock);
6173 mRequestThreadPaused = false;
Yin-Chia Yehcd333fe2019-02-08 13:45:41 -08006174 // inflight map register actually happens in prepareHalRequest now, but it is close enough
6175 // approximation.
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07006176 mInflightMapEmpty = false;
6177 if (mStatus == RB_STATUS_STOPPED) {
6178 mStatus = RB_STATUS_READY;
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07006179 }
6180 return;
6181}
6182
6183void Camera3Device::RequestBufferStateMachine::onRequestThreadPaused() {
6184 std::lock_guard<std::mutex> lock(mLock);
6185 mRequestThreadPaused = true;
6186 if (mStatus == RB_STATUS_PENDING_STOP) {
6187 checkSwitchToStopLocked();
6188 }
6189 return;
6190}
6191
6192void Camera3Device::RequestBufferStateMachine::onInflightMapEmpty() {
6193 std::lock_guard<std::mutex> lock(mLock);
6194 mInflightMapEmpty = true;
6195 if (mStatus == RB_STATUS_PENDING_STOP) {
6196 checkSwitchToStopLocked();
6197 }
6198 return;
6199}
6200
6201void Camera3Device::RequestBufferStateMachine::onWaitUntilIdle() {
6202 std::lock_guard<std::mutex> lock(mLock);
6203 if (!checkSwitchToStopLocked()) {
6204 mStatus = RB_STATUS_PENDING_STOP;
6205 }
6206 return;
6207}
6208
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08006209bool Camera3Device::RequestBufferStateMachine::onSwitchToOfflineSuccess() {
6210 std::lock_guard<std::mutex> lock(mLock);
6211 if (mRequestBufferOngoing) {
6212 ALOGE("%s: HAL must not be requesting buffer after HAL returns switchToOffline!",
6213 __FUNCTION__);
6214 return false;
6215 }
6216 mSwitchedToOffline = true;
6217 mInflightMapEmpty = true;
6218 mRequestThreadPaused = true;
6219 mStatus = RB_STATUS_STOPPED;
6220 return true;
6221}
6222
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07006223void Camera3Device::RequestBufferStateMachine::notifyTrackerLocked(bool active) {
6224 sp<StatusTracker> statusTracker = mStatusTracker.promote();
6225 if (statusTracker != nullptr) {
6226 if (active) {
6227 statusTracker->markComponentActive(mRequestBufferStatusId);
6228 } else {
6229 statusTracker->markComponentIdle(mRequestBufferStatusId, Fence::NO_FENCE);
6230 }
6231 }
6232}
6233
6234bool Camera3Device::RequestBufferStateMachine::checkSwitchToStopLocked() {
6235 if (mInflightMapEmpty && mRequestThreadPaused && !mRequestBufferOngoing) {
6236 mStatus = RB_STATUS_STOPPED;
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07006237 return true;
6238 }
6239 return false;
6240}
6241
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08006242bool Camera3Device::startRequestBuffer() {
6243 return mRequestBufferSM.startRequestBuffer();
6244}
Shuzhen Wang268a1362018-10-16 16:32:59 -07006245
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08006246void Camera3Device::endRequestBuffer() {
6247 mRequestBufferSM.endRequestBuffer();
6248}
Shuzhen Wang268a1362018-10-16 16:32:59 -07006249
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08006250nsecs_t Camera3Device::getWaitDuration() {
6251 return kBaseGetBufferWait + getExpectedInFlightDuration();
6252}
Shuzhen Wang268a1362018-10-16 16:32:59 -07006253
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08006254void Camera3Device::getInflightBufferKeys(std::vector<std::pair<int32_t, int32_t>>* out) {
6255 mInterface->getInflightBufferKeys(out);
6256}
Shuzhen Wang268a1362018-10-16 16:32:59 -07006257
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08006258void Camera3Device::getInflightRequestBufferKeys(std::vector<uint64_t>* out) {
6259 mInterface->getInflightRequestBufferKeys(out);
6260}
Shuzhen Wang268a1362018-10-16 16:32:59 -07006261
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08006262std::vector<sp<Camera3StreamInterface>> Camera3Device::getAllStreams() {
6263 std::vector<sp<Camera3StreamInterface>> ret;
6264 bool hasInputStream = mInputStream != nullptr;
6265 ret.reserve(mOutputStreams.size() + mDeletedStreams.size() + ((hasInputStream) ? 1 : 0));
6266 if (hasInputStream) {
6267 ret.push_back(mInputStream);
Shuzhen Wang268a1362018-10-16 16:32:59 -07006268 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08006269 for (size_t i = 0; i < mOutputStreams.size(); i++) {
6270 ret.push_back(mOutputStreams[i]);
6271 }
6272 for (size_t i = 0; i < mDeletedStreams.size(); i++) {
6273 ret.push_back(mDeletedStreams[i]);
6274 }
6275 return ret;
Shuzhen Wang268a1362018-10-16 16:32:59 -07006276}
6277
Yin-Chia Yehb978c382019-10-30 00:22:37 -07006278status_t Camera3Device::switchToOffline(
6279 const std::vector<int32_t>& streamsToKeep,
6280 /*out*/ sp<CameraOfflineSessionBase>* session) {
6281 ATRACE_CALL();
6282 if (session == nullptr) {
6283 ALOGE("%s: session must not be null", __FUNCTION__);
6284 return BAD_VALUE;
6285 }
6286
6287 Mutex::Autolock il(mInterfaceLock);
Yin-Chia Yehb978c382019-10-30 00:22:37 -07006288
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08006289 bool hasInputStream = mInputStream != nullptr;
6290 int32_t inputStreamId = hasInputStream ? mInputStream->getId() : -1;
6291 bool inputStreamSupportsOffline = hasInputStream ?
6292 mInputStream->getOfflineProcessingSupport() : false;
6293 auto outputStreamIds = mOutputStreams.getStreamIds();
6294 auto streamIds = outputStreamIds;
6295 if (hasInputStream) {
6296 streamIds.push_back(mInputStream->getId());
6297 }
6298
6299 // Check all streams in streamsToKeep supports offline mode
6300 for (auto id : streamsToKeep) {
6301 if (std::find(streamIds.begin(), streamIds.end(), id) == streamIds.end()) {
6302 ALOGE("%s: Unknown stream ID %d", __FUNCTION__, id);
6303 return BAD_VALUE;
6304 } else if (id == inputStreamId) {
6305 if (!inputStreamSupportsOffline) {
6306 ALOGE("%s: input stream %d cannot be switched to offline",
6307 __FUNCTION__, id);
6308 return BAD_VALUE;
6309 }
6310 } else {
6311 sp<camera3::Camera3OutputStreamInterface> stream = mOutputStreams.get(id);
6312 if (!stream->getOfflineProcessingSupport()) {
6313 ALOGE("%s: output stream %d cannot be switched to offline",
6314 __FUNCTION__, id);
6315 return BAD_VALUE;
6316 }
6317 }
6318 }
6319
6320 // TODO: block surface sharing and surface group streams until we can support them
6321
6322 // Stop repeating request, wait until all remaining requests are submitted, then call into
6323 // HAL switchToOffline
Yin-Chia Yehb978c382019-10-30 00:22:37 -07006324 hardware::camera::device::V3_6::CameraOfflineSessionInfo offlineSessionInfo;
6325 sp<hardware::camera::device::V3_6::ICameraOfflineSession> offlineSession;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08006326 camera3::BufferRecords bufferRecords;
6327 status_t ret = mRequestThread->switchToOffline(
6328 streamsToKeep, &offlineSessionInfo, &offlineSession, &bufferRecords);
Yin-Chia Yehb978c382019-10-30 00:22:37 -07006329
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08006330 if (ret != OK) {
6331 SET_ERR("Switch to offline failed: %s (%d)", strerror(-ret), ret);
6332 return ret;
6333 }
Yin-Chia Yehb978c382019-10-30 00:22:37 -07006334
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08006335 bool succ = mRequestBufferSM.onSwitchToOfflineSuccess();
6336 if (!succ) {
6337 SET_ERR("HAL must not be calling requestStreamBuffers call");
6338 // TODO: block ALL callbacks from HAL till app configured new streams?
6339 return UNKNOWN_ERROR;
6340 }
Yin-Chia Yehb978c382019-10-30 00:22:37 -07006341
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08006342 // Verify offlineSessionInfo
6343 std::vector<int32_t> offlineStreamIds;
6344 offlineStreamIds.reserve(offlineSessionInfo.offlineStreams.size());
6345 for (auto offlineStream : offlineSessionInfo.offlineStreams) {
6346 // verify stream IDs
6347 int32_t id = offlineStream.id;
6348 if (std::find(streamIds.begin(), streamIds.end(), id) == streamIds.end()) {
6349 SET_ERR("stream ID %d not found!", id);
6350 return UNKNOWN_ERROR;
6351 }
6352
6353 // When not using HAL buf manager, only allow streams requested by app to be preserved
6354 if (!mUseHalBufManager) {
6355 if (std::find(streamsToKeep.begin(), streamsToKeep.end(), id) == streamsToKeep.end()) {
6356 SET_ERR("stream ID %d must not be switched to offline!", id);
6357 return UNKNOWN_ERROR;
6358 }
6359 }
6360
6361 offlineStreamIds.push_back(id);
6362 sp<Camera3StreamInterface> stream = (id == inputStreamId) ?
6363 static_cast<sp<Camera3StreamInterface>>(mInputStream) :
6364 static_cast<sp<Camera3StreamInterface>>(mOutputStreams.get(id));
6365 // Verify number of outstanding buffers
6366 if (stream->getOutstandingBuffersCount() != offlineStream.numOutstandingBuffers) {
6367 SET_ERR("Offline stream %d # of remaining buffer mismatch: (%zu,%d) (service/HAL)",
6368 id, stream->getOutstandingBuffersCount(), offlineStream.numOutstandingBuffers);
6369 return UNKNOWN_ERROR;
6370 }
6371 }
6372
6373 // Verify all streams to be deleted don't have any outstanding buffers
6374 if (hasInputStream && std::find(offlineStreamIds.begin(), offlineStreamIds.end(),
6375 inputStreamId) == offlineStreamIds.end()) {
6376 if (mInputStream->hasOutstandingBuffers()) {
6377 SET_ERR("Input stream %d still has %zu outstanding buffer!",
6378 inputStreamId, mInputStream->getOutstandingBuffersCount());
6379 return UNKNOWN_ERROR;
6380 }
6381 }
6382
6383 for (const auto& outStreamId : outputStreamIds) {
6384 if (std::find(offlineStreamIds.begin(), offlineStreamIds.end(),
6385 outStreamId) == offlineStreamIds.end()) {
6386 auto outStream = mOutputStreams.get(outStreamId);
6387 if (outStream->hasOutstandingBuffers()) {
6388 SET_ERR("Output stream %d still has %zu outstanding buffer!",
6389 outStreamId, outStream->getOutstandingBuffersCount());
6390 return UNKNOWN_ERROR;
6391 }
6392 }
6393 }
6394
6395 InFlightRequestMap offlineReqs;
6396 // Verify inflight requests and their pending buffers
6397 {
6398 std::lock_guard<std::mutex> l(mInFlightLock);
6399 for (auto offlineReq : offlineSessionInfo.offlineRequests) {
6400 int idx = mInFlightMap.indexOfKey(offlineReq.frameNumber);
6401 if (idx == NAME_NOT_FOUND) {
6402 SET_ERR("Offline request frame number %d not found!", offlineReq.frameNumber);
6403 return UNKNOWN_ERROR;
6404 }
6405
6406 const auto& inflightReq = mInFlightMap.valueAt(idx);
6407 // TODO: check specific stream IDs
6408 size_t numBuffersLeft = static_cast<size_t>(inflightReq.numBuffersLeft);
6409 if (numBuffersLeft != offlineReq.pendingStreams.size()) {
6410 SET_ERR("Offline request # of remaining buffer mismatch: (%d,%d) (service/HAL)",
6411 inflightReq.numBuffersLeft, offlineReq.pendingStreams.size());
6412 return UNKNOWN_ERROR;
6413 }
6414 offlineReqs.add(offlineReq.frameNumber, inflightReq);
6415 }
6416 }
6417
6418 // Create Camera3OfflineSession and transfer object ownership
Yin-Chia Yehb978c382019-10-30 00:22:37 -07006419 // (streams, inflight requests, buffer caches)
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08006420 camera3::StreamSet offlineStreamSet;
6421 sp<camera3::Camera3Stream> inputStream;
6422 for (auto offlineStream : offlineSessionInfo.offlineStreams) {
6423 int32_t id = offlineStream.id;
6424 if (mInputStream != nullptr && id == mInputStream->getId()) {
6425 inputStream = mInputStream;
6426 } else {
6427 offlineStreamSet.add(id, mOutputStreams.get(id));
6428 }
6429 }
Yin-Chia Yehb978c382019-10-30 00:22:37 -07006430
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08006431 // TODO: check if we need to lock before copying states
6432 // though technically no other thread should be talking to Camera3Device at this point
6433 Camera3OfflineStates offlineStates(
6434 mTagMonitor, mVendorTagId, mUseHalBufManager, mNeedFixupMonochromeTags,
Shuzhen Wangb7b42652020-05-07 11:59:02 -07006435 mUsePartialResult, mNumPartialResults, mLastCompletedRegularFrameNumber,
6436 mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
6437 mNextResultFrameNumber, mNextReprocessResultFrameNumber,
6438 mNextZslStillResultFrameNumber, mNextShutterFrameNumber,
6439 mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
6440 mDeviceInfo, mPhysicalDeviceInfoMap, mDistortionMappers,
6441 mZoomRatioMappers, mRotateAndCropMappers);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08006442
6443 *session = new Camera3OfflineSession(mId, inputStream, offlineStreamSet,
6444 std::move(bufferRecords), offlineReqs, offlineStates, offlineSession);
6445
6446 // Delete all streams that has been transferred to offline session
6447 Mutex::Autolock l(mLock);
6448 for (auto offlineStream : offlineSessionInfo.offlineStreams) {
6449 int32_t id = offlineStream.id;
6450 if (mInputStream != nullptr && id == mInputStream->getId()) {
6451 mInputStream.clear();
6452 } else {
6453 mOutputStreams.remove(id);
6454 }
6455 }
6456
6457 // disconnect all other streams and switch to UNCONFIGURED state
6458 if (mInputStream != nullptr) {
6459 ret = mInputStream->disconnect();
6460 if (ret != OK) {
6461 SET_ERR_L("disconnect input stream failed!");
6462 return UNKNOWN_ERROR;
6463 }
6464 }
6465
6466 for (auto streamId : mOutputStreams.getStreamIds()) {
6467 sp<Camera3StreamInterface> stream = mOutputStreams.get(streamId);
6468 ret = stream->disconnect();
6469 if (ret != OK) {
6470 SET_ERR_L("disconnect output stream %d failed!", streamId);
6471 return UNKNOWN_ERROR;
6472 }
6473 }
6474
6475 mInputStream.clear();
6476 mOutputStreams.clear();
6477 mNeedConfig = true;
6478 internalUpdateStatusLocked(STATUS_UNCONFIGURED);
6479 mOperatingMode = NO_MODE;
6480 mIsConstrainedHighSpeedConfiguration = false;
Emilian Peevc0fe54c2020-03-11 14:05:07 -07006481 mRequestThread->clearPreviousRequest();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08006482
Yin-Chia Yehb978c382019-10-30 00:22:37 -07006483 return OK;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08006484 // TO be done by CameraDeviceClient/Camera3OfflineSession
6485 // register the offline client to camera service
6486 // Setup result passthing threads etc
6487 // Initialize offline session so HAL can start sending callback to it (result Fmq)
6488 // TODO: check how many onIdle callback will be sent
6489 // Java side to make sure the CameraCaptureSession is properly closed
Yin-Chia Yehb978c382019-10-30 00:22:37 -07006490}
6491
Emilian Peevcc0b7952020-01-07 13:54:47 -08006492void Camera3Device::getOfflineStreamIds(std::vector<int> *offlineStreamIds) {
6493 ATRACE_CALL();
6494
6495 if (offlineStreamIds == nullptr) {
6496 return;
6497 }
6498
6499 Mutex::Autolock il(mInterfaceLock);
6500
6501 auto streamIds = mOutputStreams.getStreamIds();
6502 bool hasInputStream = mInputStream != nullptr;
6503 if (hasInputStream && mInputStream->getOfflineProcessingSupport()) {
6504 offlineStreamIds->push_back(mInputStream->getId());
6505 }
6506
6507 for (const auto & streamId : streamIds) {
6508 sp<camera3::Camera3OutputStreamInterface> stream = mOutputStreams.get(streamId);
6509 // Streams that use the camera buffer manager are currently not supported in
6510 // offline mode
6511 if (stream->getOfflineProcessingSupport() &&
6512 (stream->getStreamSetId() == CAMERA3_STREAM_SET_ID_INVALID)) {
6513 offlineStreamIds->push_back(streamId);
6514 }
6515 }
6516}
6517
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08006518status_t Camera3Device::setRotateAndCropAutoBehavior(
6519 camera_metadata_enum_android_scaler_rotate_and_crop_t rotateAndCropValue) {
6520 ATRACE_CALL();
6521 Mutex::Autolock il(mInterfaceLock);
6522 Mutex::Autolock l(mLock);
6523 if (mRequestThread == nullptr) {
6524 return INVALID_OPERATION;
6525 }
6526 return mRequestThread->setRotateAndCropAutoBehavior(rotateAndCropValue);
6527}
6528
Eino-Ville Talvala305cec62020-11-12 14:18:17 -08006529bool Camera3Device::supportsCameraMute() {
6530 Mutex::Autolock il(mInterfaceLock);
6531 Mutex::Autolock l(mLock);
6532
6533 return mSupportCameraMute;
6534}
6535
6536status_t Camera3Device::setCameraMute(bool enabled) {
6537 ATRACE_CALL();
6538 Mutex::Autolock il(mInterfaceLock);
6539 Mutex::Autolock l(mLock);
6540
6541 if (mRequestThread == nullptr || !mSupportCameraMute) {
6542 return INVALID_OPERATION;
6543 }
Eino-Ville Talvala11afe4f2021-05-27 14:45:31 -07006544 int32_t muteMode =
6545 !enabled ? ANDROID_SENSOR_TEST_PATTERN_MODE_OFF :
6546 mSupportTestPatternSolidColor ? ANDROID_SENSOR_TEST_PATTERN_MODE_SOLID_COLOR :
6547 ANDROID_SENSOR_TEST_PATTERN_MODE_BLACK;
6548 return mRequestThread->setCameraMute(muteMode);
Eino-Ville Talvala305cec62020-11-12 14:18:17 -08006549}
6550
Cliff Wuc2ad9c82021-04-21 00:58:58 +08006551status_t Camera3Device::injectCamera(const String8& injectedCamId,
6552 sp<CameraProviderManager> manager) {
6553 ALOGI("%s Injection camera: injectedCamId = %s", __FUNCTION__, injectedCamId.string());
6554 ATRACE_CALL();
6555 Mutex::Autolock il(mInterfaceLock);
6556
6557 status_t res = NO_ERROR;
6558 if (mInjectionMethods->isInjecting()) {
6559 if (injectedCamId == mInjectionMethods->getInjectedCamId()) {
6560 return OK;
6561 } else {
6562 res = mInjectionMethods->stopInjection();
6563 if (res != OK) {
6564 ALOGE("%s: Failed to stop the injection camera! ret != NO_ERROR: %d",
6565 __FUNCTION__, res);
6566 return res;
6567 }
6568 }
6569 }
6570
6571 res = mInjectionMethods->injectionInitialize(injectedCamId, manager, this);
6572 if (res != OK) {
6573 ALOGE("%s: Failed to initialize the injection camera! ret != NO_ERROR: %d",
6574 __FUNCTION__, res);
6575 return res;
6576 }
6577
6578 camera3::camera_stream_configuration injectionConfig;
6579 std::vector<uint32_t> injectionBufferSizes;
6580 mInjectionMethods->getInjectionConfig(&injectionConfig, &injectionBufferSizes);
6581 // When the second display of android is cast to the remote device, and the opened camera is
6582 // also cast to the second display, in this case, because the camera has configured the streams
6583 // at this time, we can directly call injectCamera() to replace the internal camera with
6584 // injection camera.
6585 if (mOperatingMode >= 0 && injectionConfig.num_streams > 0
6586 && injectionBufferSizes.size() > 0) {
6587 ALOGV("%s: The opened camera is directly cast to the remote device.", __FUNCTION__);
6588 res = mInjectionMethods->injectCamera(
6589 injectionConfig, injectionBufferSizes);
6590 if (res != OK) {
6591 ALOGE("Can't finish inject camera process!");
6592 return res;
6593 }
6594 }
6595
6596 return OK;
6597}
6598
6599status_t Camera3Device::stopInjection() {
6600 ALOGI("%s: Injection camera: stopInjection", __FUNCTION__);
6601 Mutex::Autolock il(mInterfaceLock);
6602 return mInjectionMethods->stopInjection();
6603}
6604
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08006605}; // namespace android