blob: d5f136b84d4818c661a102aeed7ab5cd8e982988 [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
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -080052#include <android/hardware/camera2/ICameraDeviceUser.h>
53
Igor Murashkinff3e31d2013-10-23 16:40:06 -070054#include "utils/CameraTraces.h"
Eino-Ville Talvalaf99498e2015-09-25 16:52:55 -070055#include "mediautils/SchedulingPolicyService.h"
Eino-Ville Talvala7b82efe2013-07-25 17:12:35 -070056#include "device3/Camera3Device.h"
57#include "device3/Camera3OutputStream.h"
58#include "device3/Camera3InputStream.h"
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -070059#include "device3/Camera3DummyStream.h"
Shuzhen Wang0129d522016-10-30 22:43:41 -070060#include "device3/Camera3SharedOutputStream.h"
Eino-Ville Talvalaf67e23e2014-07-23 17:17:59 -070061#include "CameraService.h"
Jayant Chowdhary12361932018-08-27 14:46:13 -070062#include "utils/CameraThreadState.h"
Jayant Chowdharyd4776262020-06-23 23:45:57 -070063#include "utils/TraceHFR.h"
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -080064
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -080065#include <algorithm>
Yin-Chia Yeh84be5782019-03-01 11:47:02 -080066#include <tuple>
67
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -080068using namespace android::camera3;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -080069using namespace android::hardware::camera;
70using namespace android::hardware::camera::device::V3_2;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -080071
72namespace android {
73
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -080074Camera3Device::Camera3Device(const String8 &id):
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -080075 mId(id),
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -080076 mOperatingMode(NO_MODE),
Eino-Ville Talvala9a179412015-06-09 13:15:16 -070077 mIsConstrainedHighSpeedConfiguration(false),
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -070078 mStatus(STATUS_UNINITIALIZED),
Ruben Brunk183f0562015-08-12 12:55:02 -070079 mStatusWaiters(0),
Zhijun He204e3292014-07-14 17:09:23 -070080 mUsePartialResult(false),
81 mNumPartialResults(1),
Shuzhen Wangc28dccc2016-02-11 23:48:46 -080082 mTimestampOffset(0),
Eino-Ville Talvala42368d92013-04-09 14:13:50 -070083 mNextResultFrameNumber(0),
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -070084 mNextReprocessResultFrameNumber(0),
Shuzhen Wang5ee99842019-04-12 11:55:48 -070085 mNextZslStillResultFrameNumber(0),
Eino-Ville Talvala42368d92013-04-09 14:13:50 -070086 mNextShutterFrameNumber(0),
Chien-Yu Chen3df11ce2015-09-30 14:13:30 -070087 mNextReprocessShutterFrameNumber(0),
Shuzhen Wang5ee99842019-04-12 11:55:48 -070088 mNextZslStillShutterFrameNumber(0),
Emilian Peev71c73a22017-03-21 16:35:51 +000089 mListener(NULL),
Emilian Peev811d2952018-05-25 11:08:40 +010090 mVendorTagId(CAMERA_METADATA_INVALID_VENDOR_ID),
Shuzhen Wang268a1362018-10-16 16:32:59 -070091 mLastTemplateId(-1),
92 mNeedFixupMonochromeTags(false)
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -080093{
94 ATRACE_CALL();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -080095 ALOGV("%s: Created device for camera %s", __FUNCTION__, mId.string());
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -080096}
97
98Camera3Device::~Camera3Device()
99{
100 ATRACE_CALL();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800101 ALOGV("%s: Tearing down for camera id %s", __FUNCTION__, mId.string());
Yin-Chia Yehc5248132018-08-15 12:19:20 -0700102 disconnectImpl();
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800103}
104
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800105const String8& Camera3Device::getId() const {
Igor Murashkin71381052013-03-04 14:53:08 -0800106 return mId;
107}
108
Emilian Peevbd8c5032018-02-14 23:05:40 +0000109status_t Camera3Device::initialize(sp<CameraProviderManager> manager, const String8& monitorTags) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800110 ATRACE_CALL();
111 Mutex::Autolock il(mInterfaceLock);
112 Mutex::Autolock l(mLock);
113
114 ALOGV("%s: Initializing HIDL device for camera %s", __FUNCTION__, mId.string());
115 if (mStatus != STATUS_UNINITIALIZED) {
116 CLOGE("Already initialized!");
117 return INVALID_OPERATION;
118 }
119 if (manager == nullptr) return INVALID_OPERATION;
120
121 sp<ICameraDeviceSession> session;
122 ATRACE_BEGIN("CameraHal::openSession");
Steven Moreland5ff9c912017-03-09 23:13:00 -0800123 status_t res = manager->openSession(mId.string(), this,
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800124 /*out*/ &session);
125 ATRACE_END();
126 if (res != OK) {
127 SET_ERR_L("Could not open camera session: %s (%d)", strerror(-res), res);
128 return res;
129 }
130
Steven Moreland5ff9c912017-03-09 23:13:00 -0800131 res = manager->getCameraCharacteristics(mId.string(), &mDeviceInfo);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800132 if (res != OK) {
Shuzhen Wang2e7f58f2018-07-11 14:00:29 -0700133 SET_ERR_L("Could not retrieve camera characteristics: %s (%d)", strerror(-res), res);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800134 session->close();
135 return res;
136 }
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -0800137 mSupportNativeZoomRatio = manager->supportNativeZoomRatio(mId.string());
Yin-Chia Yeh52778d42016-12-22 18:20:43 -0800138
Shuzhen Wang2e7f58f2018-07-11 14:00:29 -0700139 std::vector<std::string> physicalCameraIds;
Shuzhen Wang03d8cc12018-09-12 14:17:09 -0700140 bool isLogical = manager->isLogicalCamera(mId.string(), &physicalCameraIds);
Shuzhen Wang2e7f58f2018-07-11 14:00:29 -0700141 if (isLogical) {
142 for (auto& physicalId : physicalCameraIds) {
Shuzhen Wang4f6fa9d2019-03-29 10:40:35 -0700143 res = manager->getCameraCharacteristics(
144 physicalId, &mPhysicalDeviceInfoMap[physicalId]);
Shuzhen Wang2e7f58f2018-07-11 14:00:29 -0700145 if (res != OK) {
146 SET_ERR_L("Could not retrieve camera %s characteristics: %s (%d)",
147 physicalId.c_str(), strerror(-res), res);
148 session->close();
149 return res;
150 }
Shuzhen Wang4f6fa9d2019-03-29 10:40:35 -0700151
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -0800152 bool usePrecorrectArray =
153 DistortionMapper::isDistortionSupported(mPhysicalDeviceInfoMap[physicalId]);
154 if (usePrecorrectArray) {
155 res = mDistortionMappers[physicalId].setupStaticInfo(
156 mPhysicalDeviceInfoMap[physicalId]);
Shuzhen Wang4f6fa9d2019-03-29 10:40:35 -0700157 if (res != OK) {
158 SET_ERR_L("Unable to read camera %s's calibration fields for distortion "
159 "correction", physicalId.c_str());
160 session->close();
161 return res;
162 }
163 }
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -0800164
Shuzhen Wang1c834da2019-12-18 11:17:03 -0800165 mZoomRatioMappers[physicalId] = ZoomRatioMapper(
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -0800166 &mPhysicalDeviceInfoMap[physicalId],
167 mSupportNativeZoomRatio, usePrecorrectArray);
Shuzhen Wang2e7f58f2018-07-11 14:00:29 -0700168 }
169 }
170
Yifan Hongf79b5542017-04-11 14:44:25 -0700171 std::shared_ptr<RequestMetadataQueue> queue;
Yifan Honga640c5a2017-04-12 16:30:31 -0700172 auto requestQueueRet = session->getCaptureRequestMetadataQueue(
173 [&queue](const auto& descriptor) {
174 queue = std::make_shared<RequestMetadataQueue>(descriptor);
175 if (!queue->isValid() || queue->availableToWrite() <= 0) {
176 ALOGE("HAL returns empty request metadata fmq, not use it");
177 queue = nullptr;
178 // don't use the queue onwards.
179 }
180 });
181 if (!requestQueueRet.isOk()) {
182 ALOGE("Transaction error when getting request metadata fmq: %s, not use it",
183 requestQueueRet.description().c_str());
Eino-Ville Talvalac5cbb872017-04-27 12:48:33 -0700184 return DEAD_OBJECT;
Yifan Hongf79b5542017-04-11 14:44:25 -0700185 }
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700186
187 std::unique_ptr<ResultMetadataQueue>& resQueue = mResultMetadataQueue;
Yifan Honga640c5a2017-04-12 16:30:31 -0700188 auto resultQueueRet = session->getCaptureResultMetadataQueue(
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700189 [&resQueue](const auto& descriptor) {
190 resQueue = std::make_unique<ResultMetadataQueue>(descriptor);
191 if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
Yifan Honga640c5a2017-04-12 16:30:31 -0700192 ALOGE("HAL returns empty result metadata fmq, not use it");
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700193 resQueue = nullptr;
194 // Don't use the resQueue onwards.
Yifan Honga640c5a2017-04-12 16:30:31 -0700195 }
196 });
197 if (!resultQueueRet.isOk()) {
198 ALOGE("Transaction error when getting result metadata queue from camera session: %s",
199 resultQueueRet.description().c_str());
Eino-Ville Talvalac5cbb872017-04-27 12:48:33 -0700200 return DEAD_OBJECT;
Yifan Honga640c5a2017-04-12 16:30:31 -0700201 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -0700202 IF_ALOGV() {
203 session->interfaceChain([](
204 ::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
205 ALOGV("Session interface chain:");
Chih-Hung Hsieh3ef324d2018-12-11 11:48:12 -0800206 for (const auto& iface : interfaceChain) {
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -0700207 ALOGV(" %s", iface.c_str());
208 }
209 });
210 }
Yifan Hongf79b5542017-04-11 14:44:25 -0700211
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -0800212 camera_metadata_entry bufMgrMode =
213 mDeviceInfo.find(ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION);
214 if (bufMgrMode.count > 0) {
215 mUseHalBufManager = (bufMgrMode.data.u8[0] ==
216 ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5);
217 }
218
Yin-Chia Yehb978c382019-10-30 00:22:37 -0700219 camera_metadata_entry_t capabilities = mDeviceInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
220 for (size_t i = 0; i < capabilities.count; i++) {
221 uint8_t capability = capabilities.data.u8[i];
222 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_OFFLINE_PROCESSING) {
223 mSupportOfflineProcessing = true;
224 }
225 }
226
227 mInterface = new HalInterface(session, queue, mUseHalBufManager, mSupportOfflineProcessing);
Emilian Peev71c73a22017-03-21 16:35:51 +0000228 std::string providerType;
229 mVendorTagId = manager->getProviderTagIdLocked(mId.string());
Emilian Peevbd8c5032018-02-14 23:05:40 +0000230 mTagMonitor.initialize(mVendorTagId);
231 if (!monitorTags.isEmpty()) {
232 mTagMonitor.parseTagsToMonitor(String8(monitorTags));
233 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800234
Shuzhen Wang268a1362018-10-16 16:32:59 -0700235 // Metadata tags needs fixup for monochrome camera device version less
236 // than 3.5.
237 hardware::hidl_version maxVersion{0,0};
238 res = manager->getHighestSupportedVersion(mId.string(), &maxVersion);
239 if (res != OK) {
240 ALOGE("%s: Error in getting camera device version id: %s (%d)",
241 __FUNCTION__, strerror(-res), res);
242 return res;
243 }
244 int deviceVersion = HARDWARE_DEVICE_API_VERSION(
245 maxVersion.get_major(), maxVersion.get_minor());
246
247 bool isMonochrome = false;
Yin-Chia Yehb978c382019-10-30 00:22:37 -0700248 for (size_t i = 0; i < capabilities.count; i++) {
249 uint8_t capability = capabilities.data.u8[i];
Shuzhen Wang268a1362018-10-16 16:32:59 -0700250 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME) {
251 isMonochrome = true;
252 }
253 }
254 mNeedFixupMonochromeTags = (isMonochrome && deviceVersion < CAMERA_DEVICE_API_VERSION_3_5);
255
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800256 return initializeCommonLocked();
257}
258
259status_t Camera3Device::initializeCommonLocked() {
260
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700261 /** Start up status tracker thread */
262 mStatusTracker = new StatusTracker(this);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800263 status_t res = mStatusTracker->run(String8::format("C3Dev-%s-Status", mId.string()).string());
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700264 if (res != OK) {
265 SET_ERR_L("Unable to start status tracking thread: %s (%d)",
266 strerror(-res), res);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800267 mInterface->close();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700268 mStatusTracker.clear();
269 return res;
270 }
271
Eino-Ville Talvala24b366e2016-07-21 12:53:07 -0700272 /** Register in-flight map to the status tracker */
273 mInFlightStatusId = mStatusTracker->addComponent();
274
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -0700275 if (mUseHalBufManager) {
276 res = mRequestBufferSM.initialize(mStatusTracker);
277 if (res != OK) {
278 SET_ERR_L("Unable to start request buffer state machine: %s (%d)",
279 strerror(-res), res);
280 mInterface->close();
281 mStatusTracker.clear();
282 return res;
283 }
284 }
285
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -0800286 /** Create buffer manager */
287 mBufferManager = new Camera3BufferManager();
288
289 Vector<int32_t> sessionParamKeys;
290 camera_metadata_entry_t sessionKeysEntry = mDeviceInfo.find(
291 ANDROID_REQUEST_AVAILABLE_SESSION_KEYS);
292 if (sessionKeysEntry.count > 0) {
293 sessionParamKeys.insertArrayAt(sessionKeysEntry.data.i32, 0, sessionKeysEntry.count);
294 }
295
Chien-Yu Chenab5135b2015-06-30 11:20:58 -0700296 /** Start up request queue thread */
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -0700297 mRequestThread = new RequestThread(
298 this, mStatusTracker, mInterface, sessionParamKeys, mUseHalBufManager);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800299 res = mRequestThread->run(String8::format("C3Dev-%s-ReqQueue", mId.string()).string());
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800300 if (res != OK) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -0700301 SET_ERR_L("Unable to start request queue thread: %s (%d)",
302 strerror(-res), res);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800303 mInterface->close();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800304 mRequestThread.clear();
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800305 return res;
306 }
307
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -0700308 mPreparerThread = new PreparerThread();
309
Ruben Brunk183f0562015-08-12 12:55:02 -0700310 internalUpdateStatusLocked(STATUS_UNCONFIGURED);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800311 mNextStreamId = 0;
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -0700312 mDummyStreamId = NO_STREAM;
Eino-Ville Talvalaea26c772013-06-11 16:04:06 -0700313 mNeedConfig = true;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700314 mPauseStateNotify = false;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800315
Shuzhen Wangc28dccc2016-02-11 23:48:46 -0800316 // Measure the clock domain offset between camera and video/hw_composer
317 camera_metadata_entry timestampSource =
318 mDeviceInfo.find(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE);
319 if (timestampSource.count > 0 && timestampSource.data.u8[0] ==
320 ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME) {
321 mTimestampOffset = getMonoToBoottimeOffset();
322 }
323
Eino-Ville Talvalafd6ecdd2013-10-11 09:51:09 -0700324 // Will the HAL be sending in early partial result metadata?
Emilian Peev08dd2452017-04-06 16:55:14 +0100325 camera_metadata_entry partialResultsCount =
326 mDeviceInfo.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
327 if (partialResultsCount.count > 0) {
328 mNumPartialResults = partialResultsCount.data.i32[0];
329 mUsePartialResult = (mNumPartialResults > 1);
Eino-Ville Talvalafd6ecdd2013-10-11 09:51:09 -0700330 }
331
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700332 camera_metadata_entry configs =
333 mDeviceInfo.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
334 for (uint32_t i = 0; i < configs.count; i += 4) {
335 if (configs.data.i32[i] == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED &&
336 configs.data.i32[i + 3] ==
337 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT) {
338 mSupportedOpaqueInputSizes.add(Size(configs.data.i32[i + 1],
339 configs.data.i32[i + 2]));
340 }
341 }
342
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -0800343 bool usePrecorrectArray = DistortionMapper::isDistortionSupported(mDeviceInfo);
344 if (usePrecorrectArray) {
Shuzhen Wang4f6fa9d2019-03-29 10:40:35 -0700345 res = mDistortionMappers[mId.c_str()].setupStaticInfo(mDeviceInfo);
Eino-Ville Talvala7b8a1fd2018-05-22 15:30:35 -0700346 if (res != OK) {
347 SET_ERR_L("Unable to read necessary calibration fields for distortion correction");
348 return res;
349 }
350 }
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -0800351
Shuzhen Wang1c834da2019-12-18 11:17:03 -0800352 mZoomRatioMappers[mId.c_str()] = ZoomRatioMapper(&mDeviceInfo,
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -0800353 mSupportNativeZoomRatio, usePrecorrectArray);
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -0800354
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -0800355 if (RotateAndCropMapper::isNeeded(&mDeviceInfo)) {
356 mRotateAndCropMappers.emplace(mId.c_str(), &mDeviceInfo);
357 }
358
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800359 return OK;
360}
361
362status_t Camera3Device::disconnect() {
Yin-Chia Yehc5248132018-08-15 12:19:20 -0700363 return disconnectImpl();
364}
365
366status_t Camera3Device::disconnectImpl() {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800367 ATRACE_CALL();
Yin-Chia Yehe1c80632016-08-08 14:48:05 -0700368 ALOGI("%s: E", __FUNCTION__);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800369
Eino-Ville Talvala214a17f2013-06-13 12:20:02 -0700370 status_t res = OK;
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700371 std::vector<wp<Camera3StreamInterface>> streams;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700372 {
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800373 Mutex::Autolock il(mInterfaceLock);
374 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
375 {
376 Mutex::Autolock l(mLock);
377 if (mStatus == STATUS_UNINITIALIZED) return res;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700378
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800379 if (mStatus == STATUS_ACTIVE ||
380 (mStatus == STATUS_ERROR && mRequestThread != NULL)) {
381 res = mRequestThread->clearRepeatingRequests();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700382 if (res != OK) {
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800383 SET_ERR_L("Can't stop streaming");
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700384 // Continue to close device even in case of error
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800385 } else {
386 res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration);
387 if (res != OK) {
388 SET_ERR_L("Timeout waiting for HAL to drain (% " PRIi64 " ns)",
389 maxExpectedDuration);
390 // Continue to close device even in case of error
391 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700392 }
Eino-Ville Talvala214a17f2013-06-13 12:20:02 -0700393 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800394
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800395 if (mStatus == STATUS_ERROR) {
396 CLOGE("Shutting down in an error state");
397 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700398
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800399 if (mStatusTracker != NULL) {
400 mStatusTracker->requestExit();
401 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700402
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800403 if (mRequestThread != NULL) {
404 mRequestThread->requestExit();
405 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700406
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800407 streams.reserve(mOutputStreams.size() + (mInputStream != nullptr ? 1 : 0));
408 for (size_t i = 0; i < mOutputStreams.size(); i++) {
409 streams.push_back(mOutputStreams[i]);
410 }
411 if (mInputStream != nullptr) {
412 streams.push_back(mInputStream);
413 }
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700414 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700415 }
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800416 // Joining done without holding mLock and mInterfaceLock, otherwise deadlocks may ensue
417 // as the threads try to access parent state (b/143513518)
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700418 if (mRequestThread != NULL && mStatus != STATUS_ERROR) {
419 // HAL may be in a bad state, so waiting for request thread
420 // (which may be stuck in the HAL processCaptureRequest call)
421 // could be dangerous.
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800422 // give up mInterfaceLock here and then lock it again. Could this lead
423 // to other deadlocks
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700424 mRequestThread->join();
425 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700426 {
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800427 Mutex::Autolock il(mInterfaceLock);
428 if (mStatusTracker != NULL) {
429 mStatusTracker->join();
430 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800431
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800432 HalInterface* interface;
433 {
434 Mutex::Autolock l(mLock);
435 mRequestThread.clear();
436 Mutex::Autolock stLock(mTrackerLock);
437 mStatusTracker.clear();
438 interface = mInterface.get();
439 }
Eino-Ville Talvalaefff1c42015-08-28 16:27:27 -0700440
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800441 // Call close without internal mutex held, as the HAL close may need to
442 // wait on assorted callbacks,etc, to complete before it can return.
443 interface->close();
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700444
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800445 flushInflightRequests();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800446
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800447 {
448 Mutex::Autolock l(mLock);
449 mInterface->clear();
450 mOutputStreams.clear();
451 mInputStream.clear();
452 mDeletedStreams.clear();
453 mBufferManager.clear();
454 internalUpdateStatusLocked(STATUS_UNINITIALIZED);
455 }
456
457 for (auto& weakStream : streams) {
458 sp<Camera3StreamInterface> stream = weakStream.promote();
459 if (stream != nullptr) {
460 ALOGE("%s: Stream %d leaked! strong reference (%d)!",
461 __FUNCTION__, stream->getId(), stream->getStrongCount() - 1);
462 }
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700463 }
464 }
Yin-Chia Yehe1c80632016-08-08 14:48:05 -0700465 ALOGI("%s: X", __FUNCTION__);
Eino-Ville Talvala214a17f2013-06-13 12:20:02 -0700466 return res;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800467}
468
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700469// For dumping/debugging only -
470// try to acquire a lock a few times, eventually give up to proceed with
471// debug/dump operations
472bool Camera3Device::tryLockSpinRightRound(Mutex& lock) {
473 bool gotLock = false;
474 for (size_t i = 0; i < kDumpLockAttempts; ++i) {
475 if (lock.tryLock() == NO_ERROR) {
476 gotLock = true;
477 break;
478 } else {
479 usleep(kDumpSleepDuration);
480 }
481 }
482 return gotLock;
483}
484
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700485Camera3Device::Size Camera3Device::getMaxJpegResolution() const {
486 int32_t maxJpegWidth = 0, maxJpegHeight = 0;
Emilian Peev08dd2452017-04-06 16:55:14 +0100487 const int STREAM_CONFIGURATION_SIZE = 4;
488 const int STREAM_FORMAT_OFFSET = 0;
489 const int STREAM_WIDTH_OFFSET = 1;
490 const int STREAM_HEIGHT_OFFSET = 2;
491 const int STREAM_IS_INPUT_OFFSET = 3;
492 camera_metadata_ro_entry_t availableStreamConfigs =
493 mDeviceInfo.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
494 if (availableStreamConfigs.count == 0 ||
495 availableStreamConfigs.count % STREAM_CONFIGURATION_SIZE != 0) {
496 return Size(0, 0);
497 }
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700498
Emilian Peev08dd2452017-04-06 16:55:14 +0100499 // Get max jpeg size (area-wise).
500 for (size_t i=0; i < availableStreamConfigs.count; i+= STREAM_CONFIGURATION_SIZE) {
501 int32_t format = availableStreamConfigs.data.i32[i + STREAM_FORMAT_OFFSET];
502 int32_t width = availableStreamConfigs.data.i32[i + STREAM_WIDTH_OFFSET];
503 int32_t height = availableStreamConfigs.data.i32[i + STREAM_HEIGHT_OFFSET];
504 int32_t isInput = availableStreamConfigs.data.i32[i + STREAM_IS_INPUT_OFFSET];
505 if (isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT
506 && format == HAL_PIXEL_FORMAT_BLOB &&
507 (width * height > maxJpegWidth * maxJpegHeight)) {
508 maxJpegWidth = width;
509 maxJpegHeight = height;
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700510 }
511 }
Emilian Peev08dd2452017-04-06 16:55:14 +0100512
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700513 return Size(maxJpegWidth, maxJpegHeight);
514}
515
Shuzhen Wangc28dccc2016-02-11 23:48:46 -0800516nsecs_t Camera3Device::getMonoToBoottimeOffset() {
517 // try three times to get the clock offset, choose the one
518 // with the minimum gap in measurements.
519 const int tries = 3;
520 nsecs_t bestGap, measured;
521 for (int i = 0; i < tries; ++i) {
522 const nsecs_t tmono = systemTime(SYSTEM_TIME_MONOTONIC);
523 const nsecs_t tbase = systemTime(SYSTEM_TIME_BOOTTIME);
524 const nsecs_t tmono2 = systemTime(SYSTEM_TIME_MONOTONIC);
525 const nsecs_t gap = tmono2 - tmono;
526 if (i == 0 || gap < bestGap) {
527 bestGap = gap;
528 measured = tbase - ((tmono + tmono2) >> 1);
529 }
530 }
531 return measured;
532}
533
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800534hardware::graphics::common::V1_0::PixelFormat Camera3Device::mapToPixelFormat(
535 int frameworkFormat) {
536 return (hardware::graphics::common::V1_0::PixelFormat) frameworkFormat;
537}
538
539DataspaceFlags Camera3Device::mapToHidlDataspace(
540 android_dataspace dataSpace) {
541 return dataSpace;
542}
543
Chia-I Wu67a0c0e2017-04-06 13:37:01 -0700544BufferUsageFlags Camera3Device::mapToConsumerUsage(
Emilian Peev050f5dc2017-05-18 14:43:56 +0100545 uint64_t usage) {
Yin-Chia Yeh47cf8e62017-04-04 13:00:03 -0700546 return usage;
547}
548
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800549StreamRotation Camera3Device::mapToStreamRotation(camera3_stream_rotation_t rotation) {
550 switch (rotation) {
551 case CAMERA3_STREAM_ROTATION_0:
552 return StreamRotation::ROTATION_0;
553 case CAMERA3_STREAM_ROTATION_90:
554 return StreamRotation::ROTATION_90;
555 case CAMERA3_STREAM_ROTATION_180:
556 return StreamRotation::ROTATION_180;
557 case CAMERA3_STREAM_ROTATION_270:
558 return StreamRotation::ROTATION_270;
559 }
560 ALOGE("%s: Unknown stream rotation %d", __FUNCTION__, rotation);
561 return StreamRotation::ROTATION_0;
562}
563
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -0800564status_t Camera3Device::mapToStreamConfigurationMode(
565 camera3_stream_configuration_mode_t operationMode, StreamConfigurationMode *mode) {
566 if (mode == nullptr) return BAD_VALUE;
567 if (operationMode < CAMERA3_VENDOR_STREAM_CONFIGURATION_MODE_START) {
568 switch(operationMode) {
569 case CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE:
570 *mode = StreamConfigurationMode::NORMAL_MODE;
571 break;
572 case CAMERA3_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE:
573 *mode = StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE;
574 break;
575 default:
576 ALOGE("%s: Unknown stream configuration mode %d", __FUNCTION__, operationMode);
577 return BAD_VALUE;
578 }
579 } else {
580 *mode = static_cast<StreamConfigurationMode>(operationMode);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800581 }
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -0800582 return OK;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800583}
584
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800585int Camera3Device::mapToFrameworkFormat(
586 hardware::graphics::common::V1_0::PixelFormat pixelFormat) {
587 return static_cast<uint32_t>(pixelFormat);
588}
589
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -0700590android_dataspace Camera3Device::mapToFrameworkDataspace(
591 DataspaceFlags dataSpace) {
592 return static_cast<android_dataspace>(dataSpace);
593}
594
Emilian Peev050f5dc2017-05-18 14:43:56 +0100595uint64_t Camera3Device::mapConsumerToFrameworkUsage(
Chia-I Wu67a0c0e2017-04-06 13:37:01 -0700596 BufferUsageFlags usage) {
Yin-Chia Yeh47cf8e62017-04-04 13:00:03 -0700597 return usage;
598}
599
Emilian Peev050f5dc2017-05-18 14:43:56 +0100600uint64_t Camera3Device::mapProducerToFrameworkUsage(
Chia-I Wu67a0c0e2017-04-06 13:37:01 -0700601 BufferUsageFlags usage) {
Yin-Chia Yeh47cf8e62017-04-04 13:00:03 -0700602 return usage;
603}
604
Zhijun Hef7da0962014-04-24 13:27:56 -0700605ssize_t Camera3Device::getJpegBufferSize(uint32_t width, uint32_t height) const {
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700606 // Get max jpeg size (area-wise).
607 Size maxJpegResolution = getMaxJpegResolution();
608 if (maxJpegResolution.width == 0) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800609 ALOGE("%s: Camera %s: Can't find valid available jpeg sizes in static metadata!",
610 __FUNCTION__, mId.string());
Zhijun Hef7da0962014-04-24 13:27:56 -0700611 return BAD_VALUE;
612 }
613
Zhijun Hef7da0962014-04-24 13:27:56 -0700614 // Get max jpeg buffer size
615 ssize_t maxJpegBufferSize = 0;
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700616 camera_metadata_ro_entry jpegBufMaxSize = mDeviceInfo.find(ANDROID_JPEG_MAX_SIZE);
617 if (jpegBufMaxSize.count == 0) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800618 ALOGE("%s: Camera %s: Can't find maximum JPEG size in static metadata!", __FUNCTION__,
619 mId.string());
Zhijun Hef7da0962014-04-24 13:27:56 -0700620 return BAD_VALUE;
621 }
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700622 maxJpegBufferSize = jpegBufMaxSize.data.i32[0];
Yin-Chia Yeh0c4e56d2015-01-09 15:21:27 -0800623 assert(kMinJpegBufferSize < maxJpegBufferSize);
Zhijun Hef7da0962014-04-24 13:27:56 -0700624
625 // Calculate final jpeg buffer size for the given resolution.
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700626 float scaleFactor = ((float) (width * height)) /
627 (maxJpegResolution.width * maxJpegResolution.height);
Yin-Chia Yeh0c4e56d2015-01-09 15:21:27 -0800628 ssize_t jpegBufferSize = scaleFactor * (maxJpegBufferSize - kMinJpegBufferSize) +
629 kMinJpegBufferSize;
Zhijun Hef7da0962014-04-24 13:27:56 -0700630 if (jpegBufferSize > maxJpegBufferSize) {
631 jpegBufferSize = maxJpegBufferSize;
Zhijun Hef7da0962014-04-24 13:27:56 -0700632 }
633
634 return jpegBufferSize;
635}
636
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -0700637ssize_t Camera3Device::getPointCloudBufferSize() const {
638 const int FLOATS_PER_POINT=4;
639 camera_metadata_ro_entry maxPointCount = mDeviceInfo.find(ANDROID_DEPTH_MAX_DEPTH_SAMPLES);
640 if (maxPointCount.count == 0) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800641 ALOGE("%s: Camera %s: Can't find maximum depth point cloud size in static metadata!",
642 __FUNCTION__, mId.string());
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -0700643 return BAD_VALUE;
644 }
645 ssize_t maxBytesForPointCloud = sizeof(android_depth_points) +
646 maxPointCount.data.i32[0] * sizeof(float) * FLOATS_PER_POINT;
647 return maxBytesForPointCloud;
648}
649
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800650ssize_t Camera3Device::getRawOpaqueBufferSize(int32_t width, int32_t height) const {
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800651 const int PER_CONFIGURATION_SIZE = 3;
652 const int WIDTH_OFFSET = 0;
653 const int HEIGHT_OFFSET = 1;
654 const int SIZE_OFFSET = 2;
655 camera_metadata_ro_entry rawOpaqueSizes =
656 mDeviceInfo.find(ANDROID_SENSOR_OPAQUE_RAW_SIZE);
Aurimas Liutikasbc57b122016-02-16 09:59:16 -0800657 size_t count = rawOpaqueSizes.count;
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800658 if (count == 0 || (count % PER_CONFIGURATION_SIZE)) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800659 ALOGE("%s: Camera %s: bad opaque RAW size static metadata length(%zu)!",
660 __FUNCTION__, mId.string(), count);
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800661 return BAD_VALUE;
662 }
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -0700663
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800664 for (size_t i = 0; i < count; i += PER_CONFIGURATION_SIZE) {
665 if (width == rawOpaqueSizes.data.i32[i + WIDTH_OFFSET] &&
666 height == rawOpaqueSizes.data.i32[i + HEIGHT_OFFSET]) {
667 return rawOpaqueSizes.data.i32[i + SIZE_OFFSET];
668 }
669 }
670
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800671 ALOGE("%s: Camera %s: cannot find size for %dx%d opaque RAW image!",
672 __FUNCTION__, mId.string(), width, height);
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800673 return BAD_VALUE;
674}
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -0700675
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800676status_t Camera3Device::dump(int fd, const Vector<String16> &args) {
677 ATRACE_CALL();
678 (void)args;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700679
680 // Try to lock, but continue in case of failure (to avoid blocking in
681 // deadlocks)
682 bool gotInterfaceLock = tryLockSpinRightRound(mInterfaceLock);
683 bool gotLock = tryLockSpinRightRound(mLock);
684
685 ALOGW_IF(!gotInterfaceLock,
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800686 "Camera %s: %s: Unable to lock interface lock, proceeding anyway",
687 mId.string(), __FUNCTION__);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700688 ALOGW_IF(!gotLock,
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800689 "Camera %s: %s: Unable to lock main lock, proceeding anyway",
690 mId.string(), __FUNCTION__);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700691
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800692 bool dumpTemplates = false;
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700693
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800694 String16 templatesOption("-t");
695 int n = args.size();
696 for (int i = 0; i < n; i++) {
697 if (args[i] == templatesOption) {
698 dumpTemplates = true;
699 }
Emilian Peevbd8c5032018-02-14 23:05:40 +0000700 if (args[i] == TagMonitor::kMonitorOption) {
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700701 if (i + 1 < n) {
702 String8 monitorTags = String8(args[i + 1]);
703 if (monitorTags == "off") {
704 mTagMonitor.disableMonitoring();
705 } else {
706 mTagMonitor.parseTagsToMonitor(monitorTags);
707 }
708 } else {
709 mTagMonitor.disableMonitoring();
710 }
711 }
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800712 }
713
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800714 String8 lines;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800715
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800716 const char *status =
717 mStatus == STATUS_ERROR ? "ERROR" :
718 mStatus == STATUS_UNINITIALIZED ? "UNINITIALIZED" :
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700719 mStatus == STATUS_UNCONFIGURED ? "UNCONFIGURED" :
720 mStatus == STATUS_CONFIGURED ? "CONFIGURED" :
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800721 mStatus == STATUS_ACTIVE ? "ACTIVE" :
722 "Unknown";
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700723
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800724 lines.appendFormat(" Device status: %s\n", status);
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -0700725 if (mStatus == STATUS_ERROR) {
726 lines.appendFormat(" Error cause: %s\n", mErrorCause.string());
727 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800728 lines.appendFormat(" Stream configuration:\n");
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -0800729 const char *mode =
730 mOperatingMode == static_cast<int>(StreamConfigurationMode::NORMAL_MODE) ? "NORMAL" :
731 mOperatingMode == static_cast<int>(
732 StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE) ? "CONSTRAINED_HIGH_SPEED" :
733 "CUSTOM";
734 lines.appendFormat(" Operation mode: %s (%d) \n", mode, mOperatingMode);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800735
736 if (mInputStream != NULL) {
737 write(fd, lines.string(), lines.size());
738 mInputStream->dump(fd, args);
739 } else {
740 lines.appendFormat(" No input stream.\n");
741 write(fd, lines.string(), lines.size());
742 }
743 for (size_t i = 0; i < mOutputStreams.size(); i++) {
744 mOutputStreams[i]->dump(fd,args);
745 }
746
Zhijun He431503c2016-03-07 17:30:16 -0800747 if (mBufferManager != NULL) {
748 lines = String8(" Camera3 Buffer Manager:\n");
749 write(fd, lines.string(), lines.size());
750 mBufferManager->dump(fd, args);
751 }
Zhijun He125684a2015-12-26 15:07:30 -0800752
Eino-Ville Talvala42368d92013-04-09 14:13:50 -0700753 lines = String8(" In-flight requests:\n");
754 if (mInFlightMap.size() == 0) {
755 lines.append(" None\n");
756 } else {
757 for (size_t i = 0; i < mInFlightMap.size(); i++) {
758 InFlightRequest r = mInFlightMap.valueAt(i);
Colin Crosse5729fa2014-03-21 15:04:25 -0700759 lines.appendFormat(" Frame %d | Timestamp: %" PRId64 ", metadata"
Greg Kaiser51b882c2020-06-10 05:41:44 +0000760 " arrived: %s, buffers left: %d\n", mInFlightMap.keyAt(i),
Chien-Yu Chen43e69a62014-11-25 16:38:33 -0800761 r.shutterTimestamp, r.haveResultMetadata ? "true" : "false",
Greg Kaiser51b882c2020-06-10 05:41:44 +0000762 r.numBuffersLeft);
Eino-Ville Talvala42368d92013-04-09 14:13:50 -0700763 }
764 }
765 write(fd, lines.string(), lines.size());
766
Shuzhen Wang686f6442017-06-20 16:16:04 -0700767 if (mRequestThread != NULL) {
768 mRequestThread->dumpCaptureRequestLatency(fd,
769 " ProcessCaptureRequest latency histogram:");
770 }
771
Igor Murashkin1e479c02013-09-06 16:55:14 -0700772 {
773 lines = String8(" Last request sent:\n");
774 write(fd, lines.string(), lines.size());
775
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700776 CameraMetadata lastRequest = getLatestRequestLocked();
Igor Murashkin1e479c02013-09-06 16:55:14 -0700777 lastRequest.dump(fd, /*verbosity*/2, /*indentation*/6);
778 }
779
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800780 if (dumpTemplates) {
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -0800781 const char *templateNames[CAMERA3_TEMPLATE_COUNT] = {
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800782 "TEMPLATE_PREVIEW",
783 "TEMPLATE_STILL_CAPTURE",
784 "TEMPLATE_VIDEO_RECORD",
785 "TEMPLATE_VIDEO_SNAPSHOT",
786 "TEMPLATE_ZERO_SHUTTER_LAG",
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -0800787 "TEMPLATE_MANUAL",
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800788 };
789
790 for (int i = 1; i < CAMERA3_TEMPLATE_COUNT; i++) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800791 camera_metadata_t *templateRequest = nullptr;
792 mInterface->constructDefaultRequestSettings(
793 (camera3_request_template_t) i, &templateRequest);
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800794 lines = String8::format(" HAL Request %s:\n", templateNames[i-1]);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800795 if (templateRequest == nullptr) {
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800796 lines.append(" Not supported\n");
797 write(fd, lines.string(), lines.size());
798 } else {
799 write(fd, lines.string(), lines.size());
800 dump_indented_camera_metadata(templateRequest,
801 fd, /*verbosity*/2, /*indentation*/8);
802 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800803 free_camera_metadata(templateRequest);
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800804 }
805 }
806
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700807 mTagMonitor.dumpMonitoredMetadata(fd);
808
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800809 if (mInterface->valid()) {
Eino-Ville Talvalad00111e2017-01-31 11:59:12 -0800810 lines = String8(" HAL device dump:\n");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800811 write(fd, lines.string(), lines.size());
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800812 mInterface->dump(fd);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800813 }
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800814
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700815 if (gotLock) mLock.unlock();
816 if (gotInterfaceLock) mInterfaceLock.unlock();
817
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800818 return OK;
819}
820
Emilian Peevfaa4bde2020-01-23 12:19:37 -0800821const CameraMetadata& Camera3Device::infoPhysical(const String8& physicalId) const {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800822 ALOGVV("%s: E", __FUNCTION__);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800823 if (CC_UNLIKELY(mStatus == STATUS_UNINITIALIZED ||
824 mStatus == STATUS_ERROR)) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -0700825 ALOGW("%s: Access to static info %s!", __FUNCTION__,
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800826 mStatus == STATUS_ERROR ?
827 "when in error state" : "before init");
828 }
Shuzhen Wang2e7f58f2018-07-11 14:00:29 -0700829 if (physicalId.isEmpty()) {
830 return mDeviceInfo;
831 } else {
832 std::string id(physicalId.c_str());
833 if (mPhysicalDeviceInfoMap.find(id) != mPhysicalDeviceInfoMap.end()) {
834 return mPhysicalDeviceInfoMap.at(id);
835 } else {
836 ALOGE("%s: Invalid physical camera id %s", __FUNCTION__, physicalId.c_str());
837 return mDeviceInfo;
838 }
839 }
840}
841
842const CameraMetadata& Camera3Device::info() const {
843 String8 emptyId;
Emilian Peevfaa4bde2020-01-23 12:19:37 -0800844 return infoPhysical(emptyId);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800845}
846
Jianing Wei90e59c92014-03-12 18:29:36 -0700847status_t Camera3Device::checkStatusOkToCaptureLocked() {
848 switch (mStatus) {
849 case STATUS_ERROR:
850 CLOGE("Device has encountered a serious error");
851 return INVALID_OPERATION;
852 case STATUS_UNINITIALIZED:
853 CLOGE("Device not initialized");
854 return INVALID_OPERATION;
855 case STATUS_UNCONFIGURED:
856 case STATUS_CONFIGURED:
857 case STATUS_ACTIVE:
858 // OK
859 break;
860 default:
861 SET_ERR_L("Unexpected status: %d", mStatus);
862 return INVALID_OPERATION;
863 }
864 return OK;
865}
866
867status_t Camera3Device::convertMetadataListToRequestListLocked(
Emilian Peevaebbe412018-01-15 13:53:24 +0000868 const List<const PhysicalCameraSettingsList> &metadataList,
Shuzhen Wang0129d522016-10-30 22:43:41 -0700869 const std::list<const SurfaceMap> &surfaceMaps,
870 bool repeating,
Shuzhen Wang9d066012016-09-30 11:30:20 -0700871 RequestList *requestList) {
Jianing Wei90e59c92014-03-12 18:29:36 -0700872 if (requestList == NULL) {
873 CLOGE("requestList cannot be NULL.");
874 return BAD_VALUE;
875 }
876
Jianing Weicb0652e2014-03-12 18:29:36 -0700877 int32_t burstId = 0;
Emilian Peevaebbe412018-01-15 13:53:24 +0000878 List<const PhysicalCameraSettingsList>::const_iterator metadataIt = metadataList.begin();
Shuzhen Wang0129d522016-10-30 22:43:41 -0700879 std::list<const SurfaceMap>::const_iterator surfaceMapIt = surfaceMaps.begin();
880 for (; metadataIt != metadataList.end() && surfaceMapIt != surfaceMaps.end();
881 ++metadataIt, ++surfaceMapIt) {
882 sp<CaptureRequest> newRequest = setUpRequestLocked(*metadataIt, *surfaceMapIt);
Jianing Wei90e59c92014-03-12 18:29:36 -0700883 if (newRequest == 0) {
884 CLOGE("Can't create capture request");
885 return BAD_VALUE;
886 }
Jianing Weicb0652e2014-03-12 18:29:36 -0700887
Shuzhen Wang9d066012016-09-30 11:30:20 -0700888 newRequest->mRepeating = repeating;
889
Jianing Weicb0652e2014-03-12 18:29:36 -0700890 // Setup burst Id and request Id
891 newRequest->mResultExtras.burstId = burstId++;
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -0800892 auto requestIdEntry = metadataIt->begin()->metadata.find(ANDROID_REQUEST_ID);
893 if (requestIdEntry.count == 0) {
Jianing Weicb0652e2014-03-12 18:29:36 -0700894 CLOGE("RequestID does not exist in metadata");
895 return BAD_VALUE;
896 }
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -0800897 newRequest->mResultExtras.requestId = requestIdEntry.data.i32[0];
Jianing Weicb0652e2014-03-12 18:29:36 -0700898
Jianing Wei90e59c92014-03-12 18:29:36 -0700899 requestList->push_back(newRequest);
Jianing Wei2d6bb3f2014-04-11 10:00:31 -0700900
901 ALOGV("%s: requestId = %" PRId32, __FUNCTION__, newRequest->mResultExtras.requestId);
Jianing Wei90e59c92014-03-12 18:29:36 -0700902 }
Shuzhen Wang0129d522016-10-30 22:43:41 -0700903 if (metadataIt != metadataList.end() || surfaceMapIt != surfaceMaps.end()) {
904 ALOGE("%s: metadataList and surfaceMaps are not the same size!", __FUNCTION__);
905 return BAD_VALUE;
906 }
Chien-Yu Chen85a64552015-08-28 15:46:12 -0700907
908 // Setup batch size if this is a high speed video recording request.
909 if (mIsConstrainedHighSpeedConfiguration && requestList->size() > 0) {
910 auto firstRequest = requestList->begin();
911 for (auto& outputStream : (*firstRequest)->mOutputStreams) {
912 if (outputStream->isVideoStream()) {
913 (*firstRequest)->mBatchSize = requestList->size();
914 break;
915 }
916 }
917 }
918
Jianing Wei90e59c92014-03-12 18:29:36 -0700919 return OK;
920}
921
Yin-Chia Yeh7e5a2042019-02-06 16:01:06 -0800922status_t Camera3Device::capture(CameraMetadata &request, int64_t* lastFrameNumber) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800923 ATRACE_CALL();
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800924
Emilian Peevaebbe412018-01-15 13:53:24 +0000925 List<const PhysicalCameraSettingsList> requestsList;
Shuzhen Wang0129d522016-10-30 22:43:41 -0700926 std::list<const SurfaceMap> surfaceMaps;
Emilian Peevaebbe412018-01-15 13:53:24 +0000927 convertToRequestList(requestsList, surfaceMaps, request);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700928
Yin-Chia Yeh7e5a2042019-02-06 16:01:06 -0800929 return captureList(requestsList, surfaceMaps, lastFrameNumber);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700930}
931
Emilian Peevaebbe412018-01-15 13:53:24 +0000932void Camera3Device::convertToRequestList(List<const PhysicalCameraSettingsList>& requestsList,
Shuzhen Wang0129d522016-10-30 22:43:41 -0700933 std::list<const SurfaceMap>& surfaceMaps,
934 const CameraMetadata& request) {
Emilian Peevaebbe412018-01-15 13:53:24 +0000935 PhysicalCameraSettingsList requestList;
936 requestList.push_back({std::string(getId().string()), request});
937 requestsList.push_back(requestList);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700938
939 SurfaceMap surfaceMap;
940 camera_metadata_ro_entry streams = request.find(ANDROID_REQUEST_OUTPUT_STREAMS);
941 // With no surface list passed in, stream and surface will have 1-to-1
942 // mapping. So the surface index is 0 for each stream in the surfaceMap.
943 for (size_t i = 0; i < streams.count; i++) {
944 surfaceMap[streams.data.i32[i]].push_back(0);
945 }
946 surfaceMaps.push_back(surfaceMap);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800947}
948
Jianing Wei90e59c92014-03-12 18:29:36 -0700949status_t Camera3Device::submitRequestsHelper(
Emilian Peevaebbe412018-01-15 13:53:24 +0000950 const List<const PhysicalCameraSettingsList> &requests,
Shuzhen Wang0129d522016-10-30 22:43:41 -0700951 const std::list<const SurfaceMap> &surfaceMaps,
952 bool repeating,
Jianing Wei2d6bb3f2014-04-11 10:00:31 -0700953 /*out*/
954 int64_t *lastFrameNumber) {
Jianing Wei90e59c92014-03-12 18:29:36 -0700955 ATRACE_CALL();
956 Mutex::Autolock il(mInterfaceLock);
957 Mutex::Autolock l(mLock);
958
959 status_t res = checkStatusOkToCaptureLocked();
960 if (res != OK) {
961 // error logged by previous call
962 return res;
963 }
964
965 RequestList requestList;
966
Shuzhen Wang0129d522016-10-30 22:43:41 -0700967 res = convertMetadataListToRequestListLocked(requests, surfaceMaps,
968 repeating, /*out*/&requestList);
Jianing Wei90e59c92014-03-12 18:29:36 -0700969 if (res != OK) {
970 // error logged by previous call
971 return res;
972 }
973
974 if (repeating) {
Jianing Wei2d6bb3f2014-04-11 10:00:31 -0700975 res = mRequestThread->setRepeatingRequests(requestList, lastFrameNumber);
Jianing Wei90e59c92014-03-12 18:29:36 -0700976 } else {
Jianing Wei2d6bb3f2014-04-11 10:00:31 -0700977 res = mRequestThread->queueRequestList(requestList, lastFrameNumber);
Jianing Wei90e59c92014-03-12 18:29:36 -0700978 }
979
980 if (res == OK) {
981 waitUntilStateThenRelock(/*active*/true, kActiveTimeout);
982 if (res != OK) {
983 SET_ERR_L("Can't transition to active in %f seconds!",
984 kActiveTimeout/1e9);
985 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800986 ALOGV("Camera %s: Capture request %" PRId32 " enqueued", mId.string(),
Jianing Wei2d6bb3f2014-04-11 10:00:31 -0700987 (*(requestList.begin()))->mResultExtras.requestId);
Jianing Wei90e59c92014-03-12 18:29:36 -0700988 } else {
989 CLOGE("Cannot queue request. Impossible.");
990 return BAD_VALUE;
991 }
992
993 return res;
994}
995
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -0700996hardware::Return<void> Camera3Device::requestStreamBuffers(
997 const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& bufReqs,
998 requestStreamBuffers_cb _hidl_cb) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800999 RequestBufferStates states {
1000 mId, mRequestBufferInterfaceLock, mUseHalBufManager, mOutputStreams,
1001 *this, *mInterface, *this};
1002 camera3::requestStreamBuffers(states, bufReqs, _hidl_cb);
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07001003 return hardware::Void();
1004}
1005
1006hardware::Return<void> Camera3Device::returnStreamBuffers(
1007 const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer>& buffers) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001008 ReturnBufferStates states {
1009 mId, mUseHalBufManager, mOutputStreams, *mInterface};
1010 camera3::returnStreamBuffers(states, buffers);
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07001011 return hardware::Void();
1012}
1013
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001014hardware::Return<void> Camera3Device::processCaptureResult_3_4(
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001015 const hardware::hidl_vec<
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001016 hardware::camera::device::V3_4::CaptureResult>& results) {
Yin-Chia Yeh657c1872017-07-18 18:09:57 -07001017 // Ideally we should grab mLock, but that can lead to deadlock, and
1018 // it's not super important to get up to date value of mStatus for this
1019 // warning print, hence skipping the lock here
1020 if (mStatus == STATUS_ERROR) {
1021 // Per API contract, HAL should act as closed after device error
1022 // But mStatus can be set to error by framework as well, so just log
1023 // a warning here.
1024 ALOGW("%s: received capture result in error state.", __FUNCTION__);
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07001025 }
Yifan Honga640c5a2017-04-12 16:30:31 -07001026
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001027 sp<NotificationListener> listener;
1028 {
1029 std::lock_guard<std::mutex> l(mOutputLock);
1030 listener = mListener.promote();
1031 }
1032
Yifan Honga640c5a2017-04-12 16:30:31 -07001033 if (mProcessCaptureResultLock.tryLock() != OK) {
1034 // This should never happen; it indicates a wrong client implementation
1035 // that doesn't follow the contract. But, we can be tolerant here.
1036 ALOGE("%s: callback overlapped! waiting 1s...",
1037 __FUNCTION__);
1038 if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
1039 ALOGE("%s: cannot acquire lock in 1s, dropping results",
1040 __FUNCTION__);
1041 // really don't know what to do, so bail out.
1042 return hardware::Void();
1043 }
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001044 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001045 CaptureOutputStates states {
1046 mId,
Shuzhen Wangb7b42652020-05-07 11:59:02 -07001047 mInFlightLock, mLastCompletedRegularFrameNumber,
1048 mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
1049 mInFlightMap, mOutputLock, mResultQueue, mResultSignal,
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001050 mNextShutterFrameNumber,
1051 mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
1052 mNextResultFrameNumber,
1053 mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
1054 mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
1055 mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08001056 mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
1057 mTagMonitor, mInputStream, mOutputStreams, listener, *this, *this, *mInterface
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001058 };
1059
Yifan Honga640c5a2017-04-12 16:30:31 -07001060 for (const auto& result : results) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001061 processOneCaptureResultLocked(states, result.v3_2, result.physicalCameraMetadata);
Yifan Honga640c5a2017-04-12 16:30:31 -07001062 }
1063 mProcessCaptureResultLock.unlock();
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001064 return hardware::Void();
1065}
1066
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001067// Only one processCaptureResult should be called at a time, so
1068// the locks won't block. The locks are present here simply to enforce this.
1069hardware::Return<void> Camera3Device::processCaptureResult(
1070 const hardware::hidl_vec<
1071 hardware::camera::device::V3_2::CaptureResult>& results) {
1072 hardware::hidl_vec<hardware::camera::device::V3_4::PhysicalCameraMetadata> noPhysMetadata;
1073
1074 // Ideally we should grab mLock, but that can lead to deadlock, and
1075 // it's not super important to get up to date value of mStatus for this
1076 // warning print, hence skipping the lock here
1077 if (mStatus == STATUS_ERROR) {
1078 // Per API contract, HAL should act as closed after device error
1079 // But mStatus can be set to error by framework as well, so just log
1080 // a warning here.
1081 ALOGW("%s: received capture result in error state.", __FUNCTION__);
1082 }
1083
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001084 sp<NotificationListener> listener;
1085 {
1086 std::lock_guard<std::mutex> l(mOutputLock);
1087 listener = mListener.promote();
1088 }
1089
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001090 if (mProcessCaptureResultLock.tryLock() != OK) {
1091 // This should never happen; it indicates a wrong client implementation
1092 // that doesn't follow the contract. But, we can be tolerant here.
1093 ALOGE("%s: callback overlapped! waiting 1s...",
1094 __FUNCTION__);
1095 if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
1096 ALOGE("%s: cannot acquire lock in 1s, dropping results",
1097 __FUNCTION__);
1098 // really don't know what to do, so bail out.
1099 return hardware::Void();
1100 }
1101 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001102
1103 CaptureOutputStates states {
1104 mId,
Shuzhen Wangb7b42652020-05-07 11:59:02 -07001105 mInFlightLock, mLastCompletedRegularFrameNumber,
1106 mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
1107 mInFlightMap, mOutputLock, mResultQueue, mResultSignal,
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001108 mNextShutterFrameNumber,
1109 mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
1110 mNextResultFrameNumber,
1111 mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
1112 mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
1113 mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08001114 mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
1115 mTagMonitor, mInputStream, mOutputStreams, listener, *this, *this, *mInterface
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001116 };
1117
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001118 for (const auto& result : results) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001119 processOneCaptureResultLocked(states, result, noPhysMetadata);
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001120 }
1121 mProcessCaptureResultLock.unlock();
1122 return hardware::Void();
1123}
1124
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001125hardware::Return<void> Camera3Device::notify(
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001126 const hardware::hidl_vec<hardware::camera::device::V3_2::NotifyMsg>& msgs) {
Yin-Chia Yeh657c1872017-07-18 18:09:57 -07001127 // Ideally we should grab mLock, but that can lead to deadlock, and
1128 // it's not super important to get up to date value of mStatus for this
1129 // warning print, hence skipping the lock here
1130 if (mStatus == STATUS_ERROR) {
1131 // Per API contract, HAL should act as closed after device error
1132 // But mStatus can be set to error by framework as well, so just log
1133 // a warning here.
1134 ALOGW("%s: received notify message in error state.", __FUNCTION__);
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07001135 }
Yin-Chia Yeh657c1872017-07-18 18:09:57 -07001136
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001137 sp<NotificationListener> listener;
1138 {
1139 std::lock_guard<std::mutex> l(mOutputLock);
1140 listener = mListener.promote();
1141 }
1142
1143 CaptureOutputStates states {
1144 mId,
Shuzhen Wangb7b42652020-05-07 11:59:02 -07001145 mInFlightLock, mLastCompletedRegularFrameNumber,
1146 mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
1147 mInFlightMap, mOutputLock, mResultQueue, mResultSignal,
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001148 mNextShutterFrameNumber,
1149 mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
1150 mNextResultFrameNumber,
1151 mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
1152 mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
1153 mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08001154 mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
1155 mTagMonitor, mInputStream, mOutputStreams, listener, *this, *this, *mInterface
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001156 };
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001157 for (const auto& msg : msgs) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001158 camera3::notify(states, msg);
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001159 }
1160 return hardware::Void();
1161}
1162
Emilian Peevaebbe412018-01-15 13:53:24 +00001163status_t Camera3Device::captureList(const List<const PhysicalCameraSettingsList> &requestsList,
Shuzhen Wang0129d522016-10-30 22:43:41 -07001164 const std::list<const SurfaceMap> &surfaceMaps,
Jianing Weicb0652e2014-03-12 18:29:36 -07001165 int64_t *lastFrameNumber) {
Jianing Wei90e59c92014-03-12 18:29:36 -07001166 ATRACE_CALL();
1167
Emilian Peevaebbe412018-01-15 13:53:24 +00001168 return submitRequestsHelper(requestsList, surfaceMaps, /*repeating*/false, lastFrameNumber);
Jianing Wei90e59c92014-03-12 18:29:36 -07001169}
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001170
Jianing Weicb0652e2014-03-12 18:29:36 -07001171status_t Camera3Device::setStreamingRequest(const CameraMetadata &request,
1172 int64_t* /*lastFrameNumber*/) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001173 ATRACE_CALL();
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001174
Emilian Peevaebbe412018-01-15 13:53:24 +00001175 List<const PhysicalCameraSettingsList> requestsList;
Shuzhen Wang0129d522016-10-30 22:43:41 -07001176 std::list<const SurfaceMap> surfaceMaps;
Emilian Peevaebbe412018-01-15 13:53:24 +00001177 convertToRequestList(requestsList, surfaceMaps, request);
Shuzhen Wang0129d522016-10-30 22:43:41 -07001178
Emilian Peevaebbe412018-01-15 13:53:24 +00001179 return setStreamingRequestList(requestsList, /*surfaceMap*/surfaceMaps,
Shuzhen Wang0129d522016-10-30 22:43:41 -07001180 /*lastFrameNumber*/NULL);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001181}
1182
Emilian Peevaebbe412018-01-15 13:53:24 +00001183status_t Camera3Device::setStreamingRequestList(
1184 const List<const PhysicalCameraSettingsList> &requestsList,
1185 const std::list<const SurfaceMap> &surfaceMaps, int64_t *lastFrameNumber) {
Jianing Wei90e59c92014-03-12 18:29:36 -07001186 ATRACE_CALL();
1187
Emilian Peevaebbe412018-01-15 13:53:24 +00001188 return submitRequestsHelper(requestsList, surfaceMaps, /*repeating*/true, lastFrameNumber);
Jianing Wei90e59c92014-03-12 18:29:36 -07001189}
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001190
1191sp<Camera3Device::CaptureRequest> Camera3Device::setUpRequestLocked(
Emilian Peevaebbe412018-01-15 13:53:24 +00001192 const PhysicalCameraSettingsList &request, const SurfaceMap &surfaceMap) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001193 status_t res;
1194
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001195 if (mStatus == STATUS_UNCONFIGURED || mNeedConfig) {
Eino-Ville Talvalae7091aa2017-03-07 15:23:06 -08001196 // This point should only be reached via API1 (API2 must explicitly call configureStreams)
1197 // so unilaterally select normal operating mode.
Emilian Peevaebbe412018-01-15 13:53:24 +00001198 res = filterParamsAndConfigureLocked(request.begin()->metadata,
1199 CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE);
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07001200 // Stream configuration failed. Client might try other configuraitons.
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001201 if (res != OK) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07001202 CLOGE("Can't set up streams: %s (%d)", strerror(-res), res);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001203 return NULL;
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07001204 } else if (mStatus == STATUS_UNCONFIGURED) {
1205 // Stream configuration successfully configure to empty stream configuration.
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001206 CLOGE("No streams configured");
1207 return NULL;
1208 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001209 }
1210
Shuzhen Wang0129d522016-10-30 22:43:41 -07001211 sp<CaptureRequest> newRequest = createCaptureRequest(request, surfaceMap);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001212 return newRequest;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001213}
1214
Jianing Weicb0652e2014-03-12 18:29:36 -07001215status_t Camera3Device::clearStreamingRequest(int64_t *lastFrameNumber) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001216 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001217 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001218 Mutex::Autolock l(mLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001219
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001220 switch (mStatus) {
1221 case STATUS_ERROR:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001222 CLOGE("Device has encountered a serious error");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001223 return INVALID_OPERATION;
1224 case STATUS_UNINITIALIZED:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001225 CLOGE("Device not initialized");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001226 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001227 case STATUS_UNCONFIGURED:
1228 case STATUS_CONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001229 case STATUS_ACTIVE:
1230 // OK
1231 break;
1232 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001233 SET_ERR_L("Unexpected status: %d", mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001234 return INVALID_OPERATION;
1235 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001236 ALOGV("Camera %s: Clearing repeating request", mId.string());
Jianing Weicb0652e2014-03-12 18:29:36 -07001237
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07001238 return mRequestThread->clearRepeatingRequests(lastFrameNumber);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001239}
1240
1241status_t Camera3Device::waitUntilRequestReceived(int32_t requestId, nsecs_t timeout) {
1242 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001243 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001244
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001245 return mRequestThread->waitUntilRequestProcessed(requestId, timeout);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001246}
1247
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001248status_t Camera3Device::createInputStream(
1249 uint32_t width, uint32_t height, int format, int *id) {
1250 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001251 Mutex::Autolock il(mInterfaceLock);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001252 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001253 Mutex::Autolock l(mLock);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001254 ALOGV("Camera %s: Creating new input stream %d: %d x %d, format %d",
1255 mId.string(), mNextStreamId, width, height, format);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001256
1257 status_t res;
1258 bool wasActive = false;
1259
1260 switch (mStatus) {
1261 case STATUS_ERROR:
1262 ALOGE("%s: Device has encountered a serious error", __FUNCTION__);
1263 return INVALID_OPERATION;
1264 case STATUS_UNINITIALIZED:
1265 ALOGE("%s: Device not initialized", __FUNCTION__);
1266 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001267 case STATUS_UNCONFIGURED:
1268 case STATUS_CONFIGURED:
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001269 // OK
1270 break;
1271 case STATUS_ACTIVE:
1272 ALOGV("%s: Stopping activity to reconfigure streams", __FUNCTION__);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001273 res = internalPauseAndWaitLocked(maxExpectedDuration);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001274 if (res != OK) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001275 SET_ERR_L("Can't pause captures to reconfigure streams!");
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001276 return res;
1277 }
1278 wasActive = true;
1279 break;
1280 default:
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001281 SET_ERR_L("%s: Unexpected status: %d", mStatus);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001282 return INVALID_OPERATION;
1283 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001284 assert(mStatus != STATUS_ACTIVE);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001285
1286 if (mInputStream != 0) {
1287 ALOGE("%s: Cannot create more than 1 input stream", __FUNCTION__);
1288 return INVALID_OPERATION;
1289 }
1290
1291 sp<Camera3InputStream> newStream = new Camera3InputStream(mNextStreamId,
1292 width, height, format);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001293 newStream->setStatusTracker(mStatusTracker);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001294
1295 mInputStream = newStream;
1296
1297 *id = mNextStreamId++;
1298
1299 // Continue captures if active at start
1300 if (wasActive) {
1301 ALOGV("%s: Restarting activity to reconfigure streams", __FUNCTION__);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001302 // Reuse current operating mode and session parameters for new stream config
1303 res = configureStreamsLocked(mOperatingMode, mSessionParams);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001304 if (res != OK) {
1305 ALOGE("%s: Can't reconfigure device for new stream %d: %s (%d)",
1306 __FUNCTION__, mNextStreamId, strerror(-res), res);
1307 return res;
1308 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001309 internalResumeLocked();
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001310 }
1311
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001312 ALOGV("Camera %s: Created input stream", mId.string());
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001313 return OK;
1314}
1315
Eino-Ville Talvala727d1722015-06-09 13:44:19 -07001316status_t Camera3Device::createStream(sp<Surface> consumer,
Shuzhen Wang0129d522016-10-30 22:43:41 -07001317 uint32_t width, uint32_t height, int format,
1318 android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001319 const String8& physicalCameraId,
Emilian Peev40ead602017-09-26 15:46:36 +01001320 std::vector<int> *surfaceIds, int streamSetId, bool isShared, uint64_t consumerUsage) {
Shuzhen Wang0129d522016-10-30 22:43:41 -07001321 ATRACE_CALL();
1322
1323 if (consumer == nullptr) {
1324 ALOGE("%s: consumer must not be null", __FUNCTION__);
1325 return BAD_VALUE;
1326 }
1327
1328 std::vector<sp<Surface>> consumers;
1329 consumers.push_back(consumer);
1330
1331 return createStream(consumers, /*hasDeferredConsumer*/ false, width, height,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001332 format, dataSpace, rotation, id, physicalCameraId, surfaceIds, streamSetId,
1333 isShared, consumerUsage);
Shuzhen Wang0129d522016-10-30 22:43:41 -07001334}
1335
1336status_t Camera3Device::createStream(const std::vector<sp<Surface>>& consumers,
1337 bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
1338 android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001339 const String8& physicalCameraId,
Emilian Peev40ead602017-09-26 15:46:36 +01001340 std::vector<int> *surfaceIds, int streamSetId, bool isShared, uint64_t consumerUsage) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001341 ATRACE_CALL();
Emilian Peev40ead602017-09-26 15:46:36 +01001342
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001343 Mutex::Autolock il(mInterfaceLock);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001344 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001345 Mutex::Autolock l(mLock);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001346 ALOGV("Camera %s: Creating new stream %d: %d x %d, format %d, dataspace %d rotation %d"
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001347 " consumer usage %" PRIu64 ", isShared %d, physicalCameraId %s", mId.string(),
1348 mNextStreamId, width, height, format, dataSpace, rotation, consumerUsage, isShared,
1349 physicalCameraId.string());
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001350
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001351 status_t res;
1352 bool wasActive = false;
1353
1354 switch (mStatus) {
1355 case STATUS_ERROR:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001356 CLOGE("Device has encountered a serious error");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001357 return INVALID_OPERATION;
1358 case STATUS_UNINITIALIZED:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001359 CLOGE("Device not initialized");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001360 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001361 case STATUS_UNCONFIGURED:
1362 case STATUS_CONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001363 // OK
1364 break;
1365 case STATUS_ACTIVE:
1366 ALOGV("%s: Stopping activity to reconfigure streams", __FUNCTION__);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001367 res = internalPauseAndWaitLocked(maxExpectedDuration);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001368 if (res != OK) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001369 SET_ERR_L("Can't pause captures to reconfigure streams!");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001370 return res;
1371 }
1372 wasActive = true;
1373 break;
1374 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001375 SET_ERR_L("Unexpected status: %d", mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001376 return INVALID_OPERATION;
1377 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001378 assert(mStatus != STATUS_ACTIVE);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001379
1380 sp<Camera3OutputStream> newStream;
Zhijun He5d677d12016-05-29 16:52:39 -07001381
Shuzhen Wang0129d522016-10-30 22:43:41 -07001382 if (consumers.size() == 0 && !hasDeferredConsumer) {
1383 ALOGE("%s: Number of consumers cannot be smaller than 1", __FUNCTION__);
1384 return BAD_VALUE;
1385 }
Zhijun He5d677d12016-05-29 16:52:39 -07001386
Shuzhen Wang0129d522016-10-30 22:43:41 -07001387 if (hasDeferredConsumer && format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
Zhijun He5d677d12016-05-29 16:52:39 -07001388 ALOGE("Deferred consumer stream creation only support IMPLEMENTATION_DEFINED format");
1389 return BAD_VALUE;
1390 }
1391
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001392 if (format == HAL_PIXEL_FORMAT_BLOB) {
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -07001393 ssize_t blobBufferSize;
Shuzhen Wang68ac7ad2019-01-30 14:03:28 -08001394 if (dataSpace == HAL_DATASPACE_DEPTH) {
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -07001395 blobBufferSize = getPointCloudBufferSize();
1396 if (blobBufferSize <= 0) {
1397 SET_ERR_L("Invalid point cloud buffer size %zd", blobBufferSize);
1398 return BAD_VALUE;
1399 }
Shuzhen Wang68ac7ad2019-01-30 14:03:28 -08001400 } else if (dataSpace == static_cast<android_dataspace>(HAL_DATASPACE_JPEG_APP_SEGMENTS)) {
1401 blobBufferSize = width * height;
1402 } else {
1403 blobBufferSize = getJpegBufferSize(width, height);
1404 if (blobBufferSize <= 0) {
1405 SET_ERR_L("Invalid jpeg buffer size %zd", blobBufferSize);
1406 return BAD_VALUE;
1407 }
Zhijun Hef7da0962014-04-24 13:27:56 -07001408 }
Shuzhen Wang0129d522016-10-30 22:43:41 -07001409 newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
Shuzhen Wangc28dccc2016-02-11 23:48:46 -08001410 width, height, blobBufferSize, format, dataSpace, rotation,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001411 mTimestampOffset, physicalCameraId, streamSetId);
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -08001412 } else if (format == HAL_PIXEL_FORMAT_RAW_OPAQUE) {
1413 ssize_t rawOpaqueBufferSize = getRawOpaqueBufferSize(width, height);
1414 if (rawOpaqueBufferSize <= 0) {
1415 SET_ERR_L("Invalid RAW opaque buffer size %zd", rawOpaqueBufferSize);
1416 return BAD_VALUE;
1417 }
Shuzhen Wang0129d522016-10-30 22:43:41 -07001418 newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
Shuzhen Wangc28dccc2016-02-11 23:48:46 -08001419 width, height, rawOpaqueBufferSize, format, dataSpace, rotation,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001420 mTimestampOffset, physicalCameraId, streamSetId);
Shuzhen Wang758c2152017-01-10 18:26:18 -08001421 } else if (isShared) {
1422 newStream = new Camera3SharedOutputStream(mNextStreamId, consumers,
1423 width, height, format, consumerUsage, dataSpace, rotation,
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07001424 mTimestampOffset, physicalCameraId, streamSetId,
1425 mUseHalBufManager);
Shuzhen Wang0129d522016-10-30 22:43:41 -07001426 } else if (consumers.size() == 0 && hasDeferredConsumer) {
Zhijun He5d677d12016-05-29 16:52:39 -07001427 newStream = new Camera3OutputStream(mNextStreamId,
1428 width, height, format, consumerUsage, dataSpace, rotation,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001429 mTimestampOffset, physicalCameraId, streamSetId);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001430 } else {
Shuzhen Wang0129d522016-10-30 22:43:41 -07001431 newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
Shuzhen Wangc28dccc2016-02-11 23:48:46 -08001432 width, height, format, dataSpace, rotation,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001433 mTimestampOffset, physicalCameraId, streamSetId);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001434 }
Emilian Peev40ead602017-09-26 15:46:36 +01001435
1436 size_t consumerCount = consumers.size();
1437 for (size_t i = 0; i < consumerCount; i++) {
1438 int id = newStream->getSurfaceId(consumers[i]);
1439 if (id < 0) {
1440 SET_ERR_L("Invalid surface id");
1441 return BAD_VALUE;
1442 }
1443 if (surfaceIds != nullptr) {
1444 surfaceIds->push_back(id);
1445 }
1446 }
1447
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001448 newStream->setStatusTracker(mStatusTracker);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001449
Emilian Peev08dd2452017-04-06 16:55:14 +01001450 newStream->setBufferManager(mBufferManager);
Zhijun He125684a2015-12-26 15:07:30 -08001451
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001452 res = mOutputStreams.add(mNextStreamId, newStream);
1453 if (res < 0) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001454 SET_ERR_L("Can't add new stream to set: %s (%d)", strerror(-res), res);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001455 return res;
1456 }
1457
1458 *id = mNextStreamId++;
Eino-Ville Talvalaea26c772013-06-11 16:04:06 -07001459 mNeedConfig = true;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001460
1461 // Continue captures if active at start
1462 if (wasActive) {
1463 ALOGV("%s: Restarting activity to reconfigure streams", __FUNCTION__);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001464 // Reuse current operating mode and session parameters for new stream config
1465 res = configureStreamsLocked(mOperatingMode, mSessionParams);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001466 if (res != OK) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001467 CLOGE("Can't reconfigure device for new stream %d: %s (%d)",
1468 mNextStreamId, strerror(-res), res);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001469 return res;
1470 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001471 internalResumeLocked();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001472 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001473 ALOGV("Camera %s: Created new stream", mId.string());
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001474 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001475}
1476
Emilian Peev710c1422017-08-30 11:19:38 +01001477status_t Camera3Device::getStreamInfo(int id, StreamInfo *streamInfo) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001478 ATRACE_CALL();
Emilian Peev710c1422017-08-30 11:19:38 +01001479 if (nullptr == streamInfo) {
1480 return BAD_VALUE;
1481 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001482 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001483 Mutex::Autolock l(mLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001484
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001485 switch (mStatus) {
1486 case STATUS_ERROR:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001487 CLOGE("Device has encountered a serious error");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001488 return INVALID_OPERATION;
1489 case STATUS_UNINITIALIZED:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001490 CLOGE("Device not initialized!");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001491 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001492 case STATUS_UNCONFIGURED:
1493 case STATUS_CONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001494 case STATUS_ACTIVE:
1495 // OK
1496 break;
1497 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001498 SET_ERR_L("Unexpected status: %d", mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001499 return INVALID_OPERATION;
1500 }
1501
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001502 sp<Camera3StreamInterface> stream = mOutputStreams.get(id);
1503 if (stream == nullptr) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001504 CLOGE("Stream %d is unknown", id);
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001505 return BAD_VALUE;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001506 }
1507
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001508 streamInfo->width = stream->getWidth();
1509 streamInfo->height = stream->getHeight();
1510 streamInfo->format = stream->getFormat();
1511 streamInfo->dataSpace = stream->getDataSpace();
1512 streamInfo->formatOverridden = stream->isFormatOverridden();
1513 streamInfo->originalFormat = stream->getOriginalFormat();
1514 streamInfo->dataSpaceOverridden = stream->isDataSpaceOverridden();
1515 streamInfo->originalDataSpace = stream->getOriginalDataSpace();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001516 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001517}
1518
1519status_t Camera3Device::setStreamTransform(int id,
1520 int transform) {
1521 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001522 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001523 Mutex::Autolock l(mLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001524
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001525 switch (mStatus) {
1526 case STATUS_ERROR:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001527 CLOGE("Device has encountered a serious error");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001528 return INVALID_OPERATION;
1529 case STATUS_UNINITIALIZED:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001530 CLOGE("Device not initialized");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001531 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001532 case STATUS_UNCONFIGURED:
1533 case STATUS_CONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001534 case STATUS_ACTIVE:
1535 // OK
1536 break;
1537 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001538 SET_ERR_L("Unexpected status: %d", mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001539 return INVALID_OPERATION;
1540 }
1541
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001542 sp<Camera3OutputStreamInterface> stream = mOutputStreams.get(id);
1543 if (stream == nullptr) {
1544 CLOGE("Stream %d does not exist", id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001545 return BAD_VALUE;
1546 }
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001547 return stream->setTransform(transform);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001548}
1549
1550status_t Camera3Device::deleteStream(int id) {
1551 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001552 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001553 Mutex::Autolock l(mLock);
1554 status_t res;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001555
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001556 ALOGV("%s: Camera %s: Deleting stream %d", __FUNCTION__, mId.string(), id);
Igor Murashkine2172be2013-05-28 15:31:39 -07001557
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001558 // CameraDevice semantics require device to already be idle before
1559 // deleteStream is called, unlike for createStream.
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001560 if (mStatus == STATUS_ACTIVE) {
Yin-Chia Yeh693047d2018-03-08 12:14:19 -08001561 ALOGW("%s: Camera %s: Device not idle", __FUNCTION__, mId.string());
Igor Murashkin52827132013-05-13 14:53:44 -07001562 return -EBUSY;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001563 }
1564
Yin-Chia Yeh5090c732017-07-20 16:05:29 -07001565 if (mStatus == STATUS_ERROR) {
1566 ALOGW("%s: Camera %s: deleteStream not allowed in ERROR state",
1567 __FUNCTION__, mId.string());
1568 return -EBUSY;
1569 }
1570
Igor Murashkin2fba5842013-04-22 14:03:54 -07001571 sp<Camera3StreamInterface> deletedStream;
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001572 sp<Camera3StreamInterface> stream = mOutputStreams.get(id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001573 if (mInputStream != NULL && id == mInputStream->getId()) {
1574 deletedStream = mInputStream;
1575 mInputStream.clear();
1576 } else {
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001577 if (stream == nullptr) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001578 CLOGE("Stream %d does not exist", id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001579 return BAD_VALUE;
1580 }
Zhijun He5f446352014-01-22 09:49:33 -08001581 }
1582
1583 // Delete output stream or the output part of a bi-directional stream.
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001584 if (stream != nullptr) {
1585 deletedStream = stream;
1586 mOutputStreams.remove(id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001587 }
1588
1589 // Free up the stream endpoint so that it can be used by some other stream
1590 res = deletedStream->disconnect();
1591 if (res != OK) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001592 SET_ERR_L("Can't disconnect deleted stream %d", id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001593 // fall through since we want to still list the stream as deleted.
1594 }
1595 mDeletedStreams.add(deletedStream);
Eino-Ville Talvalaea26c772013-06-11 16:04:06 -07001596 mNeedConfig = true;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001597
1598 return res;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001599}
1600
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001601status_t Camera3Device::configureStreams(const CameraMetadata& sessionParams, int operatingMode) {
Igor Murashkine2d167e2014-08-19 16:19:59 -07001602 ATRACE_CALL();
1603 ALOGV("%s: E", __FUNCTION__);
1604
1605 Mutex::Autolock il(mInterfaceLock);
1606 Mutex::Autolock l(mLock);
Chien-Yu Chen17338fc2015-06-18 16:30:12 -07001607
Emilian Peev811d2952018-05-25 11:08:40 +01001608 // In case the client doesn't include any session parameter, try a
1609 // speculative configuration using the values from the last cached
1610 // default request.
1611 if (sessionParams.isEmpty() &&
1612 ((mLastTemplateId > 0) && (mLastTemplateId < CAMERA3_TEMPLATE_COUNT)) &&
1613 (!mRequestTemplateCache[mLastTemplateId].isEmpty())) {
1614 ALOGV("%s: Speculative session param configuration with template id: %d", __func__,
1615 mLastTemplateId);
1616 return filterParamsAndConfigureLocked(mRequestTemplateCache[mLastTemplateId],
1617 operatingMode);
1618 }
1619
Emilian Peevac3ce6c2017-12-12 15:27:02 +00001620 return filterParamsAndConfigureLocked(sessionParams, operatingMode);
1621}
1622
1623status_t Camera3Device::filterParamsAndConfigureLocked(const CameraMetadata& sessionParams,
1624 int operatingMode) {
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001625 //Filter out any incoming session parameters
1626 const CameraMetadata params(sessionParams);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001627 camera_metadata_entry_t availableSessionKeys = mDeviceInfo.find(
1628 ANDROID_REQUEST_AVAILABLE_SESSION_KEYS);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00001629 CameraMetadata filteredParams(availableSessionKeys.count);
1630 camera_metadata_t *meta = const_cast<camera_metadata_t *>(
1631 filteredParams.getAndLock());
1632 set_camera_metadata_vendor_id(meta, mVendorTagId);
1633 filteredParams.unlock(meta);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001634 if (availableSessionKeys.count > 0) {
1635 for (size_t i = 0; i < availableSessionKeys.count; i++) {
1636 camera_metadata_ro_entry entry = params.find(
1637 availableSessionKeys.data.i32[i]);
1638 if (entry.count > 0) {
1639 filteredParams.update(entry);
1640 }
1641 }
1642 }
1643
1644 return configureStreamsLocked(operatingMode, filteredParams);
Igor Murashkine2d167e2014-08-19 16:19:59 -07001645}
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001646
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -07001647status_t Camera3Device::getInputBufferProducer(
1648 sp<IGraphicBufferProducer> *producer) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07001649 ATRACE_CALL();
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -07001650 Mutex::Autolock il(mInterfaceLock);
1651 Mutex::Autolock l(mLock);
1652
1653 if (producer == NULL) {
1654 return BAD_VALUE;
1655 } else if (mInputStream == NULL) {
1656 return INVALID_OPERATION;
1657 }
1658
1659 return mInputStream->getInputBufferProducer(producer);
1660}
1661
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001662status_t Camera3Device::createDefaultRequest(int templateId,
1663 CameraMetadata *request) {
1664 ATRACE_CALL();
Alex Rayfe7e0c62013-05-30 00:12:13 -07001665 ALOGV("%s: for template %d", __FUNCTION__, templateId);
Chien-Yu Chen9cd14022016-03-09 12:21:01 -08001666
1667 if (templateId <= 0 || templateId >= CAMERA3_TEMPLATE_COUNT) {
1668 android_errorWriteWithInfoLog(CameraService::SN_EVENT_LOG_ID, "26866110",
Jayant Chowdhary12361932018-08-27 14:46:13 -07001669 CameraThreadState::getCallingUid(), nullptr, 0);
Chien-Yu Chen9cd14022016-03-09 12:21:01 -08001670 return BAD_VALUE;
1671 }
1672
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001673 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001674
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001675 {
1676 Mutex::Autolock l(mLock);
1677 switch (mStatus) {
1678 case STATUS_ERROR:
1679 CLOGE("Device has encountered a serious error");
1680 return INVALID_OPERATION;
1681 case STATUS_UNINITIALIZED:
1682 CLOGE("Device is not initialized!");
1683 return INVALID_OPERATION;
1684 case STATUS_UNCONFIGURED:
1685 case STATUS_CONFIGURED:
1686 case STATUS_ACTIVE:
1687 // OK
1688 break;
1689 default:
1690 SET_ERR_L("Unexpected status: %d", mStatus);
1691 return INVALID_OPERATION;
1692 }
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001693
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001694 if (!mRequestTemplateCache[templateId].isEmpty()) {
1695 *request = mRequestTemplateCache[templateId];
Emilian Peev811d2952018-05-25 11:08:40 +01001696 mLastTemplateId = templateId;
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001697 return OK;
1698 }
Zhijun Hea1530f12014-09-14 12:44:20 -07001699 }
1700
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001701 camera_metadata_t *rawRequest;
1702 status_t res = mInterface->constructDefaultRequestSettings(
1703 (camera3_request_template_t) templateId, &rawRequest);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001704
1705 {
1706 Mutex::Autolock l(mLock);
1707 if (res == BAD_VALUE) {
1708 ALOGI("%s: template %d is not supported on this camera device",
1709 __FUNCTION__, templateId);
1710 return res;
1711 } else if (res != OK) {
1712 CLOGE("Unable to construct request template %d: %s (%d)",
1713 templateId, strerror(-res), res);
1714 return res;
1715 }
1716
1717 set_camera_metadata_vendor_id(rawRequest, mVendorTagId);
1718 mRequestTemplateCache[templateId].acquire(rawRequest);
1719
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08001720 // Override the template request with zoomRatioMapper
1721 res = mZoomRatioMappers[mId.c_str()].initZoomRatioInTemplate(
1722 &mRequestTemplateCache[templateId]);
1723 if (res != OK) {
1724 CLOGE("Failed to update zoom ratio for template %d: %s (%d)",
1725 templateId, strerror(-res), res);
1726 return res;
1727 }
1728
Shuzhen Wangd25dc972020-03-24 17:11:43 -07001729 // Fill in JPEG_QUALITY if not available
1730 if (!mRequestTemplateCache[templateId].exists(ANDROID_JPEG_QUALITY)) {
1731 static const uint8_t kDefaultJpegQuality = 95;
1732 mRequestTemplateCache[templateId].update(ANDROID_JPEG_QUALITY,
1733 &kDefaultJpegQuality, 1);
1734 }
1735
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001736 *request = mRequestTemplateCache[templateId];
Emilian Peev811d2952018-05-25 11:08:40 +01001737 mLastTemplateId = templateId;
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001738 }
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001739 return OK;
1740}
1741
1742status_t Camera3Device::waitUntilDrained() {
1743 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001744 Mutex::Autolock il(mInterfaceLock);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001745 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001746 Mutex::Autolock l(mLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001747
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001748 return waitUntilDrainedLocked(maxExpectedDuration);
Zhijun He69a37482014-03-23 18:44:49 -07001749}
1750
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001751status_t Camera3Device::waitUntilDrainedLocked(nsecs_t maxExpectedDuration) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001752 switch (mStatus) {
1753 case STATUS_UNINITIALIZED:
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001754 case STATUS_UNCONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001755 ALOGV("%s: Already idle", __FUNCTION__);
1756 return OK;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001757 case STATUS_CONFIGURED:
1758 // To avoid race conditions, check with tracker to be sure
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001759 case STATUS_ERROR:
1760 case STATUS_ACTIVE:
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001761 // Need to verify shut down
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001762 break;
1763 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001764 SET_ERR_L("Unexpected status: %d",mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001765 return INVALID_OPERATION;
1766 }
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07001767 ALOGV("%s: Camera %s: Waiting until idle (%" PRIi64 "ns)", __FUNCTION__, mId.string(),
1768 maxExpectedDuration);
1769 status_t res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration);
Eino-Ville Talvala9c8a0912014-09-14 14:52:19 -07001770 if (res != OK) {
1771 SET_ERR_L("Error waiting for HAL to drain: %s (%d)", strerror(-res),
1772 res);
1773 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001774 return res;
1775}
1776
Ruben Brunk183f0562015-08-12 12:55:02 -07001777
1778void Camera3Device::internalUpdateStatusLocked(Status status) {
1779 mStatus = status;
1780 mRecentStatusUpdates.add(mStatus);
1781 mStatusChanged.broadcast();
1782}
1783
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001784// Pause to reconfigure
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001785status_t Camera3Device::internalPauseAndWaitLocked(nsecs_t maxExpectedDuration) {
Emilian Peeve86358b2019-02-15 13:51:39 -08001786 if (mRequestThread.get() != nullptr) {
1787 mRequestThread->setPaused(true);
1788 } else {
1789 return NO_INIT;
1790 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001791
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07001792 ALOGV("%s: Camera %s: Internal wait until idle (% " PRIi64 " ns)", __FUNCTION__, mId.string(),
1793 maxExpectedDuration);
1794 status_t res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001795 if (res != OK) {
1796 SET_ERR_L("Can't idle device in %f seconds!",
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07001797 maxExpectedDuration/1e9);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001798 }
1799
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001800 return res;
1801}
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001802
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001803// Resume after internalPauseAndWaitLocked
1804status_t Camera3Device::internalResumeLocked() {
1805 status_t res;
1806
1807 mRequestThread->setPaused(false);
1808
Eino-Ville Talvala002001b2018-01-23 16:53:50 -08001809 ALOGV("%s: Camera %s: Internal wait until active (% " PRIi64 " ns)", __FUNCTION__, mId.string(),
1810 kActiveTimeout);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001811 res = waitUntilStateThenRelock(/*active*/ true, kActiveTimeout);
1812 if (res != OK) {
1813 SET_ERR_L("Can't transition to active in %f seconds!",
1814 kActiveTimeout/1e9);
1815 }
1816 mPauseStateNotify = false;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001817 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001818}
1819
Ruben Brunk183f0562015-08-12 12:55:02 -07001820status_t Camera3Device::waitUntilStateThenRelock(bool active, nsecs_t timeout) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001821 status_t res = OK;
Ruben Brunk183f0562015-08-12 12:55:02 -07001822
1823 size_t startIndex = 0;
1824 if (mStatusWaiters == 0) {
1825 // Clear the list of recent statuses if there are no existing threads waiting on updates to
1826 // this status list
1827 mRecentStatusUpdates.clear();
1828 } else {
1829 // If other threads are waiting on updates to this status list, set the position of the
1830 // first element that this list will check rather than clearing the list.
1831 startIndex = mRecentStatusUpdates.size();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001832 }
1833
Ruben Brunk183f0562015-08-12 12:55:02 -07001834 mStatusWaiters++;
1835
Yin-Chia Yehe52b8fa2020-07-28 00:17:58 -07001836 bool signalPipelineDrain = false;
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07001837 if (!active && mUseHalBufManager) {
1838 auto streamIds = mOutputStreams.getStreamIds();
Yin-Chia Yehcd333fe2019-02-08 13:45:41 -08001839 if (mStatus == STATUS_ACTIVE) {
1840 mRequestThread->signalPipelineDrain(streamIds);
Yin-Chia Yehe52b8fa2020-07-28 00:17:58 -07001841 signalPipelineDrain = true;
Yin-Chia Yehcd333fe2019-02-08 13:45:41 -08001842 }
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07001843 mRequestBufferSM.onWaitUntilIdle();
1844 }
1845
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001846 bool stateSeen = false;
1847 do {
Ruben Brunk183f0562015-08-12 12:55:02 -07001848 if (active == (mStatus == STATUS_ACTIVE)) {
1849 // Desired state is current
1850 break;
1851 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001852
1853 res = mStatusChanged.waitRelative(mLock, timeout);
1854 if (res != OK) break;
1855
Ruben Brunk183f0562015-08-12 12:55:02 -07001856 // This is impossible, but if not, could result in subtle deadlocks and invalid state
1857 // transitions.
1858 LOG_ALWAYS_FATAL_IF(startIndex > mRecentStatusUpdates.size(),
1859 "%s: Skipping status updates in Camera3Device, may result in deadlock.",
1860 __FUNCTION__);
1861
1862 // Encountered desired state since we began waiting
1863 for (size_t i = startIndex; i < mRecentStatusUpdates.size(); i++) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001864 if (active == (mRecentStatusUpdates[i] == STATUS_ACTIVE) ) {
1865 stateSeen = true;
1866 break;
1867 }
1868 }
1869 } while (!stateSeen);
1870
Yin-Chia Yehe52b8fa2020-07-28 00:17:58 -07001871 if (signalPipelineDrain) {
1872 mRequestThread->resetPipelineDrain();
1873 }
1874
Ruben Brunk183f0562015-08-12 12:55:02 -07001875 mStatusWaiters--;
1876
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001877 return res;
1878}
1879
1880
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07001881status_t Camera3Device::setNotifyCallback(wp<NotificationListener> listener) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001882 ATRACE_CALL();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001883 std::lock_guard<std::mutex> l(mOutputLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001884
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001885 if (listener != NULL && mListener != NULL) {
1886 ALOGW("%s: Replacing old callback listener", __FUNCTION__);
1887 }
1888 mListener = listener;
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07001889 mRequestThread->setNotificationListener(listener);
1890 mPreparerThread->setNotificationListener(listener);
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001891
1892 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001893}
1894
Eino-Ville Talvala46910bd2013-07-18 19:15:17 -07001895bool Camera3Device::willNotify3A() {
1896 return false;
1897}
1898
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001899status_t Camera3Device::waitForNextFrame(nsecs_t timeout) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07001900 ATRACE_CALL();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001901 std::unique_lock<std::mutex> l(mOutputLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001902
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001903 while (mResultQueue.empty()) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001904 auto st = mResultSignal.wait_for(l, std::chrono::nanoseconds(timeout));
1905 if (st == std::cv_status::timeout) {
1906 return TIMED_OUT;
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001907 }
1908 }
1909 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001910}
1911
Jianing Weicb0652e2014-03-12 18:29:36 -07001912status_t Camera3Device::getNextResult(CaptureResult *frame) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001913 ATRACE_CALL();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001914 std::lock_guard<std::mutex> l(mOutputLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001915
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001916 if (mResultQueue.empty()) {
1917 return NOT_ENOUGH_DATA;
1918 }
1919
Jianing Weicb0652e2014-03-12 18:29:36 -07001920 if (frame == NULL) {
1921 ALOGE("%s: argument cannot be NULL", __FUNCTION__);
1922 return BAD_VALUE;
1923 }
1924
1925 CaptureResult &result = *(mResultQueue.begin());
1926 frame->mResultExtras = result.mResultExtras;
1927 frame->mMetadata.acquire(result.mMetadata);
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001928 frame->mPhysicalMetadatas = std::move(result.mPhysicalMetadatas);
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001929 mResultQueue.erase(mResultQueue.begin());
1930
1931 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001932}
1933
1934status_t Camera3Device::triggerAutofocus(uint32_t id) {
1935 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001936 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001937
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001938 ALOGV("%s: Triggering autofocus, id %d", __FUNCTION__, id);
1939 // Mix-in this trigger into the next request and only the next request.
1940 RequestTrigger trigger[] = {
1941 {
1942 ANDROID_CONTROL_AF_TRIGGER,
1943 ANDROID_CONTROL_AF_TRIGGER_START
1944 },
1945 {
1946 ANDROID_CONTROL_AF_TRIGGER_ID,
1947 static_cast<int32_t>(id)
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07001948 }
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001949 };
1950
1951 return mRequestThread->queueTrigger(trigger,
1952 sizeof(trigger)/sizeof(trigger[0]));
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001953}
1954
1955status_t Camera3Device::triggerCancelAutofocus(uint32_t id) {
1956 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001957 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001958
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001959 ALOGV("%s: Triggering cancel autofocus, id %d", __FUNCTION__, id);
1960 // Mix-in this trigger into the next request and only the next request.
1961 RequestTrigger trigger[] = {
1962 {
1963 ANDROID_CONTROL_AF_TRIGGER,
1964 ANDROID_CONTROL_AF_TRIGGER_CANCEL
1965 },
1966 {
1967 ANDROID_CONTROL_AF_TRIGGER_ID,
1968 static_cast<int32_t>(id)
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07001969 }
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001970 };
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001971
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001972 return mRequestThread->queueTrigger(trigger,
1973 sizeof(trigger)/sizeof(trigger[0]));
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001974}
1975
1976status_t Camera3Device::triggerPrecaptureMetering(uint32_t id) {
1977 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001978 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001979
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001980 ALOGV("%s: Triggering precapture metering, id %d", __FUNCTION__, id);
1981 // Mix-in this trigger into the next request and only the next request.
1982 RequestTrigger trigger[] = {
1983 {
1984 ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
1985 ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_START
1986 },
1987 {
1988 ANDROID_CONTROL_AE_PRECAPTURE_ID,
1989 static_cast<int32_t>(id)
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07001990 }
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001991 };
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001992
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001993 return mRequestThread->queueTrigger(trigger,
1994 sizeof(trigger)/sizeof(trigger[0]));
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001995}
1996
Jianing Weicb0652e2014-03-12 18:29:36 -07001997status_t Camera3Device::flush(int64_t *frameNumber) {
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07001998 ATRACE_CALL();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001999 ALOGV("%s: Camera %s: Flushing all requests", __FUNCTION__, mId.string());
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002000 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07002001
Zhijun He7ef20392014-04-21 16:04:17 -07002002 {
2003 Mutex::Autolock l(mLock);
Emilian Peeved2ebe42018-09-25 16:59:09 +01002004
2005 // b/116514106 "disconnect()" can get called twice for the same device. The
2006 // camera device will not be initialized during the second run.
2007 if (mStatus == STATUS_UNINITIALIZED) {
2008 return OK;
2009 }
2010
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07002011 mRequestThread->clear(/*out*/frameNumber);
Zhijun He7ef20392014-04-21 16:04:17 -07002012 }
2013
Emilian Peev08dd2452017-04-06 16:55:14 +01002014 return mRequestThread->flush();
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07002015}
2016
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002017status_t Camera3Device::prepare(int streamId) {
Ruben Brunkc78ac262015-08-13 17:58:46 -07002018 return prepare(camera3::Camera3StreamInterface::ALLOCATE_PIPELINE_MAX, streamId);
2019}
2020
2021status_t Camera3Device::prepare(int maxCount, int streamId) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002022 ATRACE_CALL();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002023 ALOGV("%s: Camera %s: Preparing stream %d", __FUNCTION__, mId.string(), streamId);
Eino-Ville Talvala261394e2015-05-13 14:28:38 -07002024 Mutex::Autolock il(mInterfaceLock);
2025 Mutex::Autolock l(mLock);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002026
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002027 sp<Camera3StreamInterface> stream = mOutputStreams.get(streamId);
2028 if (stream == nullptr) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002029 CLOGE("Stream %d does not exist", streamId);
2030 return BAD_VALUE;
2031 }
2032
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002033 if (stream->isUnpreparable() || stream->hasOutstandingBuffers() ) {
Eino-Ville Talvala261394e2015-05-13 14:28:38 -07002034 CLOGE("Stream %d has already been a request target", streamId);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002035 return BAD_VALUE;
2036 }
2037
2038 if (mRequestThread->isStreamPending(stream)) {
Eino-Ville Talvala261394e2015-05-13 14:28:38 -07002039 CLOGE("Stream %d is already a target in a pending request", streamId);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002040 return BAD_VALUE;
2041 }
2042
Ruben Brunkc78ac262015-08-13 17:58:46 -07002043 return mPreparerThread->prepare(maxCount, stream);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002044}
2045
Eino-Ville Talvalab25e3c82015-07-15 16:04:27 -07002046status_t Camera3Device::tearDown(int streamId) {
2047 ATRACE_CALL();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002048 ALOGV("%s: Camera %s: Tearing down stream %d", __FUNCTION__, mId.string(), streamId);
Eino-Ville Talvalab25e3c82015-07-15 16:04:27 -07002049 Mutex::Autolock il(mInterfaceLock);
2050 Mutex::Autolock l(mLock);
2051
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002052 sp<Camera3StreamInterface> stream = mOutputStreams.get(streamId);
2053 if (stream == nullptr) {
Eino-Ville Talvalab25e3c82015-07-15 16:04:27 -07002054 CLOGE("Stream %d does not exist", streamId);
2055 return BAD_VALUE;
2056 }
2057
Eino-Ville Talvalab25e3c82015-07-15 16:04:27 -07002058 if (stream->hasOutstandingBuffers() || mRequestThread->isStreamPending(stream)) {
2059 CLOGE("Stream %d is a target of a in-progress request", streamId);
2060 return BAD_VALUE;
2061 }
2062
2063 return stream->tearDown();
2064}
2065
Shuzhen Wangb0fdc1e2016-03-20 23:21:39 -07002066status_t Camera3Device::addBufferListenerForStream(int streamId,
2067 wp<Camera3StreamBufferListener> listener) {
2068 ATRACE_CALL();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002069 ALOGV("%s: Camera %s: Adding buffer listener for stream %d", __FUNCTION__, mId.string(), streamId);
Shuzhen Wangb0fdc1e2016-03-20 23:21:39 -07002070 Mutex::Autolock il(mInterfaceLock);
2071 Mutex::Autolock l(mLock);
2072
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002073 sp<Camera3StreamInterface> stream = mOutputStreams.get(streamId);
2074 if (stream == nullptr) {
Shuzhen Wangb0fdc1e2016-03-20 23:21:39 -07002075 CLOGE("Stream %d does not exist", streamId);
2076 return BAD_VALUE;
2077 }
Shuzhen Wangb0fdc1e2016-03-20 23:21:39 -07002078 stream->addBufferListener(listener);
2079
2080 return OK;
2081}
2082
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002083/**
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002084 * Methods called by subclasses
2085 */
2086
2087void Camera3Device::notifyStatus(bool idle) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07002088 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002089 {
2090 // Need mLock to safely update state and synchronize to current
2091 // state of methods in flight.
2092 Mutex::Autolock l(mLock);
2093 // We can get various system-idle notices from the status tracker
2094 // while starting up. Only care about them if we've actually sent
2095 // in some requests recently.
2096 if (mStatus != STATUS_ACTIVE && mStatus != STATUS_CONFIGURED) {
2097 return;
2098 }
Eino-Ville Talvala002001b2018-01-23 16:53:50 -08002099 ALOGV("%s: Camera %s: Now %s, pauseState: %s", __FUNCTION__, mId.string(),
2100 idle ? "idle" : "active", mPauseStateNotify ? "true" : "false");
Ruben Brunk183f0562015-08-12 12:55:02 -07002101 internalUpdateStatusLocked(idle ? STATUS_CONFIGURED : STATUS_ACTIVE);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002102
2103 // Skip notifying listener if we're doing some user-transparent
2104 // state changes
2105 if (mPauseStateNotify) return;
2106 }
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07002107
2108 sp<NotificationListener> listener;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002109 {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002110 std::lock_guard<std::mutex> l(mOutputLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07002111 listener = mListener.promote();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002112 }
2113 if (idle && listener != NULL) {
2114 listener->notifyIdle();
2115 }
2116}
2117
Shuzhen Wang758c2152017-01-10 18:26:18 -08002118status_t Camera3Device::setConsumerSurfaces(int streamId,
Emilian Peev40ead602017-09-26 15:46:36 +01002119 const std::vector<sp<Surface>>& consumers, std::vector<int> *surfaceIds) {
Zhijun He5d677d12016-05-29 16:52:39 -07002120 ATRACE_CALL();
Shuzhen Wang758c2152017-01-10 18:26:18 -08002121 ALOGV("%s: Camera %s: set consumer surface for stream %d",
2122 __FUNCTION__, mId.string(), streamId);
Emilian Peev40ead602017-09-26 15:46:36 +01002123
2124 if (surfaceIds == nullptr) {
2125 return BAD_VALUE;
2126 }
2127
Zhijun He5d677d12016-05-29 16:52:39 -07002128 Mutex::Autolock il(mInterfaceLock);
2129 Mutex::Autolock l(mLock);
2130
Shuzhen Wang758c2152017-01-10 18:26:18 -08002131 if (consumers.size() == 0) {
2132 CLOGE("No consumer is passed!");
Zhijun He5d677d12016-05-29 16:52:39 -07002133 return BAD_VALUE;
2134 }
2135
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002136 sp<Camera3OutputStreamInterface> stream = mOutputStreams.get(streamId);
2137 if (stream == nullptr) {
Zhijun He5d677d12016-05-29 16:52:39 -07002138 CLOGE("Stream %d is unknown", streamId);
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002139 return BAD_VALUE;
Zhijun He5d677d12016-05-29 16:52:39 -07002140 }
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002141
2142 // isConsumerConfigurationDeferred will be off after setConsumers
2143 bool isDeferred = stream->isConsumerConfigurationDeferred();
Shuzhen Wang758c2152017-01-10 18:26:18 -08002144 status_t res = stream->setConsumers(consumers);
Zhijun He5d677d12016-05-29 16:52:39 -07002145 if (res != OK) {
2146 CLOGE("Stream %d set consumer failed (error %d %s) ", streamId, res, strerror(-res));
2147 return res;
2148 }
2149
Emilian Peev40ead602017-09-26 15:46:36 +01002150 for (auto &consumer : consumers) {
2151 int id = stream->getSurfaceId(consumer);
2152 if (id < 0) {
2153 CLOGE("Invalid surface id!");
2154 return BAD_VALUE;
2155 }
2156 surfaceIds->push_back(id);
2157 }
2158
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002159 if (isDeferred) {
Shuzhen Wang0129d522016-10-30 22:43:41 -07002160 if (!stream->isConfiguring()) {
2161 CLOGE("Stream %d was already fully configured.", streamId);
2162 return INVALID_OPERATION;
2163 }
Zhijun He5d677d12016-05-29 16:52:39 -07002164
Shuzhen Wang0129d522016-10-30 22:43:41 -07002165 res = stream->finishConfiguration();
2166 if (res != OK) {
Shuzhen Wang210ba5c2018-07-25 16:47:40 -07002167 // If finishConfiguration fails due to abandoned surface, do not set
2168 // device to error state.
2169 bool isSurfaceAbandoned =
2170 (res == NO_INIT || res == DEAD_OBJECT) && stream->isAbandoned();
2171 if (!isSurfaceAbandoned) {
2172 SET_ERR_L("Can't finish configuring output stream %d: %s (%d)",
2173 stream->getId(), strerror(-res), res);
2174 }
Shuzhen Wang0129d522016-10-30 22:43:41 -07002175 return res;
2176 }
Zhijun He5d677d12016-05-29 16:52:39 -07002177 }
2178
2179 return OK;
2180}
2181
Emilian Peev40ead602017-09-26 15:46:36 +01002182status_t Camera3Device::updateStream(int streamId, const std::vector<sp<Surface>> &newSurfaces,
2183 const std::vector<OutputStreamInfo> &outputInfo,
2184 const std::vector<size_t> &removedSurfaceIds, KeyedVector<sp<Surface>, size_t> *outputMap) {
2185 Mutex::Autolock il(mInterfaceLock);
2186 Mutex::Autolock l(mLock);
2187
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002188 sp<Camera3OutputStreamInterface> stream = mOutputStreams.get(streamId);
2189 if (stream == nullptr) {
Emilian Peev40ead602017-09-26 15:46:36 +01002190 CLOGE("Stream %d is unknown", streamId);
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002191 return BAD_VALUE;
Emilian Peev40ead602017-09-26 15:46:36 +01002192 }
2193
2194 for (const auto &it : removedSurfaceIds) {
2195 if (mRequestThread->isOutputSurfacePending(streamId, it)) {
2196 CLOGE("Shared surface still part of a pending request!");
2197 return -EBUSY;
2198 }
2199 }
2200
Emilian Peev40ead602017-09-26 15:46:36 +01002201 status_t res = stream->updateStream(newSurfaces, outputInfo, removedSurfaceIds, outputMap);
2202 if (res != OK) {
2203 CLOGE("Stream %d failed to update stream (error %d %s) ",
2204 streamId, res, strerror(-res));
2205 if (res == UNKNOWN_ERROR) {
2206 SET_ERR_L("%s: Stream update failed to revert to previous output configuration!",
2207 __FUNCTION__);
2208 }
2209 return res;
2210 }
2211
2212 return res;
2213}
2214
Chien-Yu Chena936ac22017-10-23 15:59:49 -07002215status_t Camera3Device::dropStreamBuffers(bool dropping, int streamId) {
2216 Mutex::Autolock il(mInterfaceLock);
2217 Mutex::Autolock l(mLock);
2218
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002219 sp<Camera3OutputStreamInterface> stream = mOutputStreams.get(streamId);
2220 if (stream == nullptr) {
Chien-Yu Chena936ac22017-10-23 15:59:49 -07002221 ALOGE("%s: Stream %d is not found.", __FUNCTION__, streamId);
2222 return BAD_VALUE;
2223 }
Chien-Yu Chena936ac22017-10-23 15:59:49 -07002224 return stream->dropBuffers(dropping);
2225}
2226
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002227/**
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002228 * Camera3Device private methods
2229 */
2230
2231sp<Camera3Device::CaptureRequest> Camera3Device::createCaptureRequest(
Emilian Peevaebbe412018-01-15 13:53:24 +00002232 const PhysicalCameraSettingsList &request, const SurfaceMap &surfaceMap) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002233 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002234
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08002235 sp<CaptureRequest> newRequest = new CaptureRequest();
Emilian Peevaebbe412018-01-15 13:53:24 +00002236 newRequest->mSettingsList = request;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002237
2238 camera_metadata_entry_t inputStreams =
Emilian Peevaebbe412018-01-15 13:53:24 +00002239 newRequest->mSettingsList.begin()->metadata.find(ANDROID_REQUEST_INPUT_STREAMS);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002240 if (inputStreams.count > 0) {
2241 if (mInputStream == NULL ||
Zhijun Hed1d64672013-09-06 15:00:01 -07002242 mInputStream->getId() != inputStreams.data.i32[0]) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002243 CLOGE("Request references unknown input stream %d",
2244 inputStreams.data.u8[0]);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002245 return NULL;
2246 }
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002247
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002248 if (mInputStream->isConfiguring()) {
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002249 SET_ERR_L("%s: input stream %d is not configured!",
2250 __FUNCTION__, mInputStream->getId());
2251 return NULL;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002252 }
Shuzhen Wangb3a0fb52018-09-13 17:24:08 -07002253 // Check if stream prepare is blocking requests.
2254 if (mInputStream->isBlockedByPrepare()) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002255 CLOGE("Request references an input stream that's being prepared!");
2256 return NULL;
2257 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002258
2259 newRequest->mInputStream = mInputStream;
Emilian Peevaebbe412018-01-15 13:53:24 +00002260 newRequest->mSettingsList.begin()->metadata.erase(ANDROID_REQUEST_INPUT_STREAMS);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002261 }
2262
2263 camera_metadata_entry_t streams =
Emilian Peevaebbe412018-01-15 13:53:24 +00002264 newRequest->mSettingsList.begin()->metadata.find(ANDROID_REQUEST_OUTPUT_STREAMS);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002265 if (streams.count == 0) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002266 CLOGE("Zero output streams specified!");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002267 return NULL;
2268 }
2269
2270 for (size_t i = 0; i < streams.count; i++) {
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002271 sp<Camera3OutputStreamInterface> stream = mOutputStreams.get(streams.data.i32[i]);
2272 if (stream == nullptr) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002273 CLOGE("Request references unknown stream %d",
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002274 streams.data.i32[i]);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002275 return NULL;
2276 }
Zhijun He5d677d12016-05-29 16:52:39 -07002277 // It is illegal to include a deferred consumer output stream into a request
Shuzhen Wang0129d522016-10-30 22:43:41 -07002278 auto iter = surfaceMap.find(streams.data.i32[i]);
2279 if (iter != surfaceMap.end()) {
2280 const std::vector<size_t>& surfaces = iter->second;
2281 for (const auto& surface : surfaces) {
2282 if (stream->isConsumerConfigurationDeferred(surface)) {
2283 CLOGE("Stream %d surface %zu hasn't finished configuration yet "
2284 "due to deferred consumer", stream->getId(), surface);
2285 return NULL;
2286 }
2287 }
Yin-Chia Yeh0b287572018-10-15 12:38:13 -07002288 newRequest->mOutputSurfaces[streams.data.i32[i]] = surfaces;
Zhijun He5d677d12016-05-29 16:52:39 -07002289 }
2290
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002291 if (stream->isConfiguring()) {
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002292 SET_ERR_L("%s: stream %d is not configured!", __FUNCTION__, stream->getId());
2293 return NULL;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002294 }
Shuzhen Wangb3a0fb52018-09-13 17:24:08 -07002295 // Check if stream prepare is blocking requests.
2296 if (stream->isBlockedByPrepare()) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002297 CLOGE("Request references an output stream that's being prepared!");
2298 return NULL;
2299 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002300
2301 newRequest->mOutputStreams.push(stream);
2302 }
Emilian Peevaebbe412018-01-15 13:53:24 +00002303 newRequest->mSettingsList.begin()->metadata.erase(ANDROID_REQUEST_OUTPUT_STREAMS);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07002304 newRequest->mBatchSize = 1;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002305
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08002306 auto rotateAndCropEntry =
2307 newRequest->mSettingsList.begin()->metadata.find(ANDROID_SCALER_ROTATE_AND_CROP);
2308 if (rotateAndCropEntry.count > 0 &&
2309 rotateAndCropEntry.data.u8[0] == ANDROID_SCALER_ROTATE_AND_CROP_AUTO) {
2310 newRequest->mRotateAndCropAuto = true;
2311 } else {
2312 newRequest->mRotateAndCropAuto = false;
2313 }
2314
Shuzhen Wangd1d051a2020-08-20 15:42:23 -07002315 auto zoomRatioEntry =
2316 newRequest->mSettingsList.begin()->metadata.find(ANDROID_CONTROL_ZOOM_RATIO);
2317 if (zoomRatioEntry.count > 0 &&
2318 zoomRatioEntry.data.f[0] == 1.0f) {
2319 newRequest->mZoomRatioIs1x = true;
2320 } else {
2321 newRequest->mZoomRatioIs1x = false;
2322 }
2323
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002324 return newRequest;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002325}
2326
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002327void Camera3Device::cancelStreamsConfigurationLocked() {
2328 int res = OK;
2329 if (mInputStream != NULL && mInputStream->isConfiguring()) {
2330 res = mInputStream->cancelConfiguration();
2331 if (res != OK) {
2332 CLOGE("Can't cancel configuring input stream %d: %s (%d)",
2333 mInputStream->getId(), strerror(-res), res);
2334 }
2335 }
2336
2337 for (size_t i = 0; i < mOutputStreams.size(); i++) {
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002338 sp<Camera3OutputStreamInterface> outputStream = mOutputStreams[i];
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002339 if (outputStream->isConfiguring()) {
2340 res = outputStream->cancelConfiguration();
2341 if (res != OK) {
2342 CLOGE("Can't cancel configuring output stream %d: %s (%d)",
2343 outputStream->getId(), strerror(-res), res);
2344 }
2345 }
2346 }
2347
2348 // Return state to that at start of call, so that future configures
2349 // properly clean things up
2350 internalUpdateStatusLocked(STATUS_UNCONFIGURED);
2351 mNeedConfig = true;
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002352
2353 res = mPreparerThread->resume();
2354 if (res != OK) {
2355 ALOGE("%s: Camera %s: Preparer thread failed to resume!", __FUNCTION__, mId.string());
2356 }
2357}
2358
Emilian Peev0d0191e2020-04-21 17:01:18 -07002359bool Camera3Device::checkAbandonedStreamsLocked() {
2360 if ((mInputStream.get() != nullptr) && (mInputStream->isAbandoned())) {
2361 return true;
2362 }
2363
2364 for (size_t i = 0; i < mOutputStreams.size(); i++) {
2365 auto stream = mOutputStreams[i];
2366 if ((stream.get() != nullptr) && (stream->isAbandoned())) {
2367 return true;
2368 }
2369 }
2370
2371 return false;
2372}
2373
Emilian Peev3bead5f2020-05-28 17:29:08 -07002374bool Camera3Device::reconfigureCamera(const CameraMetadata& sessionParams, int clientStatusId) {
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002375 ATRACE_CALL();
2376 bool ret = false;
2377
Jayant Chowdhary646c31b2020-01-30 13:09:59 -08002378 Mutex::Autolock il(mInterfaceLock);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002379 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
2380
2381 Mutex::Autolock l(mLock);
Emilian Peev0d0191e2020-04-21 17:01:18 -07002382 if (checkAbandonedStreamsLocked()) {
2383 ALOGW("%s: Abandoned stream detected, session parameters can't be applied correctly!",
2384 __FUNCTION__);
2385 return true;
2386 }
2387
Emilian Peev3bead5f2020-05-28 17:29:08 -07002388 status_t rc = NO_ERROR;
2389 bool markClientActive = false;
2390 if (mStatus == STATUS_ACTIVE) {
2391 markClientActive = true;
2392 mPauseStateNotify = true;
2393 mStatusTracker->markComponentIdle(clientStatusId, Fence::NO_FENCE);
2394
2395 rc = internalPauseAndWaitLocked(maxExpectedDuration);
2396 }
2397
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002398 if (rc == NO_ERROR) {
2399 mNeedConfig = true;
2400 rc = configureStreamsLocked(mOperatingMode, sessionParams, /*notifyRequestThread*/ false);
2401 if (rc == NO_ERROR) {
2402 ret = true;
2403 mPauseStateNotify = false;
2404 //Moving to active state while holding 'mLock' is important.
2405 //There could be pending calls to 'create-/deleteStream' which
2406 //will trigger another stream configuration while the already
2407 //present streams end up with outstanding buffers that will
2408 //not get drained.
2409 internalUpdateStatusLocked(STATUS_ACTIVE);
Shuzhen Wang210ba5c2018-07-25 16:47:40 -07002410 } else if (rc == DEAD_OBJECT) {
2411 // DEAD_OBJECT can be returned if either the consumer surface is
2412 // abandoned, or the HAL has died.
2413 // - If the HAL has died, configureStreamsLocked call will set
2414 // device to error state,
2415 // - If surface is abandoned, we should not set device to error
2416 // state.
2417 ALOGE("Failed to re-configure camera due to abandoned surface");
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002418 } else {
Shuzhen Wang210ba5c2018-07-25 16:47:40 -07002419 SET_ERR_L("Failed to re-configure camera: %d", rc);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002420 }
2421 } else {
2422 ALOGE("%s: Failed to pause streaming: %d", __FUNCTION__, rc);
2423 }
2424
Emilian Peev3bead5f2020-05-28 17:29:08 -07002425 if (markClientActive) {
2426 mStatusTracker->markComponentActive(clientStatusId);
2427 }
2428
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002429 return ret;
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002430}
2431
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01002432status_t Camera3Device::configureStreamsLocked(int operatingMode,
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002433 const CameraMetadata& sessionParams, bool notifyRequestThread) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002434 ATRACE_CALL();
2435 status_t res;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002436
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002437 if (mStatus != STATUS_UNCONFIGURED && mStatus != STATUS_CONFIGURED) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002438 CLOGE("Not idle");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002439 return INVALID_OPERATION;
2440 }
2441
Eino-Ville Talvalae7091aa2017-03-07 15:23:06 -08002442 if (operatingMode < 0) {
2443 CLOGE("Invalid operating mode: %d", operatingMode);
2444 return BAD_VALUE;
2445 }
2446
2447 bool isConstrainedHighSpeed =
2448 static_cast<int>(StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE) ==
2449 operatingMode;
2450
2451 if (mOperatingMode != operatingMode) {
2452 mNeedConfig = true;
2453 mIsConstrainedHighSpeedConfiguration = isConstrainedHighSpeed;
2454 mOperatingMode = operatingMode;
2455 }
2456
Shuzhen Wang0cf01cb2019-09-05 13:33:06 -07002457 // In case called from configureStreams, abort queued input buffers not belonging to
2458 // any pending requests.
2459 if (mInputStream != NULL && notifyRequestThread) {
2460 while (true) {
2461 camera3_stream_buffer_t inputBuffer;
2462 status_t res = mInputStream->getInputBuffer(&inputBuffer,
2463 /*respectHalLimit*/ false);
2464 if (res != OK) {
2465 // Exhausted acquiring all input buffers.
2466 break;
2467 }
2468
2469 inputBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
2470 res = mInputStream->returnInputBuffer(inputBuffer);
2471 if (res != OK) {
2472 ALOGE("%s: %d: couldn't return input buffer while clearing input queue: "
2473 "%s (%d)", __FUNCTION__, __LINE__, strerror(-res), res);
2474 }
2475 }
2476 }
2477
Eino-Ville Talvalaea26c772013-06-11 16:04:06 -07002478 if (!mNeedConfig) {
2479 ALOGV("%s: Skipping config, no stream changes", __FUNCTION__);
2480 return OK;
2481 }
2482
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002483 // Workaround for device HALv3.2 or older spec bug - zero streams requires
2484 // adding a dummy stream instead.
2485 // TODO: Bug: 17321404 for fixing the HAL spec and removing this workaround.
2486 if (mOutputStreams.size() == 0) {
2487 addDummyStreamLocked();
2488 } else {
2489 tryRemoveDummyStreamLocked();
2490 }
2491
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002492 // Start configuring the streams
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002493 ALOGV("%s: Camera %s: Starting stream configuration", __FUNCTION__, mId.string());
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002494
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002495 mPreparerThread->pause();
2496
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002497 camera3_stream_configuration config;
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -08002498 config.operation_mode = mOperatingMode;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002499 config.num_streams = (mInputStream != NULL) + mOutputStreams.size();
2500
2501 Vector<camera3_stream_t*> streams;
2502 streams.setCapacity(config.num_streams);
Emilian Peev192ee832018-01-31 14:46:47 +00002503 std::vector<uint32_t> bufferSizes(config.num_streams, 0);
Yin-Chia Yehfb6e55b2018-01-25 10:50:26 -08002504
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002505
2506 if (mInputStream != NULL) {
2507 camera3_stream_t *inputStream;
2508 inputStream = mInputStream->startConfiguration();
2509 if (inputStream == NULL) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002510 CLOGE("Can't start input stream configuration");
2511 cancelStreamsConfigurationLocked();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002512 return INVALID_OPERATION;
2513 }
2514 streams.add(inputStream);
2515 }
2516
2517 for (size_t i = 0; i < mOutputStreams.size(); i++) {
Igor Murashkin2fba5842013-04-22 14:03:54 -07002518
2519 // Don't configure bidi streams twice, nor add them twice to the list
2520 if (mOutputStreams[i].get() ==
2521 static_cast<Camera3StreamInterface*>(mInputStream.get())) {
2522
2523 config.num_streams--;
2524 continue;
2525 }
2526
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002527 camera3_stream_t *outputStream;
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002528 outputStream = mOutputStreams[i]->startConfiguration();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002529 if (outputStream == NULL) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002530 CLOGE("Can't start output stream configuration");
2531 cancelStreamsConfigurationLocked();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002532 return INVALID_OPERATION;
2533 }
2534 streams.add(outputStream);
Yin-Chia Yehfb6e55b2018-01-25 10:50:26 -08002535
Shuzhen Wangb7ab1e42019-02-20 15:42:23 -08002536 if (outputStream->format == HAL_PIXEL_FORMAT_BLOB) {
Emilian Peev192ee832018-01-31 14:46:47 +00002537 size_t k = i + ((mInputStream != nullptr) ? 1 : 0); // Input stream if present should
2538 // always occupy the initial entry.
Shuzhen Wangb7ab1e42019-02-20 15:42:23 -08002539 if (outputStream->data_space == HAL_DATASPACE_V0_JFIF) {
2540 bufferSizes[k] = static_cast<uint32_t>(
2541 getJpegBufferSize(outputStream->width, outputStream->height));
2542 } else if (outputStream->data_space ==
2543 static_cast<android_dataspace>(HAL_DATASPACE_JPEG_APP_SEGMENTS)) {
2544 bufferSizes[k] = outputStream->width * outputStream->height;
2545 } else {
2546 ALOGW("%s: Blob dataSpace %d not supported",
2547 __FUNCTION__, outputStream->data_space);
2548 }
Yin-Chia Yehfb6e55b2018-01-25 10:50:26 -08002549 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002550 }
2551
2552 config.streams = streams.editArray();
2553
2554 // Do the HAL configuration; will potentially touch stream
Shuzhen Wang92653952019-05-07 15:11:43 -07002555 // max_buffers, usage, and priv fields, as well as data_space and format
2556 // fields for IMPLEMENTATION_DEFINED formats.
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002557
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01002558 const camera_metadata_t *sessionBuffer = sessionParams.getAndLock();
Emilian Peev192ee832018-01-31 14:46:47 +00002559 res = mInterface->configureStreams(sessionBuffer, &config, bufferSizes);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01002560 sessionParams.unlock(sessionBuffer);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002561
Eino-Ville Talvala17543512014-08-06 14:32:02 -07002562 if (res == BAD_VALUE) {
2563 // HAL rejected this set of streams as unsupported, clean up config
2564 // attempt and return to unconfigured state
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002565 CLOGE("Set of requested inputs/outputs not supported by HAL");
2566 cancelStreamsConfigurationLocked();
Eino-Ville Talvala17543512014-08-06 14:32:02 -07002567 return BAD_VALUE;
2568 } else if (res != OK) {
2569 // Some other kind of error from configure_streams - this is not
2570 // expected
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002571 SET_ERR_L("Unable to configure streams with HAL: %s (%d)",
2572 strerror(-res), res);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002573 return res;
2574 }
2575
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002576 // Finish all stream configuration immediately.
2577 // TODO: Try to relax this later back to lazy completion, which should be
2578 // faster
2579
Igor Murashkin073f8572013-05-02 14:59:28 -07002580 if (mInputStream != NULL && mInputStream->isConfiguring()) {
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002581 bool streamReConfigured = false;
2582 res = mInputStream->finishConfiguration(&streamReConfigured);
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002583 if (res != OK) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002584 CLOGE("Can't finish configuring input stream %d: %s (%d)",
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002585 mInputStream->getId(), strerror(-res), res);
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002586 cancelStreamsConfigurationLocked();
Shuzhen Wang210ba5c2018-07-25 16:47:40 -07002587 if ((res == NO_INIT || res == DEAD_OBJECT) && mInputStream->isAbandoned()) {
2588 return DEAD_OBJECT;
2589 }
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002590 return BAD_VALUE;
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002591 }
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002592 if (streamReConfigured) {
2593 mInterface->onStreamReConfigured(mInputStream->getId());
2594 }
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002595 }
2596
2597 for (size_t i = 0; i < mOutputStreams.size(); i++) {
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002598 sp<Camera3OutputStreamInterface> outputStream = mOutputStreams[i];
Zhijun He5d677d12016-05-29 16:52:39 -07002599 if (outputStream->isConfiguring() && !outputStream->isConsumerConfigurationDeferred()) {
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002600 bool streamReConfigured = false;
2601 res = outputStream->finishConfiguration(&streamReConfigured);
Igor Murashkin073f8572013-05-02 14:59:28 -07002602 if (res != OK) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002603 CLOGE("Can't finish configuring output stream %d: %s (%d)",
Igor Murashkin073f8572013-05-02 14:59:28 -07002604 outputStream->getId(), strerror(-res), res);
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002605 cancelStreamsConfigurationLocked();
Shuzhen Wang210ba5c2018-07-25 16:47:40 -07002606 if ((res == NO_INIT || res == DEAD_OBJECT) && outputStream->isAbandoned()) {
2607 return DEAD_OBJECT;
2608 }
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002609 return BAD_VALUE;
Igor Murashkin073f8572013-05-02 14:59:28 -07002610 }
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002611 if (streamReConfigured) {
2612 mInterface->onStreamReConfigured(outputStream->getId());
2613 }
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002614 }
2615 }
2616
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002617 // Request thread needs to know to avoid using repeat-last-settings protocol
2618 // across configure_streams() calls
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002619 if (notifyRequestThread) {
2620 mRequestThread->configurationComplete(mIsConstrainedHighSpeedConfiguration, sessionParams);
2621 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002622
Zhijun He90f7c372016-08-16 16:19:43 -07002623 char value[PROPERTY_VALUE_MAX];
2624 property_get("camera.fifo.disable", value, "0");
2625 int32_t disableFifo = atoi(value);
2626 if (disableFifo != 1) {
2627 // Boost priority of request thread to SCHED_FIFO.
2628 pid_t requestThreadTid = mRequestThread->getTid();
2629 res = requestPriority(getpid(), requestThreadTid,
Mikhail Naganov83f04272017-02-07 10:45:09 -08002630 kRequestThreadPriority, /*isForApp*/ false, /*asynchronous*/ false);
Zhijun He90f7c372016-08-16 16:19:43 -07002631 if (res != OK) {
2632 ALOGW("Can't set realtime priority for request processing thread: %s (%d)",
2633 strerror(-res), res);
2634 } else {
2635 ALOGD("Set real time priority for request queue thread (tid %d)", requestThreadTid);
2636 }
Eino-Ville Talvalaf99498e2015-09-25 16:52:55 -07002637 }
2638
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002639 // Update device state
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01002640 const camera_metadata_t *newSessionParams = sessionParams.getAndLock();
2641 const camera_metadata_t *currentSessionParams = mSessionParams.getAndLock();
2642 bool updateSessionParams = (newSessionParams != currentSessionParams) ? true : false;
2643 sessionParams.unlock(newSessionParams);
2644 mSessionParams.unlock(currentSessionParams);
2645 if (updateSessionParams) {
2646 mSessionParams = sessionParams;
2647 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002648
Eino-Ville Talvalaea26c772013-06-11 16:04:06 -07002649 mNeedConfig = false;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002650
Ruben Brunk183f0562015-08-12 12:55:02 -07002651 internalUpdateStatusLocked((mDummyStreamId == NO_STREAM) ?
2652 STATUS_CONFIGURED : STATUS_UNCONFIGURED);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002653
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002654 ALOGV("%s: Camera %s: Stream configuration complete", __FUNCTION__, mId.string());
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002655
Zhijun He0a210512014-07-24 13:45:15 -07002656 // tear down the deleted streams after configure streams.
2657 mDeletedStreams.clear();
2658
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002659 auto rc = mPreparerThread->resume();
2660 if (rc != OK) {
2661 SET_ERR_L("%s: Camera %s: Preparer thread failed to resume!", __FUNCTION__, mId.string());
2662 return rc;
2663 }
2664
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07002665 if (mDummyStreamId == NO_STREAM) {
2666 mRequestBufferSM.onStreamsConfigured();
2667 }
2668
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002669 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002670}
2671
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002672status_t Camera3Device::addDummyStreamLocked() {
2673 ATRACE_CALL();
2674 status_t res;
2675
2676 if (mDummyStreamId != NO_STREAM) {
2677 // Should never be adding a second dummy stream when one is already
2678 // active
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002679 SET_ERR_L("%s: Camera %s: A dummy stream already exists!",
2680 __FUNCTION__, mId.string());
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002681 return INVALID_OPERATION;
2682 }
2683
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002684 ALOGV("%s: Camera %s: Adding a dummy stream", __FUNCTION__, mId.string());
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002685
2686 sp<Camera3OutputStreamInterface> dummyStream =
2687 new Camera3DummyStream(mNextStreamId);
2688
2689 res = mOutputStreams.add(mNextStreamId, dummyStream);
2690 if (res < 0) {
2691 SET_ERR_L("Can't add dummy stream to set: %s (%d)", strerror(-res), res);
2692 return res;
2693 }
2694
2695 mDummyStreamId = mNextStreamId;
2696 mNextStreamId++;
2697
2698 return OK;
2699}
2700
2701status_t Camera3Device::tryRemoveDummyStreamLocked() {
2702 ATRACE_CALL();
2703 status_t res;
2704
2705 if (mDummyStreamId == NO_STREAM) return OK;
2706 if (mOutputStreams.size() == 1) return OK;
2707
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002708 ALOGV("%s: Camera %s: Removing the dummy stream", __FUNCTION__, mId.string());
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002709
2710 // Ok, have a dummy stream and there's at least one other output stream,
2711 // so remove the dummy
2712
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002713 sp<Camera3StreamInterface> deletedStream = mOutputStreams.get(mDummyStreamId);
2714 if (deletedStream == nullptr) {
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002715 SET_ERR_L("Dummy stream %d does not appear to exist", mDummyStreamId);
2716 return INVALID_OPERATION;
2717 }
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002718 mOutputStreams.remove(mDummyStreamId);
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002719
2720 // Free up the stream endpoint so that it can be used by some other stream
2721 res = deletedStream->disconnect();
2722 if (res != OK) {
2723 SET_ERR_L("Can't disconnect deleted dummy stream %d", mDummyStreamId);
2724 // fall through since we want to still list the stream as deleted.
2725 }
2726 mDeletedStreams.add(deletedStream);
2727 mDummyStreamId = NO_STREAM;
2728
2729 return res;
2730}
2731
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002732void Camera3Device::setErrorState(const char *fmt, ...) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07002733 ATRACE_CALL();
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002734 Mutex::Autolock l(mLock);
2735 va_list args;
2736 va_start(args, fmt);
2737
2738 setErrorStateLockedV(fmt, args);
2739
2740 va_end(args);
2741}
2742
2743void Camera3Device::setErrorStateV(const char *fmt, va_list args) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07002744 ATRACE_CALL();
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002745 Mutex::Autolock l(mLock);
2746 setErrorStateLockedV(fmt, args);
2747}
2748
2749void Camera3Device::setErrorStateLocked(const char *fmt, ...) {
2750 va_list args;
2751 va_start(args, fmt);
2752
2753 setErrorStateLockedV(fmt, args);
2754
2755 va_end(args);
2756}
2757
2758void Camera3Device::setErrorStateLockedV(const char *fmt, va_list args) {
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002759 // Print out all error messages to log
2760 String8 errorCause = String8::formatV(fmt, args);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002761 ALOGE("Camera %s: %s", mId.string(), errorCause.string());
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002762
2763 // But only do error state transition steps for the first error
Zhijun Heb05eeae2013-06-06 13:51:22 -07002764 if (mStatus == STATUS_ERROR || mStatus == STATUS_UNINITIALIZED) return;
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002765
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002766 mErrorCause = errorCause;
2767
Yin-Chia Yeh3d145ae2017-07-27 12:47:03 -07002768 if (mRequestThread != nullptr) {
2769 mRequestThread->setPaused(true);
2770 }
Ruben Brunk183f0562015-08-12 12:55:02 -07002771 internalUpdateStatusLocked(STATUS_ERROR);
Eino-Ville Talvala17543512014-08-06 14:32:02 -07002772
2773 // Notify upstream about a device error
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07002774 sp<NotificationListener> listener = mListener.promote();
2775 if (listener != NULL) {
2776 listener->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
Eino-Ville Talvala17543512014-08-06 14:32:02 -07002777 CaptureResultExtras());
2778 }
2779
2780 // Save stack trace. View by dumping it later.
2781 CameraTraces::saveTrace();
2782 // TODO: consider adding errorCause and client pid/procname
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002783}
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002784
2785/**
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002786 * In-flight request management
2787 */
2788
Jianing Weicb0652e2014-03-12 18:29:36 -07002789status_t Camera3Device::registerInFlight(uint32_t frameNumber,
Chien-Yu Chend196d612015-06-22 19:49:01 -07002790 int32_t numBuffers, CaptureResultExtras resultExtras, bool hasInput,
Shuzhen Wang5c22c152017-12-31 17:12:25 -08002791 bool hasAppCallback, nsecs_t maxExpectedDuration,
Shuzhen Wang26abaf42018-08-28 15:41:20 -07002792 std::set<String8>& physicalCameraIds, bool isStillCapture,
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08002793 bool isZslCapture, bool rotateAndCropAuto, const std::set<std::string>& cameraIdsWithZoom,
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08002794 const SurfaceMap& outputSurfaces) {
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002795 ATRACE_CALL();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002796 std::lock_guard<std::mutex> l(mInFlightLock);
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002797
2798 ssize_t res;
Chien-Yu Chend196d612015-06-22 19:49:01 -07002799 res = mInFlightMap.add(frameNumber, InFlightRequest(numBuffers, resultExtras, hasInput,
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07002800 hasAppCallback, maxExpectedDuration, physicalCameraIds, isStillCapture, isZslCapture,
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08002801 rotateAndCropAuto, cameraIdsWithZoom, outputSurfaces));
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002802 if (res < 0) return res;
2803
Eino-Ville Talvala24b366e2016-07-21 12:53:07 -07002804 if (mInFlightMap.size() == 1) {
Emilian Peev26d975d2018-07-05 14:52:57 +01002805 // Hold a separate dedicated tracker lock to prevent race with disconnect and also
2806 // avoid a deadlock during reprocess requests.
2807 Mutex::Autolock l(mTrackerLock);
Yin-Chia Yeh38dfde52017-06-27 17:13:33 -07002808 if (mStatusTracker != nullptr) {
2809 mStatusTracker->markComponentActive(mInFlightStatusId);
2810 }
Eino-Ville Talvala24b366e2016-07-21 12:53:07 -07002811 }
2812
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07002813 mExpectedInflightDuration += maxExpectedDuration;
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002814 return OK;
2815}
2816
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002817void Camera3Device::onInflightEntryRemovedLocked(nsecs_t duration) {
Shuzhen Wangcadb3302016-11-04 14:17:56 -07002818 // Indicate idle inFlightMap to the status tracker
2819 if (mInFlightMap.size() == 0) {
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07002820 mRequestBufferSM.onInflightMapEmpty();
Emilian Peev26d975d2018-07-05 14:52:57 +01002821 // Hold a separate dedicated tracker lock to prevent race with disconnect and also
2822 // avoid a deadlock during reprocess requests.
2823 Mutex::Autolock l(mTrackerLock);
Yin-Chia Yeh38dfde52017-06-27 17:13:33 -07002824 if (mStatusTracker != nullptr) {
2825 mStatusTracker->markComponentIdle(mInFlightStatusId, Fence::NO_FENCE);
2826 }
Shuzhen Wangcadb3302016-11-04 14:17:56 -07002827 }
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07002828 mExpectedInflightDuration -= duration;
Shuzhen Wangcadb3302016-11-04 14:17:56 -07002829}
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08002830
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002831void Camera3Device::checkInflightMapLengthLocked() {
Yin-Chia Yeh99fd0972019-06-27 14:22:44 -07002832 // Sanity check - if we have too many in-flight frames with long total inflight duration,
2833 // something has likely gone wrong. This might still be legit only if application send in
2834 // a long burst of long exposure requests.
2835 if (mExpectedInflightDuration > kMinWarnInflightDuration) {
2836 if (!mIsConstrainedHighSpeedConfiguration && mInFlightMap.size() > kInFlightWarnLimit) {
2837 CLOGW("In-flight list too large: %zu, total inflight duration %" PRIu64,
2838 mInFlightMap.size(), mExpectedInflightDuration);
2839 } else if (mIsConstrainedHighSpeedConfiguration && mInFlightMap.size() >
2840 kInFlightWarnLimitHighSpeed) {
2841 CLOGW("In-flight list too large for high speed configuration: %zu,"
2842 "total inflight duration %" PRIu64,
2843 mInFlightMap.size(), mExpectedInflightDuration);
2844 }
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08002845 }
2846}
2847
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002848void Camera3Device::onInflightMapFlushedLocked() {
2849 mExpectedInflightDuration = 0;
2850}
2851
2852void Camera3Device::removeInFlightMapEntryLocked(int idx) {
Jayant Chowdharyd4776262020-06-23 23:45:57 -07002853 ATRACE_HFR_CALL();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002854 nsecs_t duration = mInFlightMap.valueAt(idx).maxExpectedDuration;
2855 mInFlightMap.removeItemsAt(idx, 1);
2856
2857 onInflightEntryRemovedLocked(duration);
2858}
2859
2860
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07002861void Camera3Device::flushInflightRequests() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07002862 ATRACE_CALL();
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07002863 sp<NotificationListener> listener;
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07002864 {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002865 std::lock_guard<std::mutex> l(mOutputLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07002866 listener = mListener.promote();
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07002867 }
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002868
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002869 FlushInflightReqStates states {
2870 mId, mInFlightLock, mInFlightMap, mUseHalBufManager,
2871 listener, *this, *mInterface, *this};
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07002872
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002873 camera3::flushInflightRequests(states);
Eino-Ville Talvala17543512014-08-06 14:32:02 -07002874}
2875
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002876CameraMetadata Camera3Device::getLatestRequestLocked() {
Igor Murashkin1e479c02013-09-06 16:55:14 -07002877 ALOGV("%s", __FUNCTION__);
2878
Igor Murashkin1e479c02013-09-06 16:55:14 -07002879 CameraMetadata retVal;
2880
2881 if (mRequestThread != NULL) {
2882 retVal = mRequestThread->getLatestRequest();
2883 }
2884
Igor Murashkin1e479c02013-09-06 16:55:14 -07002885 return retVal;
2886}
2887
Eino-Ville Talvala4d453832016-07-15 11:56:53 -07002888void Camera3Device::monitorMetadata(TagMonitor::eventSource source,
Shuzhen Wangc2cba122018-05-17 18:10:24 -07002889 int64_t frameNumber, nsecs_t timestamp, const CameraMetadata& metadata,
2890 const std::unordered_map<std::string, CameraMetadata>& physicalMetadata) {
2891
2892 mTagMonitor.monitorMetadata(source, frameNumber, timestamp, metadata,
2893 physicalMetadata);
Eino-Ville Talvala4d453832016-07-15 11:56:53 -07002894}
2895
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002896/**
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002897 * HalInterface inner class methods
2898 */
2899
Yifan Hongf79b5542017-04-11 14:44:25 -07002900Camera3Device::HalInterface::HalInterface(
2901 sp<ICameraDeviceSession> &session,
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08002902 std::shared_ptr<RequestMetadataQueue> queue,
Yin-Chia Yehb978c382019-10-30 00:22:37 -07002903 bool useHalBufManager, bool supportOfflineProcessing) :
Yifan Hongf79b5542017-04-11 14:44:25 -07002904 mHidlSession(session),
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08002905 mRequestMetadataQueue(queue),
Emilian Peev4ec17882019-01-24 17:16:58 -08002906 mUseHalBufManager(useHalBufManager),
Yin-Chia Yehb978c382019-10-30 00:22:37 -07002907 mIsReconfigurationQuerySupported(true),
2908 mSupportOfflineProcessing(supportOfflineProcessing) {
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002909 // Check with hardware service manager if we can downcast these interfaces
2910 // Somewhat expensive, so cache the results at startup
Yin-Chia Yehb978c382019-10-30 00:22:37 -07002911 auto castResult_3_6 = device::V3_6::ICameraDeviceSession::castFrom(mHidlSession);
2912 if (castResult_3_6.isOk()) {
2913 mHidlSession_3_6 = castResult_3_6;
2914 }
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07002915 auto castResult_3_5 = device::V3_5::ICameraDeviceSession::castFrom(mHidlSession);
2916 if (castResult_3_5.isOk()) {
2917 mHidlSession_3_5 = castResult_3_5;
2918 }
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002919 auto castResult_3_4 = device::V3_4::ICameraDeviceSession::castFrom(mHidlSession);
2920 if (castResult_3_4.isOk()) {
2921 mHidlSession_3_4 = castResult_3_4;
2922 }
2923 auto castResult_3_3 = device::V3_3::ICameraDeviceSession::castFrom(mHidlSession);
2924 if (castResult_3_3.isOk()) {
2925 mHidlSession_3_3 = castResult_3_3;
2926 }
2927}
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002928
Yin-Chia Yehb978c382019-10-30 00:22:37 -07002929Camera3Device::HalInterface::HalInterface() :
2930 mUseHalBufManager(false),
2931 mSupportOfflineProcessing(false) {}
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002932
2933Camera3Device::HalInterface::HalInterface(const HalInterface& other) :
Yifan Hongf79b5542017-04-11 14:44:25 -07002934 mHidlSession(other.mHidlSession),
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08002935 mRequestMetadataQueue(other.mRequestMetadataQueue),
Yin-Chia Yehb978c382019-10-30 00:22:37 -07002936 mUseHalBufManager(other.mUseHalBufManager),
2937 mSupportOfflineProcessing(other.mSupportOfflineProcessing) {}
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002938
2939bool Camera3Device::HalInterface::valid() {
Emilian Peev31abd0a2017-05-11 18:37:46 +01002940 return (mHidlSession != nullptr);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002941}
2942
2943void Camera3Device::HalInterface::clear() {
Yin-Chia Yehb978c382019-10-30 00:22:37 -07002944 mHidlSession_3_6.clear();
Emilian Peev644a3e12018-11-23 13:52:39 +00002945 mHidlSession_3_5.clear();
Emilian Peev9e740b02018-01-30 18:28:03 +00002946 mHidlSession_3_4.clear();
2947 mHidlSession_3_3.clear();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002948 mHidlSession.clear();
2949}
2950
2951status_t Camera3Device::HalInterface::constructDefaultRequestSettings(
2952 camera3_request_template_t templateId,
2953 /*out*/ camera_metadata_t **requestTemplate) {
2954 ATRACE_NAME("CameraHal::constructDefaultRequestSettings");
2955 if (!valid()) return INVALID_OPERATION;
2956 status_t res = OK;
2957
Emilian Peev31abd0a2017-05-11 18:37:46 +01002958 common::V1_0::Status status;
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002959
2960 auto requestCallback = [&status, &requestTemplate]
Emilian Peev31abd0a2017-05-11 18:37:46 +01002961 (common::V1_0::Status s, const device::V3_2::CameraMetadata& request) {
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002962 status = s;
2963 if (status == common::V1_0::Status::OK) {
2964 const camera_metadata *r =
2965 reinterpret_cast<const camera_metadata_t*>(request.data());
2966 size_t expectedSize = request.size();
2967 int ret = validate_camera_metadata_structure(r, &expectedSize);
2968 if (ret == OK || ret == CAMERA_METADATA_VALIDATION_SHIFTED) {
2969 *requestTemplate = clone_camera_metadata(r);
2970 if (*requestTemplate == nullptr) {
2971 ALOGE("%s: Unable to clone camera metadata received from HAL",
2972 __FUNCTION__);
Emilian Peev31abd0a2017-05-11 18:37:46 +01002973 status = common::V1_0::Status::INTERNAL_ERROR;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002974 }
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002975 } else {
2976 ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
2977 status = common::V1_0::Status::INTERNAL_ERROR;
Emilian Peev31abd0a2017-05-11 18:37:46 +01002978 }
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002979 }
2980 };
2981 hardware::Return<void> err;
Eino-Ville Talvala96441462018-02-06 11:41:55 -08002982 RequestTemplate id;
2983 switch (templateId) {
2984 case CAMERA3_TEMPLATE_PREVIEW:
2985 id = RequestTemplate::PREVIEW;
2986 break;
2987 case CAMERA3_TEMPLATE_STILL_CAPTURE:
2988 id = RequestTemplate::STILL_CAPTURE;
2989 break;
2990 case CAMERA3_TEMPLATE_VIDEO_RECORD:
2991 id = RequestTemplate::VIDEO_RECORD;
2992 break;
2993 case CAMERA3_TEMPLATE_VIDEO_SNAPSHOT:
2994 id = RequestTemplate::VIDEO_SNAPSHOT;
2995 break;
2996 case CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG:
2997 id = RequestTemplate::ZERO_SHUTTER_LAG;
2998 break;
2999 case CAMERA3_TEMPLATE_MANUAL:
3000 id = RequestTemplate::MANUAL;
3001 break;
3002 default:
3003 // Unknown template ID, or this HAL is too old to support it
3004 return BAD_VALUE;
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08003005 }
Eino-Ville Talvala96441462018-02-06 11:41:55 -08003006 err = mHidlSession->constructDefaultRequestSettings(id, requestCallback);
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08003007
Emilian Peev31abd0a2017-05-11 18:37:46 +01003008 if (!err.isOk()) {
3009 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3010 res = DEAD_OBJECT;
3011 } else {
3012 res = CameraProviderManager::mapToStatusT(status);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003013 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003014
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003015 return res;
3016}
3017
Emilian Peev4ec17882019-01-24 17:16:58 -08003018bool Camera3Device::HalInterface::isReconfigurationRequired(CameraMetadata& oldSessionParams,
3019 CameraMetadata& newSessionParams) {
3020 // We do reconfiguration by default;
3021 bool ret = true;
3022 if ((mHidlSession_3_5 != nullptr) && mIsReconfigurationQuerySupported) {
3023 android::hardware::hidl_vec<uint8_t> oldParams, newParams;
3024 camera_metadata_t* oldSessioMeta = const_cast<camera_metadata_t*>(
3025 oldSessionParams.getAndLock());
3026 camera_metadata_t* newSessioMeta = const_cast<camera_metadata_t*>(
3027 newSessionParams.getAndLock());
3028 oldParams.setToExternal(reinterpret_cast<uint8_t*>(oldSessioMeta),
3029 get_camera_metadata_size(oldSessioMeta));
3030 newParams.setToExternal(reinterpret_cast<uint8_t*>(newSessioMeta),
3031 get_camera_metadata_size(newSessioMeta));
3032 hardware::camera::common::V1_0::Status callStatus;
3033 bool required;
3034 auto hidlCb = [&callStatus, &required] (hardware::camera::common::V1_0::Status s,
3035 bool requiredFlag) {
3036 callStatus = s;
3037 required = requiredFlag;
3038 };
3039 auto err = mHidlSession_3_5->isReconfigurationRequired(oldParams, newParams, hidlCb);
3040 oldSessionParams.unlock(oldSessioMeta);
3041 newSessionParams.unlock(newSessioMeta);
3042 if (err.isOk()) {
3043 switch (callStatus) {
3044 case hardware::camera::common::V1_0::Status::OK:
3045 ret = required;
3046 break;
3047 case hardware::camera::common::V1_0::Status::METHOD_NOT_SUPPORTED:
3048 mIsReconfigurationQuerySupported = false;
3049 ret = true;
3050 break;
3051 default:
3052 ALOGV("%s: Reconfiguration query failed: %d", __FUNCTION__, callStatus);
3053 ret = true;
3054 }
3055 } else {
3056 ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, err.description().c_str());
3057 ret = true;
3058 }
3059 }
3060
3061 return ret;
3062}
3063
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01003064status_t Camera3Device::HalInterface::configureStreams(const camera_metadata_t *sessionParams,
Emilian Peev192ee832018-01-31 14:46:47 +00003065 camera3_stream_configuration *config, const std::vector<uint32_t>& bufferSizes) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003066 ATRACE_NAME("CameraHal::configureStreams");
3067 if (!valid()) return INVALID_OPERATION;
3068 status_t res = OK;
3069
Emilian Peev31abd0a2017-05-11 18:37:46 +01003070 // Convert stream config to HIDL
3071 std::set<int> activeStreams;
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003072 device::V3_2::StreamConfiguration requestedConfiguration3_2;
3073 device::V3_4::StreamConfiguration requestedConfiguration3_4;
3074 requestedConfiguration3_2.streams.resize(config->num_streams);
3075 requestedConfiguration3_4.streams.resize(config->num_streams);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003076 for (size_t i = 0; i < config->num_streams; i++) {
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003077 device::V3_2::Stream &dst3_2 = requestedConfiguration3_2.streams[i];
3078 device::V3_4::Stream &dst3_4 = requestedConfiguration3_4.streams[i];
Emilian Peev31abd0a2017-05-11 18:37:46 +01003079 camera3_stream_t *src = config->streams[i];
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003080
Emilian Peev31abd0a2017-05-11 18:37:46 +01003081 Camera3Stream* cam3stream = Camera3Stream::cast(src);
3082 cam3stream->setBufferFreedListener(this);
3083 int streamId = cam3stream->getId();
3084 StreamType streamType;
3085 switch (src->stream_type) {
3086 case CAMERA3_STREAM_OUTPUT:
3087 streamType = StreamType::OUTPUT;
3088 break;
3089 case CAMERA3_STREAM_INPUT:
3090 streamType = StreamType::INPUT;
3091 break;
3092 default:
3093 ALOGE("%s: Stream %d: Unsupported stream type %d",
3094 __FUNCTION__, streamId, config->streams[i]->stream_type);
3095 return BAD_VALUE;
3096 }
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003097 dst3_2.id = streamId;
3098 dst3_2.streamType = streamType;
3099 dst3_2.width = src->width;
3100 dst3_2.height = src->height;
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003101 dst3_2.usage = mapToConsumerUsage(cam3stream->getUsage());
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003102 dst3_2.rotation = mapToStreamRotation((camera3_stream_rotation_t) src->rotation);
Shuzhen Wang92653952019-05-07 15:11:43 -07003103 // For HidlSession version 3.5 or newer, the format and dataSpace sent
3104 // to HAL are original, not the overriden ones.
3105 if (mHidlSession_3_5 != nullptr) {
3106 dst3_2.format = mapToPixelFormat(cam3stream->isFormatOverridden() ?
3107 cam3stream->getOriginalFormat() : src->format);
3108 dst3_2.dataSpace = mapToHidlDataspace(cam3stream->isDataSpaceOverridden() ?
3109 cam3stream->getOriginalDataSpace() : src->data_space);
3110 } else {
3111 dst3_2.format = mapToPixelFormat(src->format);
3112 dst3_2.dataSpace = mapToHidlDataspace(src->data_space);
3113 }
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003114 dst3_4.v3_2 = dst3_2;
Emilian Peev192ee832018-01-31 14:46:47 +00003115 dst3_4.bufferSize = bufferSizes[i];
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003116 if (src->physical_camera_id != nullptr) {
3117 dst3_4.physicalCameraId = src->physical_camera_id;
3118 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003119
3120 activeStreams.insert(streamId);
3121 // Create Buffer ID map if necessary
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003122 mBufferRecords.tryCreateBufferCache(streamId);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003123 }
3124 // remove BufferIdMap for deleted streams
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003125 mBufferRecords.removeInactiveBufferCaches(activeStreams);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003126
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003127 StreamConfigurationMode operationMode;
Emilian Peev31abd0a2017-05-11 18:37:46 +01003128 res = mapToStreamConfigurationMode(
3129 (camera3_stream_configuration_mode_t) config->operation_mode,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003130 /*out*/ &operationMode);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003131 if (res != OK) {
3132 return res;
3133 }
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003134 requestedConfiguration3_2.operationMode = operationMode;
3135 requestedConfiguration3_4.operationMode = operationMode;
3136 requestedConfiguration3_4.sessionParams.setToExternal(
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01003137 reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams)),
3138 get_camera_metadata_size(sessionParams));
3139
Emilian Peev31abd0a2017-05-11 18:37:46 +01003140 // Invoke configureStreams
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003141 device::V3_3::HalStreamConfiguration finalConfiguration;
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003142 device::V3_4::HalStreamConfiguration finalConfiguration3_4;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003143 device::V3_6::HalStreamConfiguration finalConfiguration3_6;
Emilian Peev31abd0a2017-05-11 18:37:46 +01003144 common::V1_0::Status status;
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003145
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003146 auto configStream34Cb = [&status, &finalConfiguration3_4]
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003147 (common::V1_0::Status s, const device::V3_4::HalStreamConfiguration& halConfiguration) {
3148 finalConfiguration3_4 = halConfiguration;
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01003149 status = s;
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003150 };
3151
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003152 auto configStream36Cb = [&status, &finalConfiguration3_6]
3153 (common::V1_0::Status s, const device::V3_6::HalStreamConfiguration& halConfiguration) {
3154 finalConfiguration3_6 = halConfiguration;
3155 status = s;
3156 };
3157
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003158 auto postprocConfigStream34 = [&finalConfiguration, &finalConfiguration3_4]
3159 (hardware::Return<void>& err) -> status_t {
3160 if (!err.isOk()) {
3161 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3162 return DEAD_OBJECT;
3163 }
3164 finalConfiguration.streams.resize(finalConfiguration3_4.streams.size());
3165 for (size_t i = 0; i < finalConfiguration3_4.streams.size(); i++) {
3166 finalConfiguration.streams[i] = finalConfiguration3_4.streams[i].v3_3;
3167 }
3168 return OK;
3169 };
3170
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003171 auto postprocConfigStream36 = [&finalConfiguration, &finalConfiguration3_6]
3172 (hardware::Return<void>& err) -> status_t {
3173 if (!err.isOk()) {
3174 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3175 return DEAD_OBJECT;
3176 }
3177 finalConfiguration.streams.resize(finalConfiguration3_6.streams.size());
3178 for (size_t i = 0; i < finalConfiguration3_6.streams.size(); i++) {
3179 finalConfiguration.streams[i] = finalConfiguration3_6.streams[i].v3_4.v3_3;
3180 }
3181 return OK;
3182 };
3183
Shuzhen Wang92653952019-05-07 15:11:43 -07003184 // See which version of HAL we have
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003185 if (mHidlSession_3_6 != nullptr) {
3186 ALOGV("%s: v3.6 device found", __FUNCTION__);
3187 device::V3_5::StreamConfiguration requestedConfiguration3_5;
3188 requestedConfiguration3_5.v3_4 = requestedConfiguration3_4;
3189 requestedConfiguration3_5.streamConfigCounter = mNextStreamConfigCounter++;
3190 auto err = mHidlSession_3_6->configureStreams_3_6(
3191 requestedConfiguration3_5, configStream36Cb);
3192 res = postprocConfigStream36(err);
3193 if (res != OK) {
3194 return res;
3195 }
3196 } else if (mHidlSession_3_5 != nullptr) {
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003197 ALOGV("%s: v3.5 device found", __FUNCTION__);
3198 device::V3_5::StreamConfiguration requestedConfiguration3_5;
3199 requestedConfiguration3_5.v3_4 = requestedConfiguration3_4;
3200 requestedConfiguration3_5.streamConfigCounter = mNextStreamConfigCounter++;
3201 auto err = mHidlSession_3_5->configureStreams_3_5(
3202 requestedConfiguration3_5, configStream34Cb);
3203 res = postprocConfigStream34(err);
3204 if (res != OK) {
3205 return res;
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01003206 }
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003207 } else if (mHidlSession_3_4 != nullptr) {
3208 // We do; use v3.4 for the call
3209 ALOGV("%s: v3.4 device found", __FUNCTION__);
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003210 auto err = mHidlSession_3_4->configureStreams_3_4(
3211 requestedConfiguration3_4, configStream34Cb);
3212 res = postprocConfigStream34(err);
3213 if (res != OK) {
3214 return res;
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003215 }
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08003216 } else if (mHidlSession_3_3 != nullptr) {
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003217 // We do; use v3.3 for the call
3218 ALOGV("%s: v3.3 device found", __FUNCTION__);
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08003219 auto err = mHidlSession_3_3->configureStreams_3_3(requestedConfiguration3_2,
Emilian Peev31abd0a2017-05-11 18:37:46 +01003220 [&status, &finalConfiguration]
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003221 (common::V1_0::Status s, const device::V3_3::HalStreamConfiguration& halConfiguration) {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003222 finalConfiguration = halConfiguration;
3223 status = s;
3224 });
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003225 if (!err.isOk()) {
3226 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3227 return DEAD_OBJECT;
3228 }
3229 } else {
3230 // We don't; use v3.2 call and construct a v3.3 HalStreamConfiguration
3231 ALOGV("%s: v3.2 device found", __FUNCTION__);
3232 HalStreamConfiguration finalConfiguration_3_2;
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003233 auto err = mHidlSession->configureStreams(requestedConfiguration3_2,
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003234 [&status, &finalConfiguration_3_2]
3235 (common::V1_0::Status s, const HalStreamConfiguration& halConfiguration) {
3236 finalConfiguration_3_2 = halConfiguration;
3237 status = s;
3238 });
3239 if (!err.isOk()) {
3240 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3241 return DEAD_OBJECT;
3242 }
3243 finalConfiguration.streams.resize(finalConfiguration_3_2.streams.size());
3244 for (size_t i = 0; i < finalConfiguration_3_2.streams.size(); i++) {
3245 finalConfiguration.streams[i].v3_2 = finalConfiguration_3_2.streams[i];
3246 finalConfiguration.streams[i].overrideDataSpace =
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003247 requestedConfiguration3_2.streams[i].dataSpace;
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003248 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003249 }
3250
3251 if (status != common::V1_0::Status::OK ) {
3252 return CameraProviderManager::mapToStatusT(status);
3253 }
3254
3255 // And convert output stream configuration from HIDL
3256
3257 for (size_t i = 0; i < config->num_streams; i++) {
3258 camera3_stream_t *dst = config->streams[i];
3259 int streamId = Camera3Stream::cast(dst)->getId();
3260
3261 // Start scan at i, with the assumption that the stream order matches
3262 size_t realIdx = i;
3263 bool found = false;
Eino-Ville Talvala370875f2019-04-12 12:40:27 -07003264 size_t halStreamCount = finalConfiguration.streams.size();
3265 for (size_t idx = 0; idx < halStreamCount; idx++) {
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003266 if (finalConfiguration.streams[realIdx].v3_2.id == streamId) {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003267 found = true;
3268 break;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003269 }
Eino-Ville Talvala370875f2019-04-12 12:40:27 -07003270 realIdx = (realIdx >= halStreamCount - 1) ? 0 : realIdx + 1;
Emilian Peev31abd0a2017-05-11 18:37:46 +01003271 }
3272 if (!found) {
3273 ALOGE("%s: Stream %d not found in stream configuration response from HAL",
3274 __FUNCTION__, streamId);
3275 return INVALID_OPERATION;
3276 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003277 device::V3_3::HalStream &src = finalConfiguration.streams[realIdx];
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003278 device::V3_6::HalStream &src_36 = finalConfiguration3_6.streams[realIdx];
Yin-Chia Yeh77327052017-01-09 18:23:07 -08003279
Emilian Peev710c1422017-08-30 11:19:38 +01003280 Camera3Stream* dstStream = Camera3Stream::cast(dst);
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003281 int overrideFormat = mapToFrameworkFormat(src.v3_2.overrideFormat);
3282 android_dataspace overrideDataSpace = mapToFrameworkDataspace(src.overrideDataSpace);
3283
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003284 if (mHidlSession_3_6 != nullptr) {
3285 dstStream->setOfflineProcessingSupport(src_36.supportOffline);
3286 }
3287
Yin-Chia Yeh90667662019-07-01 15:45:00 -07003288 if (dstStream->getOriginalFormat() != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
Shuzhen Wang92653952019-05-07 15:11:43 -07003289 dstStream->setFormatOverride(false);
3290 dstStream->setDataSpaceOverride(false);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003291 if (dst->format != overrideFormat) {
3292 ALOGE("%s: Stream %d: Format override not allowed for format 0x%x", __FUNCTION__,
3293 streamId, dst->format);
Yin-Chia Yeh77327052017-01-09 18:23:07 -08003294 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003295 if (dst->data_space != overrideDataSpace) {
3296 ALOGE("%s: Stream %d: DataSpace override not allowed for format 0x%x", __FUNCTION__,
3297 streamId, dst->format);
3298 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003299 } else {
Shuzhen Wang92653952019-05-07 15:11:43 -07003300 bool needFormatOverride =
3301 requestedConfiguration3_2.streams[i].format != src.v3_2.overrideFormat;
3302 bool needDataspaceOverride =
3303 requestedConfiguration3_2.streams[i].dataSpace != src.overrideDataSpace;
Emilian Peev31abd0a2017-05-11 18:37:46 +01003304 // Override allowed with IMPLEMENTATION_DEFINED
Shuzhen Wang92653952019-05-07 15:11:43 -07003305 dstStream->setFormatOverride(needFormatOverride);
3306 dstStream->setDataSpaceOverride(needDataspaceOverride);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003307 dst->format = overrideFormat;
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003308 dst->data_space = overrideDataSpace;
Yin-Chia Yeh77327052017-01-09 18:23:07 -08003309 }
3310
Emilian Peev31abd0a2017-05-11 18:37:46 +01003311 if (dst->stream_type == CAMERA3_STREAM_INPUT) {
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003312 if (src.v3_2.producerUsage != 0) {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003313 ALOGE("%s: Stream %d: INPUT streams must have 0 for producer usage",
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003314 __FUNCTION__, streamId);
3315 return INVALID_OPERATION;
3316 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003317 dstStream->setUsage(
3318 mapConsumerToFrameworkUsage(src.v3_2.consumerUsage));
Emilian Peev31abd0a2017-05-11 18:37:46 +01003319 } else {
3320 // OUTPUT
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003321 if (src.v3_2.consumerUsage != 0) {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003322 ALOGE("%s: Stream %d: OUTPUT streams must have 0 for consumer usage",
3323 __FUNCTION__, streamId);
3324 return INVALID_OPERATION;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003325 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003326 dstStream->setUsage(
3327 mapProducerToFrameworkUsage(src.v3_2.producerUsage));
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003328 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003329 dst->max_buffers = src.v3_2.maxBuffers;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003330 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003331
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003332 return res;
3333}
3334
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003335status_t Camera3Device::HalInterface::wrapAsHidlRequest(camera3_capture_request_t* request,
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003336 /*out*/device::V3_2::CaptureRequest* captureRequest,
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003337 /*out*/std::vector<native_handle_t*>* handlesCreated,
3338 /*out*/std::vector<std::pair<int32_t, int32_t>>* inflightBuffers) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003339 ATRACE_CALL();
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003340 if (captureRequest == nullptr || handlesCreated == nullptr || inflightBuffers == nullptr) {
3341 ALOGE("%s: captureRequest (%p), handlesCreated (%p), and inflightBuffers(%p) "
3342 "must not be null", __FUNCTION__, captureRequest, handlesCreated, inflightBuffers);
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003343 return BAD_VALUE;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003344 }
3345
3346 captureRequest->frameNumber = request->frame_number;
Yifan Hongf79b5542017-04-11 14:44:25 -07003347
3348 captureRequest->fmqSettingsSize = 0;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003349
3350 {
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003351 if (request->input_buffer != nullptr) {
3352 int32_t streamId = Camera3Stream::cast(request->input_buffer->stream)->getId();
3353 buffer_handle_t buf = *(request->input_buffer->buffer);
3354 auto pair = getBufferId(buf, streamId);
3355 bool isNewBuffer = pair.first;
3356 uint64_t bufferId = pair.second;
3357 captureRequest->inputBuffer.streamId = streamId;
3358 captureRequest->inputBuffer.bufferId = bufferId;
3359 captureRequest->inputBuffer.buffer = (isNewBuffer) ? buf : nullptr;
3360 captureRequest->inputBuffer.status = BufferStatus::OK;
3361 native_handle_t *acquireFence = nullptr;
3362 if (request->input_buffer->acquire_fence != -1) {
3363 acquireFence = native_handle_create(1,0);
3364 acquireFence->data[0] = request->input_buffer->acquire_fence;
3365 handlesCreated->push_back(acquireFence);
3366 }
3367 captureRequest->inputBuffer.acquireFence = acquireFence;
3368 captureRequest->inputBuffer.releaseFence = nullptr;
3369
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003370 mBufferRecords.pushInflightBuffer(captureRequest->frameNumber, streamId,
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003371 request->input_buffer->buffer);
3372 inflightBuffers->push_back(std::make_pair(captureRequest->frameNumber, streamId));
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003373 } else {
3374 captureRequest->inputBuffer.streamId = -1;
3375 captureRequest->inputBuffer.bufferId = BUFFER_ID_NO_BUFFER;
3376 }
3377
3378 captureRequest->outputBuffers.resize(request->num_output_buffers);
3379 for (size_t i = 0; i < request->num_output_buffers; i++) {
3380 const camera3_stream_buffer_t *src = request->output_buffers + i;
3381 StreamBuffer &dst = captureRequest->outputBuffers[i];
3382 int32_t streamId = Camera3Stream::cast(src->stream)->getId();
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003383 if (src->buffer != nullptr) {
3384 buffer_handle_t buf = *(src->buffer);
3385 auto pair = getBufferId(buf, streamId);
3386 bool isNewBuffer = pair.first;
3387 dst.bufferId = pair.second;
3388 dst.buffer = isNewBuffer ? buf : nullptr;
3389 native_handle_t *acquireFence = nullptr;
3390 if (src->acquire_fence != -1) {
3391 acquireFence = native_handle_create(1,0);
3392 acquireFence->data[0] = src->acquire_fence;
3393 handlesCreated->push_back(acquireFence);
3394 }
3395 dst.acquireFence = acquireFence;
3396 } else if (mUseHalBufManager) {
3397 // HAL buffer management path
3398 dst.bufferId = BUFFER_ID_NO_BUFFER;
3399 dst.buffer = nullptr;
3400 dst.acquireFence = nullptr;
3401 } else {
3402 ALOGE("%s: cannot send a null buffer in capture request!", __FUNCTION__);
3403 return BAD_VALUE;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003404 }
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003405 dst.streamId = streamId;
3406 dst.status = BufferStatus::OK;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003407 dst.releaseFence = nullptr;
3408
Yin-Chia Yeh5f840f82019-03-05 11:59:04 -08003409 // Output buffers are empty when using HAL buffer manager
3410 if (!mUseHalBufManager) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003411 mBufferRecords.pushInflightBuffer(
3412 captureRequest->frameNumber, streamId, src->buffer);
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003413 inflightBuffers->push_back(std::make_pair(captureRequest->frameNumber, streamId));
Yin-Chia Yeh5f840f82019-03-05 11:59:04 -08003414 }
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003415 }
3416 }
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003417 return OK;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003418}
3419
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003420void Camera3Device::HalInterface::cleanupNativeHandles(
3421 std::vector<native_handle_t*> *handles, bool closeFd) {
3422 if (handles == nullptr) {
3423 return;
3424 }
3425 if (closeFd) {
3426 for (auto& handle : *handles) {
3427 native_handle_close(handle);
3428 }
3429 }
3430 for (auto& handle : *handles) {
3431 native_handle_delete(handle);
3432 }
3433 handles->clear();
3434 return;
3435}
3436
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003437status_t Camera3Device::HalInterface::processBatchCaptureRequests(
3438 std::vector<camera3_capture_request_t*>& requests,/*out*/uint32_t* numRequestProcessed) {
3439 ATRACE_NAME("CameraHal::processBatchCaptureRequests");
3440 if (!valid()) return INVALID_OPERATION;
3441
Emilian Peevaebbe412018-01-15 13:53:24 +00003442 sp<device::V3_4::ICameraDeviceSession> hidlSession_3_4;
3443 auto castResult_3_4 = device::V3_4::ICameraDeviceSession::castFrom(mHidlSession);
3444 if (castResult_3_4.isOk()) {
3445 hidlSession_3_4 = castResult_3_4;
3446 }
3447
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003448 hardware::hidl_vec<device::V3_2::CaptureRequest> captureRequests;
Emilian Peevaebbe412018-01-15 13:53:24 +00003449 hardware::hidl_vec<device::V3_4::CaptureRequest> captureRequests_3_4;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003450 size_t batchSize = requests.size();
Emilian Peevaebbe412018-01-15 13:53:24 +00003451 if (hidlSession_3_4 != nullptr) {
3452 captureRequests_3_4.resize(batchSize);
3453 } else {
3454 captureRequests.resize(batchSize);
3455 }
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003456 std::vector<native_handle_t*> handlesCreated;
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003457 std::vector<std::pair<int32_t, int32_t>> inflightBuffers;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003458
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003459 status_t res = OK;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003460 for (size_t i = 0; i < batchSize; i++) {
Emilian Peevaebbe412018-01-15 13:53:24 +00003461 if (hidlSession_3_4 != nullptr) {
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003462 res = wrapAsHidlRequest(requests[i], /*out*/&captureRequests_3_4[i].v3_2,
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003463 /*out*/&handlesCreated, /*out*/&inflightBuffers);
Emilian Peevaebbe412018-01-15 13:53:24 +00003464 } else {
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003465 res = wrapAsHidlRequest(requests[i], /*out*/&captureRequests[i],
3466 /*out*/&handlesCreated, /*out*/&inflightBuffers);
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003467 }
3468 if (res != OK) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003469 mBufferRecords.popInflightBuffers(inflightBuffers);
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003470 cleanupNativeHandles(&handlesCreated);
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003471 return res;
Emilian Peevaebbe412018-01-15 13:53:24 +00003472 }
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003473 }
3474
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003475 std::vector<device::V3_2::BufferCache> cachesToRemove;
3476 {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003477 std::lock_guard<std::mutex> lock(mFreedBuffersLock);
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003478 for (auto& pair : mFreedBuffers) {
3479 // The stream might have been removed since onBufferFreed
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003480 if (mBufferRecords.isStreamCached(pair.first)) {
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003481 cachesToRemove.push_back({pair.first, pair.second});
3482 }
3483 }
3484 mFreedBuffers.clear();
3485 }
3486
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003487 common::V1_0::Status status = common::V1_0::Status::INTERNAL_ERROR;
3488 *numRequestProcessed = 0;
Yifan Hongf79b5542017-04-11 14:44:25 -07003489
3490 // Write metadata to FMQ.
3491 for (size_t i = 0; i < batchSize; i++) {
3492 camera3_capture_request_t* request = requests[i];
Emilian Peevaebbe412018-01-15 13:53:24 +00003493 device::V3_2::CaptureRequest* captureRequest;
3494 if (hidlSession_3_4 != nullptr) {
3495 captureRequest = &captureRequests_3_4[i].v3_2;
3496 } else {
3497 captureRequest = &captureRequests[i];
3498 }
Yifan Hongf79b5542017-04-11 14:44:25 -07003499
3500 if (request->settings != nullptr) {
3501 size_t settingsSize = get_camera_metadata_size(request->settings);
3502 if (mRequestMetadataQueue != nullptr && mRequestMetadataQueue->write(
3503 reinterpret_cast<const uint8_t*>(request->settings), settingsSize)) {
3504 captureRequest->settings.resize(0);
3505 captureRequest->fmqSettingsSize = settingsSize;
3506 } else {
3507 if (mRequestMetadataQueue != nullptr) {
3508 ALOGW("%s: couldn't utilize fmq, fallback to hwbinder", __FUNCTION__);
3509 }
3510 captureRequest->settings.setToExternal(
3511 reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(request->settings)),
3512 get_camera_metadata_size(request->settings));
3513 captureRequest->fmqSettingsSize = 0u;
3514 }
3515 } else {
3516 // A null request settings maps to a size-0 CameraMetadata
3517 captureRequest->settings.resize(0);
3518 captureRequest->fmqSettingsSize = 0u;
3519 }
Emilian Peevaebbe412018-01-15 13:53:24 +00003520
3521 if (hidlSession_3_4 != nullptr) {
3522 captureRequests_3_4[i].physicalCameraSettings.resize(request->num_physcam_settings);
3523 for (size_t j = 0; j < request->num_physcam_settings; j++) {
Emilian Peev00420d22018-02-05 21:33:13 +00003524 if (request->physcam_settings != nullptr) {
3525 size_t settingsSize = get_camera_metadata_size(request->physcam_settings[j]);
3526 if (mRequestMetadataQueue != nullptr && mRequestMetadataQueue->write(
3527 reinterpret_cast<const uint8_t*>(request->physcam_settings[j]),
3528 settingsSize)) {
3529 captureRequests_3_4[i].physicalCameraSettings[j].settings.resize(0);
3530 captureRequests_3_4[i].physicalCameraSettings[j].fmqSettingsSize =
3531 settingsSize;
3532 } else {
3533 if (mRequestMetadataQueue != nullptr) {
3534 ALOGW("%s: couldn't utilize fmq, fallback to hwbinder", __FUNCTION__);
3535 }
3536 captureRequests_3_4[i].physicalCameraSettings[j].settings.setToExternal(
3537 reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(
3538 request->physcam_settings[j])),
3539 get_camera_metadata_size(request->physcam_settings[j]));
3540 captureRequests_3_4[i].physicalCameraSettings[j].fmqSettingsSize = 0u;
Emilian Peevaebbe412018-01-15 13:53:24 +00003541 }
Emilian Peev00420d22018-02-05 21:33:13 +00003542 } else {
Emilian Peevaebbe412018-01-15 13:53:24 +00003543 captureRequests_3_4[i].physicalCameraSettings[j].fmqSettingsSize = 0u;
Emilian Peev00420d22018-02-05 21:33:13 +00003544 captureRequests_3_4[i].physicalCameraSettings[j].settings.resize(0);
Emilian Peevaebbe412018-01-15 13:53:24 +00003545 }
3546 captureRequests_3_4[i].physicalCameraSettings[j].physicalCameraId =
3547 request->physcam_id[j];
3548 }
3549 }
Yifan Hongf79b5542017-04-11 14:44:25 -07003550 }
Emilian Peevaebbe412018-01-15 13:53:24 +00003551
3552 hardware::details::return_status err;
Jayant Chowdharyc8d581e2018-07-16 14:46:23 -07003553 auto resultCallback =
3554 [&status, &numRequestProcessed] (auto s, uint32_t n) {
3555 status = s;
3556 *numRequestProcessed = n;
3557 };
Emilian Peevaebbe412018-01-15 13:53:24 +00003558 if (hidlSession_3_4 != nullptr) {
3559 err = hidlSession_3_4->processCaptureRequest_3_4(captureRequests_3_4, cachesToRemove,
Jayant Chowdharyc8d581e2018-07-16 14:46:23 -07003560 resultCallback);
Emilian Peevaebbe412018-01-15 13:53:24 +00003561 } else {
3562 err = mHidlSession->processCaptureRequest(captureRequests, cachesToRemove,
Jayant Chowdharyc8d581e2018-07-16 14:46:23 -07003563 resultCallback);
Emilian Peevaebbe412018-01-15 13:53:24 +00003564 }
Eino-Ville Talvalac5cbb872017-04-27 12:48:33 -07003565 if (!err.isOk()) {
3566 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003567 status = common::V1_0::Status::CAMERA_DISCONNECTED;
Eino-Ville Talvalac5cbb872017-04-27 12:48:33 -07003568 }
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003569
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003570 if (status == common::V1_0::Status::OK && *numRequestProcessed != batchSize) {
3571 ALOGE("%s: processCaptureRequest returns OK but processed %d/%zu requests",
3572 __FUNCTION__, *numRequestProcessed, batchSize);
3573 status = common::V1_0::Status::INTERNAL_ERROR;
3574 }
3575
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003576 res = CameraProviderManager::mapToStatusT(status);
3577 if (res == OK) {
3578 if (mHidlSession->isRemote()) {
3579 // Only close acquire fence FDs when the HIDL transaction succeeds (so the FDs have been
3580 // sent to camera HAL processes)
3581 cleanupNativeHandles(&handlesCreated, /*closeFd*/true);
3582 } else {
3583 // In passthrough mode the FDs are now owned by HAL
3584 cleanupNativeHandles(&handlesCreated);
3585 }
3586 } else {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003587 mBufferRecords.popInflightBuffers(inflightBuffers);
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003588 cleanupNativeHandles(&handlesCreated);
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003589 }
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003590 return res;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003591}
3592
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003593status_t Camera3Device::HalInterface::flush() {
3594 ATRACE_NAME("CameraHal::flush");
3595 if (!valid()) return INVALID_OPERATION;
3596 status_t res = OK;
3597
Emilian Peev31abd0a2017-05-11 18:37:46 +01003598 auto err = mHidlSession->flush();
3599 if (!err.isOk()) {
3600 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3601 res = DEAD_OBJECT;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003602 } else {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003603 res = CameraProviderManager::mapToStatusT(err);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003604 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003605
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003606 return res;
3607}
3608
Emilian Peev31abd0a2017-05-11 18:37:46 +01003609status_t Camera3Device::HalInterface::dump(int /*fd*/) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003610 ATRACE_NAME("CameraHal::dump");
3611 if (!valid()) return INVALID_OPERATION;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003612
Emilian Peev31abd0a2017-05-11 18:37:46 +01003613 // Handled by CameraProviderManager::dump
3614
3615 return OK;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003616}
3617
3618status_t Camera3Device::HalInterface::close() {
3619 ATRACE_NAME("CameraHal::close()");
3620 if (!valid()) return INVALID_OPERATION;
3621 status_t res = OK;
3622
Emilian Peev31abd0a2017-05-11 18:37:46 +01003623 auto err = mHidlSession->close();
3624 // Interface will be dead shortly anyway, so don't log errors
3625 if (!err.isOk()) {
3626 res = DEAD_OBJECT;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003627 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003628
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003629 return res;
3630}
3631
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003632void Camera3Device::HalInterface::signalPipelineDrain(const std::vector<int>& streamIds) {
3633 ATRACE_NAME("CameraHal::signalPipelineDrain");
3634 if (!valid() || mHidlSession_3_5 == nullptr) {
3635 ALOGE("%s called on invalid camera!", __FUNCTION__);
3636 return;
3637 }
3638
Yin-Chia Yehc300a072019-02-13 14:56:57 -08003639 auto err = mHidlSession_3_5->signalStreamFlush(streamIds, mNextStreamConfigCounter - 1);
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003640 if (!err.isOk()) {
3641 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3642 return;
3643 }
3644}
3645
Yin-Chia Yehb978c382019-10-30 00:22:37 -07003646status_t Camera3Device::HalInterface::switchToOffline(
3647 const std::vector<int32_t>& streamsToKeep,
3648 /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003649 /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
3650 /*out*/camera3::BufferRecords* bufferRecords) {
Yin-Chia Yehb978c382019-10-30 00:22:37 -07003651 ATRACE_NAME("CameraHal::switchToOffline");
3652 if (!valid() || mHidlSession_3_6 == nullptr) {
3653 ALOGE("%s called on invalid camera!", __FUNCTION__);
3654 return INVALID_OPERATION;
3655 }
3656
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003657 if (offlineSessionInfo == nullptr || offlineSession == nullptr || bufferRecords == nullptr) {
3658 ALOGE("%s: output arguments must not be null!", __FUNCTION__);
Yin-Chia Yehb978c382019-10-30 00:22:37 -07003659 return INVALID_OPERATION;
3660 }
3661
3662 common::V1_0::Status status = common::V1_0::Status::INTERNAL_ERROR;
Yin-Chia Yehb978c382019-10-30 00:22:37 -07003663 auto resultCallback =
3664 [&status, &offlineSessionInfo, &offlineSession] (auto s, auto info, auto session) {
3665 status = s;
3666 *offlineSessionInfo = info;
3667 *offlineSession = session;
3668 };
3669 auto err = mHidlSession_3_6->switchToOffline(streamsToKeep, resultCallback);
3670
3671 if (!err.isOk()) {
3672 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3673 return DEAD_OBJECT;
3674 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003675
3676 status_t ret = CameraProviderManager::mapToStatusT(status);
3677 if (ret != OK) {
3678 return ret;
3679 }
3680
3681 // TODO: assert no ongoing requestBuffer/returnBuffer call here
3682 // TODO: update RequestBufferStateMachine to block requestBuffer/returnBuffer once HAL
3683 // returns from switchToOffline.
3684
3685
3686 // Validate buffer caches
3687 std::vector<int32_t> streams;
3688 streams.reserve(offlineSessionInfo->offlineStreams.size());
3689 for (auto offlineStream : offlineSessionInfo->offlineStreams) {
3690 int32_t id = offlineStream.id;
3691 streams.push_back(id);
3692 // Verify buffer caches
3693 std::vector<uint64_t> bufIds(offlineStream.circulatingBufferIds.begin(),
3694 offlineStream.circulatingBufferIds.end());
3695 if (!verifyBufferIds(id, bufIds)) {
3696 ALOGE("%s: stream ID %d buffer cache records mismatch!", __FUNCTION__, id);
3697 return UNKNOWN_ERROR;
3698 }
3699 }
3700
3701 // Move buffer records
3702 bufferRecords->takeBufferCaches(mBufferRecords, streams);
3703 bufferRecords->takeInflightBufferMap(mBufferRecords);
3704 bufferRecords->takeRequestedBufferMap(mBufferRecords);
3705 return ret;
Yin-Chia Yehb978c382019-10-30 00:22:37 -07003706}
3707
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07003708void Camera3Device::HalInterface::getInflightBufferKeys(
3709 std::vector<std::pair<int32_t, int32_t>>* out) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003710 mBufferRecords.getInflightBufferKeys(out);
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07003711 return;
3712}
3713
Yin-Chia Yeh84be5782019-03-01 11:47:02 -08003714void Camera3Device::HalInterface::getInflightRequestBufferKeys(
3715 std::vector<uint64_t>* out) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003716 mBufferRecords.getInflightRequestBufferKeys(out);
Yin-Chia Yeh84be5782019-03-01 11:47:02 -08003717 return;
3718}
3719
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003720bool Camera3Device::HalInterface::verifyBufferIds(
3721 int32_t streamId, std::vector<uint64_t>& bufIds) {
3722 return mBufferRecords.verifyBufferIds(streamId, bufIds);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003723}
3724
3725status_t Camera3Device::HalInterface::popInflightBuffer(
Yin-Chia Yehf4650602017-01-10 13:13:39 -08003726 int32_t frameNumber, int32_t streamId,
3727 /*out*/ buffer_handle_t **buffer) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003728 return mBufferRecords.popInflightBuffer(frameNumber, streamId, buffer);
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003729}
3730
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07003731status_t Camera3Device::HalInterface::pushInflightRequestBuffer(
Yin-Chia Yeh84be5782019-03-01 11:47:02 -08003732 uint64_t bufferId, buffer_handle_t* buf, int32_t streamId) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003733 return mBufferRecords.pushInflightRequestBuffer(bufferId, buf, streamId);
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07003734}
3735
3736// Find and pop a buffer_handle_t based on bufferId
3737status_t Camera3Device::HalInterface::popInflightRequestBuffer(
Yin-Chia Yeh84be5782019-03-01 11:47:02 -08003738 uint64_t bufferId,
3739 /*out*/ buffer_handle_t** buffer,
3740 /*optional out*/ int32_t* streamId) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003741 return mBufferRecords.popInflightRequestBuffer(bufferId, buffer, streamId);
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07003742}
3743
Yin-Chia Yeh77327052017-01-09 18:23:07 -08003744std::pair<bool, uint64_t> Camera3Device::HalInterface::getBufferId(
3745 const buffer_handle_t& buf, int streamId) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003746 return mBufferRecords.getBufferId(buf, streamId);
Yin-Chia Yeh77327052017-01-09 18:23:07 -08003747}
3748
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003749void Camera3Device::HalInterface::onBufferFreed(
3750 int streamId, const native_handle_t* handle) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003751 uint32_t bufferId = mBufferRecords.removeOneBufferCache(streamId, handle);
3752 std::lock_guard<std::mutex> lock(mFreedBuffersLock);
3753 if (bufferId != BUFFER_ID_NO_BUFFER) {
3754 mFreedBuffers.push_back(std::make_pair(streamId, bufferId));
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003755 }
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003756}
3757
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07003758void Camera3Device::HalInterface::onStreamReConfigured(int streamId) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003759 std::vector<uint64_t> bufIds = mBufferRecords.clearBufferCaches(streamId);
3760 std::lock_guard<std::mutex> lock(mFreedBuffersLock);
3761 for (auto bufferId : bufIds) {
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07003762 mFreedBuffers.push_back(std::make_pair(streamId, bufferId));
3763 }
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07003764}
3765
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003766/**
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003767 * RequestThread inner class methods
3768 */
3769
3770Camera3Device::RequestThread::RequestThread(wp<Camera3Device> parent,
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07003771 sp<StatusTracker> statusTracker,
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07003772 sp<HalInterface> interface, const Vector<int32_t>& sessionParamKeys,
3773 bool useHalBufManager) :
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07003774 Thread(/*canCallJava*/false),
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003775 mParent(parent),
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07003776 mStatusTracker(statusTracker),
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003777 mInterface(interface),
Eino-Ville Talvala77c1a352016-06-13 12:32:43 -07003778 mListener(nullptr),
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07003779 mId(getId(parent)),
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003780 mReconfigured(false),
3781 mDoPause(false),
3782 mPaused(true),
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003783 mNotifyPipelineDrain(false),
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003784 mFrameNumber(0),
Jianing Weicb0652e2014-03-12 18:29:36 -07003785 mLatestRequestId(NAME_NOT_FOUND),
Yin-Chia Yehc00a25c2014-08-21 14:27:44 -07003786 mCurrentAfTriggerId(0),
3787 mCurrentPreCaptureTriggerId(0),
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08003788 mRotateAndCropOverride(ANDROID_SCALER_ROTATE_AND_CROP_NONE),
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003789 mRepeatingLastFrameNumber(
3790 hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES),
Shuzhen Wang686f6442017-06-20 16:16:04 -07003791 mPrepareVideoStream(false),
Emilian Peeva14b4dd2018-05-15 11:00:31 +01003792 mConstrainedMode(false),
Emilian Peevac3ce6c2017-12-12 15:27:02 +00003793 mRequestLatency(kRequestLatencyBinSize),
3794 mSessionParamKeys(sessionParamKeys),
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07003795 mLatestSessionParams(sessionParamKeys.size()),
3796 mUseHalBufManager(useHalBufManager) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07003797 mStatusId = statusTracker->addComponent();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003798}
3799
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003800Camera3Device::RequestThread::~RequestThread() {}
3801
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07003802void Camera3Device::RequestThread::setNotificationListener(
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07003803 wp<NotificationListener> listener) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003804 ATRACE_CALL();
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003805 Mutex::Autolock l(mRequestLock);
3806 mListener = listener;
3807}
3808
Emilian Peevac3ce6c2017-12-12 15:27:02 +00003809void Camera3Device::RequestThread::configurationComplete(bool isConstrainedHighSpeed,
3810 const CameraMetadata& sessionParams) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003811 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003812 Mutex::Autolock l(mRequestLock);
3813 mReconfigured = true;
Emilian Peevac3ce6c2017-12-12 15:27:02 +00003814 mLatestSessionParams = sessionParams;
Chien-Yu Chenc66969b2016-05-19 16:37:51 -07003815 // Prepare video stream for high speed recording.
3816 mPrepareVideoStream = isConstrainedHighSpeed;
Emilian Peeva14b4dd2018-05-15 11:00:31 +01003817 mConstrainedMode = isConstrainedHighSpeed;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003818}
3819
Jianing Wei90e59c92014-03-12 18:29:36 -07003820status_t Camera3Device::RequestThread::queueRequestList(
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003821 List<sp<CaptureRequest> > &requests,
3822 /*out*/
3823 int64_t *lastFrameNumber) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003824 ATRACE_CALL();
Jianing Wei90e59c92014-03-12 18:29:36 -07003825 Mutex::Autolock l(mRequestLock);
3826 for (List<sp<CaptureRequest> >::iterator it = requests.begin(); it != requests.end();
3827 ++it) {
3828 mRequestQueue.push_back(*it);
3829 }
3830
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003831 if (lastFrameNumber != NULL) {
3832 *lastFrameNumber = mFrameNumber + mRequestQueue.size() - 1;
3833 ALOGV("%s: requestId %d, mFrameNumber %" PRId32 ", lastFrameNumber %" PRId64 ".",
3834 __FUNCTION__, (*(requests.begin()))->mResultExtras.requestId, mFrameNumber,
3835 *lastFrameNumber);
3836 }
Jianing Weicb0652e2014-03-12 18:29:36 -07003837
Jianing Wei90e59c92014-03-12 18:29:36 -07003838 unpauseForNewRequests();
3839
3840 return OK;
3841}
3842
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003843
3844status_t Camera3Device::RequestThread::queueTrigger(
3845 RequestTrigger trigger[],
3846 size_t count) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003847 ATRACE_CALL();
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003848 Mutex::Autolock l(mTriggerMutex);
3849 status_t ret;
3850
3851 for (size_t i = 0; i < count; ++i) {
3852 ret = queueTriggerLocked(trigger[i]);
3853
3854 if (ret != OK) {
3855 return ret;
3856 }
3857 }
3858
3859 return OK;
3860}
3861
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003862const String8& Camera3Device::RequestThread::getId(const wp<Camera3Device> &device) {
3863 static String8 deadId("<DeadDevice>");
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07003864 sp<Camera3Device> d = device.promote();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003865 if (d != nullptr) return d->mId;
3866 return deadId;
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07003867}
3868
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003869status_t Camera3Device::RequestThread::queueTriggerLocked(
3870 RequestTrigger trigger) {
3871
3872 uint32_t tag = trigger.metadataTag;
3873 ssize_t index = mTriggerMap.indexOfKey(tag);
3874
3875 switch (trigger.getTagType()) {
3876 case TYPE_BYTE:
3877 // fall-through
3878 case TYPE_INT32:
3879 break;
3880 default:
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07003881 ALOGE("%s: Type not supported: 0x%x", __FUNCTION__,
3882 trigger.getTagType());
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003883 return INVALID_OPERATION;
3884 }
3885
3886 /**
3887 * Collect only the latest trigger, since we only have 1 field
3888 * in the request settings per trigger tag, and can't send more than 1
3889 * trigger per request.
3890 */
3891 if (index != NAME_NOT_FOUND) {
3892 mTriggerMap.editValueAt(index) = trigger;
3893 } else {
3894 mTriggerMap.add(tag, trigger);
3895 }
3896
3897 return OK;
3898}
3899
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003900status_t Camera3Device::RequestThread::setRepeatingRequests(
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003901 const RequestList &requests,
3902 /*out*/
3903 int64_t *lastFrameNumber) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003904 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003905 Mutex::Autolock l(mRequestLock);
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003906 if (lastFrameNumber != NULL) {
3907 *lastFrameNumber = mRepeatingLastFrameNumber;
3908 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003909 mRepeatingRequests.clear();
3910 mRepeatingRequests.insert(mRepeatingRequests.begin(),
3911 requests.begin(), requests.end());
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07003912
3913 unpauseForNewRequests();
3914
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003915 mRepeatingLastFrameNumber = hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003916 return OK;
3917}
3918
Chih-Hung Hsieh8b0b9712016-08-09 14:25:53 -07003919bool Camera3Device::RequestThread::isRepeatingRequestLocked(const sp<CaptureRequest>& requestIn) {
Yin-Chia Yeh8684b7f2014-06-13 14:53:05 -07003920 if (mRepeatingRequests.empty()) {
3921 return false;
3922 }
3923 int32_t requestId = requestIn->mResultExtras.requestId;
3924 const RequestList &repeatRequests = mRepeatingRequests;
3925 // All repeating requests are guaranteed to have same id so only check first quest
3926 const sp<CaptureRequest> firstRequest = *repeatRequests.begin();
3927 return (firstRequest->mResultExtras.requestId == requestId);
3928}
3929
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003930status_t Camera3Device::RequestThread::clearRepeatingRequests(/*out*/int64_t *lastFrameNumber) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003931 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003932 Mutex::Autolock l(mRequestLock);
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07003933 return clearRepeatingRequestsLocked(lastFrameNumber);
3934
3935}
3936
3937status_t Camera3Device::RequestThread::clearRepeatingRequestsLocked(/*out*/int64_t *lastFrameNumber) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003938 mRepeatingRequests.clear();
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003939 if (lastFrameNumber != NULL) {
3940 *lastFrameNumber = mRepeatingLastFrameNumber;
3941 }
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003942 mRepeatingLastFrameNumber = hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003943 return OK;
3944}
3945
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003946status_t Camera3Device::RequestThread::clear(
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003947 /*out*/int64_t *lastFrameNumber) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003948 ATRACE_CALL();
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07003949 Mutex::Autolock l(mRequestLock);
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003950 ALOGV("RequestThread::%s:", __FUNCTION__);
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003951
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07003952 mRepeatingRequests.clear();
Yin-Chia Yeh8684b7f2014-06-13 14:53:05 -07003953
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003954 // Send errors for all requests pending in the request queue, including
3955 // pending repeating requests
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07003956 sp<NotificationListener> listener = mListener.promote();
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003957 if (listener != NULL) {
3958 for (RequestList::iterator it = mRequestQueue.begin();
3959 it != mRequestQueue.end(); ++it) {
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07003960 // Abort the input buffers for reprocess requests.
3961 if ((*it)->mInputStream != NULL) {
3962 camera3_stream_buffer_t inputBuffer;
Eino-Ville Talvalaba435252017-06-21 16:07:25 -07003963 status_t res = (*it)->mInputStream->getInputBuffer(&inputBuffer,
3964 /*respectHalLimit*/ false);
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07003965 if (res != OK) {
3966 ALOGW("%s: %d: couldn't get input buffer while clearing the request "
3967 "list: %s (%d)", __FUNCTION__, __LINE__, strerror(-res), res);
3968 } else {
Shuzhen Wang0cf01cb2019-09-05 13:33:06 -07003969 inputBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07003970 res = (*it)->mInputStream->returnInputBuffer(inputBuffer);
3971 if (res != OK) {
3972 ALOGE("%s: %d: couldn't return input buffer while clearing the request "
3973 "list: %s (%d)", __FUNCTION__, __LINE__, strerror(-res), res);
3974 }
3975 }
3976 }
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003977 // Set the frame number this request would have had, if it
3978 // had been submitted; this frame number will not be reused.
3979 // The requestId and burstId fields were set when the request was
3980 // submitted originally (in convertMetadataListToRequestListLocked)
3981 (*it)->mResultExtras.frameNumber = mFrameNumber++;
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003982 listener->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003983 (*it)->mResultExtras);
Yin-Chia Yeh8684b7f2014-06-13 14:53:05 -07003984 }
3985 }
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07003986 mRequestQueue.clear();
Jinguang Dongb26e7a02016-11-14 16:04:02 +08003987
3988 Mutex::Autolock al(mTriggerMutex);
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07003989 mTriggerMap.clear();
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003990 if (lastFrameNumber != NULL) {
3991 *lastFrameNumber = mRepeatingLastFrameNumber;
3992 }
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003993 mRepeatingLastFrameNumber = hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES;
Emilian Peev8dae54c2019-12-02 15:17:17 -08003994 mRequestSignal.signal();
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07003995 return OK;
3996}
3997
Chien-Yu Chen85a64552015-08-28 15:46:12 -07003998status_t Camera3Device::RequestThread::flush() {
3999 ATRACE_CALL();
4000 Mutex::Autolock l(mFlushLock);
4001
Emilian Peev08dd2452017-04-06 16:55:14 +01004002 return mInterface->flush();
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004003}
4004
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004005void Camera3Device::RequestThread::setPaused(bool paused) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004006 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004007 Mutex::Autolock l(mPauseLock);
4008 mDoPause = paused;
4009 mDoPauseSignal.signal();
4010}
4011
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004012status_t Camera3Device::RequestThread::waitUntilRequestProcessed(
4013 int32_t requestId, nsecs_t timeout) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004014 ATRACE_CALL();
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004015 Mutex::Autolock l(mLatestRequestMutex);
4016 status_t res;
4017 while (mLatestRequestId != requestId) {
4018 nsecs_t startTime = systemTime();
4019
4020 res = mLatestRequestSignal.waitRelative(mLatestRequestMutex, timeout);
4021 if (res != OK) return res;
4022
4023 timeout -= (systemTime() - startTime);
4024 }
4025
4026 return OK;
4027}
4028
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004029void Camera3Device::RequestThread::requestExit() {
4030 // Call parent to set up shutdown
4031 Thread::requestExit();
4032 // The exit from any possible waits
4033 mDoPauseSignal.signal();
4034 mRequestSignal.signal();
Shuzhen Wang686f6442017-06-20 16:16:04 -07004035
4036 mRequestLatency.log("ProcessCaptureRequest latency histogram");
4037 mRequestLatency.reset();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004038}
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004039
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07004040void Camera3Device::RequestThread::checkAndStopRepeatingRequest() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004041 ATRACE_CALL();
Yin-Chia Yeh473fad92016-05-23 15:54:41 -07004042 bool surfaceAbandoned = false;
4043 int64_t lastFrameNumber = 0;
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07004044 sp<NotificationListener> listener;
Yin-Chia Yeh473fad92016-05-23 15:54:41 -07004045 {
4046 Mutex::Autolock l(mRequestLock);
4047 // Check all streams needed by repeating requests are still valid. Otherwise, stop
4048 // repeating requests.
4049 for (const auto& request : mRepeatingRequests) {
4050 for (const auto& s : request->mOutputStreams) {
4051 if (s->isAbandoned()) {
4052 surfaceAbandoned = true;
4053 clearRepeatingRequestsLocked(&lastFrameNumber);
4054 break;
4055 }
4056 }
4057 if (surfaceAbandoned) {
4058 break;
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07004059 }
4060 }
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07004061 listener = mListener.promote();
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07004062 }
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07004063
4064 if (listener != NULL && surfaceAbandoned) {
4065 listener->notifyRepeatingRequestError(lastFrameNumber);
Yin-Chia Yeh473fad92016-05-23 15:54:41 -07004066 }
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07004067}
4068
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004069bool Camera3Device::RequestThread::sendRequestsBatch() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004070 ATRACE_CALL();
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004071 status_t res;
4072 size_t batchSize = mNextRequests.size();
4073 std::vector<camera3_capture_request_t*> requests(batchSize);
4074 uint32_t numRequestProcessed = 0;
4075 for (size_t i = 0; i < batchSize; i++) {
4076 requests[i] = &mNextRequests.editItemAt(i).halRequest;
Yin-Chia Yeh885691c2018-05-01 15:54:24 -07004077 ATRACE_ASYNC_BEGIN("frame capture", mNextRequests[i].halRequest.frame_number);
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004078 }
4079
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004080 res = mInterface->processBatchCaptureRequests(requests, &numRequestProcessed);
4081
4082 bool triggerRemoveFailed = false;
4083 NextRequest& triggerFailedRequest = mNextRequests.editItemAt(0);
4084 for (size_t i = 0; i < numRequestProcessed; i++) {
4085 NextRequest& nextRequest = mNextRequests.editItemAt(i);
4086 nextRequest.submitted = true;
4087
Shuzhen Wangc2cba122018-05-17 18:10:24 -07004088 updateNextRequest(nextRequest);
Emilian Peevaebbe412018-01-15 13:53:24 +00004089
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004090 if (!triggerRemoveFailed) {
4091 // Remove any previously queued triggers (after unlock)
4092 status_t removeTriggerRes = removeTriggers(mPrevRequest);
4093 if (removeTriggerRes != OK) {
4094 triggerRemoveFailed = true;
4095 triggerFailedRequest = nextRequest;
4096 }
4097 }
4098 }
4099
4100 if (triggerRemoveFailed) {
4101 SET_ERR("RequestThread: Unable to remove triggers "
4102 "(capture request %d, HAL device: %s (%d)",
4103 triggerFailedRequest.halRequest.frame_number, strerror(-res), res);
4104 cleanUpFailedRequests(/*sendRequestError*/ false);
4105 return false;
4106 }
4107
4108 if (res != OK) {
4109 // Should only get a failure here for malformed requests or device-level
4110 // errors, so consider all errors fatal. Bad metadata failures should
4111 // come through notify.
4112 SET_ERR("RequestThread: Unable to submit capture request %d to HAL device: %s (%d)",
4113 mNextRequests[numRequestProcessed].halRequest.frame_number,
4114 strerror(-res), res);
4115 cleanUpFailedRequests(/*sendRequestError*/ false);
4116 return false;
4117 }
4118 return true;
4119}
4120
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07004121nsecs_t Camera3Device::RequestThread::calculateMaxExpectedDuration(const camera_metadata_t *request) {
4122 nsecs_t maxExpectedDuration = kDefaultExpectedDuration;
4123 camera_metadata_ro_entry_t e = camera_metadata_ro_entry_t();
4124 find_camera_metadata_ro_entry(request,
4125 ANDROID_CONTROL_AE_MODE,
4126 &e);
4127 if (e.count == 0) return maxExpectedDuration;
4128
4129 switch (e.data.u8[0]) {
4130 case ANDROID_CONTROL_AE_MODE_OFF:
4131 find_camera_metadata_ro_entry(request,
4132 ANDROID_SENSOR_EXPOSURE_TIME,
4133 &e);
4134 if (e.count > 0) {
4135 maxExpectedDuration = e.data.i64[0];
4136 }
4137 find_camera_metadata_ro_entry(request,
4138 ANDROID_SENSOR_FRAME_DURATION,
4139 &e);
4140 if (e.count > 0) {
4141 maxExpectedDuration = std::max(e.data.i64[0], maxExpectedDuration);
4142 }
4143 break;
4144 default:
4145 find_camera_metadata_ro_entry(request,
4146 ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
4147 &e);
4148 if (e.count > 1) {
4149 maxExpectedDuration = 1e9 / e.data.u8[0];
4150 }
4151 break;
4152 }
4153
4154 return maxExpectedDuration;
4155}
4156
Emilian Peeva14b4dd2018-05-15 11:00:31 +01004157bool Camera3Device::RequestThread::skipHFRTargetFPSUpdate(int32_t tag,
4158 const camera_metadata_ro_entry_t& newEntry, const camera_metadata_entry_t& currentEntry) {
4159 if (mConstrainedMode && (ANDROID_CONTROL_AE_TARGET_FPS_RANGE == tag) &&
4160 (newEntry.count == currentEntry.count) && (currentEntry.count == 2) &&
4161 (currentEntry.data.i32[1] == newEntry.data.i32[1])) {
4162 return true;
4163 }
4164
4165 return false;
4166}
4167
Shuzhen Wangc2cba122018-05-17 18:10:24 -07004168void Camera3Device::RequestThread::updateNextRequest(NextRequest& nextRequest) {
4169 // Update the latest request sent to HAL
4170 if (nextRequest.halRequest.settings != NULL) { // Don't update if they were unchanged
4171 Mutex::Autolock al(mLatestRequestMutex);
4172
4173 camera_metadata_t* cloned = clone_camera_metadata(nextRequest.halRequest.settings);
4174 mLatestRequest.acquire(cloned);
4175
4176 mLatestPhysicalRequest.clear();
4177 for (uint32_t i = 0; i < nextRequest.halRequest.num_physcam_settings; i++) {
4178 cloned = clone_camera_metadata(nextRequest.halRequest.physcam_settings[i]);
4179 mLatestPhysicalRequest.emplace(nextRequest.halRequest.physcam_id[i],
4180 CameraMetadata(cloned));
4181 }
4182
4183 sp<Camera3Device> parent = mParent.promote();
4184 if (parent != NULL) {
4185 parent->monitorMetadata(TagMonitor::REQUEST,
4186 nextRequest.halRequest.frame_number,
4187 0, mLatestRequest, mLatestPhysicalRequest);
4188 }
4189 }
4190
4191 if (nextRequest.halRequest.settings != NULL) {
4192 nextRequest.captureRequest->mSettingsList.begin()->metadata.unlock(
4193 nextRequest.halRequest.settings);
4194 }
4195
4196 cleanupPhysicalSettings(nextRequest.captureRequest, &nextRequest.halRequest);
4197}
4198
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004199bool Camera3Device::RequestThread::updateSessionParameters(const CameraMetadata& settings) {
4200 ATRACE_CALL();
4201 bool updatesDetected = false;
4202
Emilian Peev4ec17882019-01-24 17:16:58 -08004203 CameraMetadata updatedParams(mLatestSessionParams);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004204 for (auto tag : mSessionParamKeys) {
4205 camera_metadata_ro_entry entry = settings.find(tag);
Emilian Peev4ec17882019-01-24 17:16:58 -08004206 camera_metadata_entry lastEntry = updatedParams.find(tag);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004207
4208 if (entry.count > 0) {
4209 bool isDifferent = false;
4210 if (lastEntry.count > 0) {
4211 // Have a last value, compare to see if changed
4212 if (lastEntry.type == entry.type &&
4213 lastEntry.count == entry.count) {
4214 // Same type and count, compare values
4215 size_t bytesPerValue = camera_metadata_type_size[lastEntry.type];
4216 size_t entryBytes = bytesPerValue * lastEntry.count;
4217 int cmp = memcmp(entry.data.u8, lastEntry.data.u8, entryBytes);
4218 if (cmp != 0) {
4219 isDifferent = true;
4220 }
4221 } else {
4222 // Count or type has changed
4223 isDifferent = true;
4224 }
4225 } else {
4226 // No last entry, so always consider to be different
4227 isDifferent = true;
4228 }
4229
4230 if (isDifferent) {
4231 ALOGV("%s: Session parameter tag id %d changed", __FUNCTION__, tag);
Emilian Peeva14b4dd2018-05-15 11:00:31 +01004232 if (!skipHFRTargetFPSUpdate(tag, entry, lastEntry)) {
4233 updatesDetected = true;
4234 }
Emilian Peev4ec17882019-01-24 17:16:58 -08004235 updatedParams.update(entry);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004236 }
4237 } else if (lastEntry.count > 0) {
4238 // Value has been removed
4239 ALOGV("%s: Session parameter tag id %d removed", __FUNCTION__, tag);
Emilian Peev4ec17882019-01-24 17:16:58 -08004240 updatedParams.erase(tag);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004241 updatesDetected = true;
4242 }
4243 }
4244
Emilian Peev4ec17882019-01-24 17:16:58 -08004245 bool reconfigureRequired;
4246 if (updatesDetected) {
4247 reconfigureRequired = mInterface->isReconfigurationRequired(mLatestSessionParams,
4248 updatedParams);
4249 mLatestSessionParams = updatedParams;
4250 } else {
4251 reconfigureRequired = false;
4252 }
4253
4254 return reconfigureRequired;
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004255}
4256
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004257bool Camera3Device::RequestThread::threadLoop() {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004258 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004259 status_t res;
Jayant Chowdhary37eca242019-11-18 08:55:56 -08004260 // Any function called from threadLoop() must not hold mInterfaceLock since
4261 // it could lead to deadlocks (disconnect() -> hold mInterfaceMutex -> wait for request thread
4262 // to finish -> request thread waits on mInterfaceMutex) http://b/143513518
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004263
4264 // Handle paused state.
4265 if (waitIfPaused()) {
4266 return true;
4267 }
4268
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004269 // Wait for the next batch of requests.
4270 waitForNextRequestBatch();
4271 if (mNextRequests.size() == 0) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004272 return true;
4273 }
4274
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004275 // Get the latest request ID, if any
4276 int latestRequestId;
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004277 camera_metadata_entry_t requestIdEntry = mNextRequests[mNextRequests.size() - 1].
Emilian Peevaebbe412018-01-15 13:53:24 +00004278 captureRequest->mSettingsList.begin()->metadata.find(ANDROID_REQUEST_ID);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004279 if (requestIdEntry.count > 0) {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004280 latestRequestId = requestIdEntry.data.i32[0];
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004281 } else {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004282 ALOGW("%s: Did not have android.request.id set in the request.", __FUNCTION__);
4283 latestRequestId = NAME_NOT_FOUND;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004284 }
4285
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004286 // 'mNextRequests' will at this point contain either a set of HFR batched requests
4287 // or a single request from streaming or burst. In either case the first element
4288 // should contain the latest camera settings that we need to check for any session
4289 // parameter updates.
Emilian Peevaebbe412018-01-15 13:53:24 +00004290 if (updateSessionParameters(mNextRequests[0].captureRequest->mSettingsList.begin()->metadata)) {
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004291 res = OK;
4292
4293 //Input stream buffers are already acquired at this point so an input stream
4294 //will not be able to move to idle state unless we force it.
4295 if (mNextRequests[0].captureRequest->mInputStream != nullptr) {
4296 res = mNextRequests[0].captureRequest->mInputStream->forceToIdle();
4297 if (res != OK) {
4298 ALOGE("%s: Failed to force idle input stream: %d", __FUNCTION__, res);
4299 cleanUpFailedRequests(/*sendRequestError*/ false);
4300 return false;
4301 }
4302 }
4303
4304 if (res == OK) {
Emilian Peev3bead5f2020-05-28 17:29:08 -07004305 sp<Camera3Device> parent = mParent.promote();
4306 if (parent != nullptr) {
4307 mReconfigured |= parent->reconfigureCamera(mLatestSessionParams, mStatusId);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004308 }
Emilian Peev3bead5f2020-05-28 17:29:08 -07004309 setPaused(false);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004310
4311 if (mNextRequests[0].captureRequest->mInputStream != nullptr) {
4312 mNextRequests[0].captureRequest->mInputStream->restoreConfiguredState();
4313 if (res != OK) {
4314 ALOGE("%s: Failed to restore configured input stream: %d", __FUNCTION__, res);
4315 cleanUpFailedRequests(/*sendRequestError*/ false);
4316 return false;
4317 }
4318 }
4319 }
4320 }
4321
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004322 // Prepare a batch of HAL requests and output buffers.
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004323 res = prepareHalRequests();
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004324 if (res == TIMED_OUT) {
4325 // Not a fatal error if getting output buffers time out.
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004326 cleanUpFailedRequests(/*sendRequestError*/ true);
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07004327 // Check if any stream is abandoned.
4328 checkAndStopRepeatingRequest();
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004329 return true;
4330 } else if (res != OK) {
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004331 cleanUpFailedRequests(/*sendRequestError*/ false);
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07004332 return false;
4333 }
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004334
Zhijun Hecc27e112013-10-03 16:12:43 -07004335 // Inform waitUntilRequestProcessed thread of a new request ID
4336 {
4337 Mutex::Autolock al(mLatestRequestMutex);
4338
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004339 mLatestRequestId = latestRequestId;
Zhijun Hecc27e112013-10-03 16:12:43 -07004340 mLatestRequestSignal.signal();
4341 }
4342
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004343 // Submit a batch of requests to HAL.
4344 // Use flush lock only when submitting multilple requests in a batch.
4345 // TODO: The problem with flush lock is flush() will be blocked by process_capture_request()
4346 // which may take a long time to finish so synchronizing flush() and
4347 // process_capture_request() defeats the purpose of cancelling requests ASAP with flush().
4348 // For now, only synchronize for high speed recording and we should figure something out for
4349 // removing the synchronization.
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004350 bool useFlushLock = mNextRequests.size() > 1;
Eino-Ville Talvala17a61ad2013-06-03 16:53:32 -07004351
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004352 if (useFlushLock) {
4353 mFlushLock.lock();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004354 }
4355
Zhijun Hef0645c12016-08-02 00:58:11 -07004356 ALOGVV("%s: %d: submitting %zu requests in a batch.", __FUNCTION__, __LINE__,
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004357 mNextRequests.size());
Igor Murashkin1e479c02013-09-06 16:55:14 -07004358
Yin-Chia Yehcd333fe2019-02-08 13:45:41 -08004359 sp<Camera3Device> parent = mParent.promote();
4360 if (parent != nullptr) {
4361 parent->mRequestBufferSM.onSubmittingRequest();
4362 }
4363
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004364 bool submitRequestSuccess = false;
Shuzhen Wang686f6442017-06-20 16:16:04 -07004365 nsecs_t tRequestStart = systemTime(SYSTEM_TIME_MONOTONIC);
Yin-Chia Yeh11648852019-05-16 10:42:54 -07004366 submitRequestSuccess = sendRequestsBatch();
4367
Shuzhen Wang686f6442017-06-20 16:16:04 -07004368 nsecs_t tRequestEnd = systemTime(SYSTEM_TIME_MONOTONIC);
4369 mRequestLatency.add(tRequestStart, tRequestEnd);
Igor Murashkin1e479c02013-09-06 16:55:14 -07004370
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004371 if (useFlushLock) {
4372 mFlushLock.unlock();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004373 }
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004374
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004375 // Unset as current request
4376 {
4377 Mutex::Autolock l(mRequestLock);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004378 mNextRequests.clear();
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004379 }
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004380 mRequestSubmittedSignal.signal();
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004381
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004382 return submitRequestSuccess;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004383}
4384
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004385status_t Camera3Device::RequestThread::prepareHalRequests() {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004386 ATRACE_CALL();
4387
Yin-Chia Yehd07b11e2018-06-01 12:50:02 -07004388 bool batchedRequest = mNextRequests[0].captureRequest->mBatchSize > 1;
Shuzhen Wang4a472662017-02-26 23:29:04 -08004389 for (size_t i = 0; i < mNextRequests.size(); i++) {
4390 auto& nextRequest = mNextRequests.editItemAt(i);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004391 sp<CaptureRequest> captureRequest = nextRequest.captureRequest;
4392 camera3_capture_request_t* halRequest = &nextRequest.halRequest;
4393 Vector<camera3_stream_buffer_t>* outputBuffers = &nextRequest.outputBuffers;
4394
4395 // Prepare a request to HAL
4396 halRequest->frame_number = captureRequest->mResultExtras.frameNumber;
4397
4398 // Insert any queued triggers (before metadata is locked)
4399 status_t res = insertTriggers(captureRequest);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004400 if (res < 0) {
4401 SET_ERR("RequestThread: Unable to insert triggers "
4402 "(capture request %d, HAL device: %s (%d)",
4403 halRequest->frame_number, strerror(-res), res);
4404 return INVALID_OPERATION;
4405 }
Eino-Ville Talvala7b8a1fd2018-05-22 15:30:35 -07004406
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004407 int triggerCount = res;
4408 bool triggersMixedIn = (triggerCount > 0 || mPrevTriggers > 0);
4409 mPrevTriggers = triggerCount;
4410
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08004411 bool rotateAndCropChanged = overrideAutoRotateAndCrop(captureRequest);
4412
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004413 // If the request is the same as last, or we had triggers last time
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08004414 bool newRequest =
4415 (mPrevRequest != captureRequest || triggersMixedIn || rotateAndCropChanged) &&
Yin-Chia Yehd07b11e2018-06-01 12:50:02 -07004416 // Request settings are all the same within one batch, so only treat the first
4417 // request in a batch as new
Zhijun He54c36822018-07-18 09:33:39 -07004418 !(batchedRequest && i > 0);
Emilian Peev00420d22018-02-05 21:33:13 +00004419 if (newRequest) {
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08004420 std::set<std::string> cameraIdsWithZoom;
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004421 /**
4422 * HAL workaround:
4423 * Insert a dummy trigger ID if a trigger is set but no trigger ID is
4424 */
4425 res = addDummyTriggerIds(captureRequest);
4426 if (res != OK) {
4427 SET_ERR("RequestThread: Unable to insert dummy trigger IDs "
4428 "(capture request %d, HAL device: %s (%d)",
4429 halRequest->frame_number, strerror(-res), res);
4430 return INVALID_OPERATION;
4431 }
4432
Eino-Ville Talvala7b8a1fd2018-05-22 15:30:35 -07004433 {
4434 // Correct metadata regions for distortion correction if enabled
4435 sp<Camera3Device> parent = mParent.promote();
4436 if (parent != nullptr) {
Shuzhen Wang4f6fa9d2019-03-29 10:40:35 -07004437 List<PhysicalCameraSettings>::iterator it;
4438 for (it = captureRequest->mSettingsList.begin();
4439 it != captureRequest->mSettingsList.end(); it++) {
4440 if (parent->mDistortionMappers.find(it->cameraId) ==
4441 parent->mDistortionMappers.end()) {
4442 continue;
4443 }
Shuzhen Wangd1d051a2020-08-20 15:42:23 -07004444
4445 if (!captureRequest->mDistortionCorrectionUpdated) {
4446 res = parent->mDistortionMappers[it->cameraId].correctCaptureRequest(
4447 &(it->metadata));
4448 if (res != OK) {
4449 SET_ERR("RequestThread: Unable to correct capture requests "
4450 "for lens distortion for request %d: %s (%d)",
4451 halRequest->frame_number, strerror(-res), res);
4452 return INVALID_OPERATION;
4453 }
4454 captureRequest->mDistortionCorrectionUpdated = true;
Shuzhen Wang4f6fa9d2019-03-29 10:40:35 -07004455 }
Eino-Ville Talvala7b8a1fd2018-05-22 15:30:35 -07004456 }
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08004457
4458 for (it = captureRequest->mSettingsList.begin();
4459 it != captureRequest->mSettingsList.end(); it++) {
4460 if (parent->mZoomRatioMappers.find(it->cameraId) ==
4461 parent->mZoomRatioMappers.end()) {
4462 continue;
4463 }
4464
Shuzhen Wangd1d051a2020-08-20 15:42:23 -07004465 if (!captureRequest->mZoomRatioIs1x) {
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08004466 cameraIdsWithZoom.insert(it->cameraId);
4467 }
4468
Shuzhen Wangd1d051a2020-08-20 15:42:23 -07004469 if (!captureRequest->mZoomRatioUpdated) {
4470 res = parent->mZoomRatioMappers[it->cameraId].updateCaptureRequest(
4471 &(it->metadata));
4472 if (res != OK) {
4473 SET_ERR("RequestThread: Unable to correct capture requests "
4474 "for zoom ratio for request %d: %s (%d)",
4475 halRequest->frame_number, strerror(-res), res);
4476 return INVALID_OPERATION;
4477 }
4478 captureRequest->mZoomRatioUpdated = true;
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08004479 }
4480 }
Shuzhen Wangd1d051a2020-08-20 15:42:23 -07004481 if (captureRequest->mRotateAndCropAuto &&
4482 !captureRequest->mRotationAndCropUpdated) {
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08004483 for (it = captureRequest->mSettingsList.begin();
4484 it != captureRequest->mSettingsList.end(); it++) {
4485 auto mapper = parent->mRotateAndCropMappers.find(it->cameraId);
4486 if (mapper != parent->mRotateAndCropMappers.end()) {
4487 res = mapper->second.updateCaptureRequest(&(it->metadata));
4488 if (res != OK) {
4489 SET_ERR("RequestThread: Unable to correct capture requests "
4490 "for rotate-and-crop for request %d: %s (%d)",
4491 halRequest->frame_number, strerror(-res), res);
4492 return INVALID_OPERATION;
4493 }
4494 }
4495 }
Shuzhen Wangd1d051a2020-08-20 15:42:23 -07004496 captureRequest->mRotationAndCropUpdated = true;
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08004497 }
Eino-Ville Talvala7b8a1fd2018-05-22 15:30:35 -07004498 }
4499 }
4500
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004501 /**
4502 * The request should be presorted so accesses in HAL
4503 * are O(logn). Sidenote, sorting a sorted metadata is nop.
4504 */
Emilian Peevaebbe412018-01-15 13:53:24 +00004505 captureRequest->mSettingsList.begin()->metadata.sort();
4506 halRequest->settings = captureRequest->mSettingsList.begin()->metadata.getAndLock();
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004507 mPrevRequest = captureRequest;
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08004508 mPrevCameraIdsWithZoom = cameraIdsWithZoom;
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004509 ALOGVV("%s: Request settings are NEW", __FUNCTION__);
4510
4511 IF_ALOGV() {
4512 camera_metadata_ro_entry_t e = camera_metadata_ro_entry_t();
4513 find_camera_metadata_ro_entry(
4514 halRequest->settings,
4515 ANDROID_CONTROL_AF_TRIGGER,
4516 &e
4517 );
4518 if (e.count > 0) {
4519 ALOGV("%s: Request (frame num %d) had AF trigger 0x%x",
4520 __FUNCTION__,
4521 halRequest->frame_number,
4522 e.data.u8[0]);
4523 }
4524 }
4525 } else {
4526 // leave request.settings NULL to indicate 'reuse latest given'
4527 ALOGVV("%s: Request settings are REUSED",
4528 __FUNCTION__);
4529 }
4530
Emilian Peevaebbe412018-01-15 13:53:24 +00004531 if (captureRequest->mSettingsList.size() > 1) {
4532 halRequest->num_physcam_settings = captureRequest->mSettingsList.size() - 1;
4533 halRequest->physcam_id = new const char* [halRequest->num_physcam_settings];
Emilian Peev00420d22018-02-05 21:33:13 +00004534 if (newRequest) {
4535 halRequest->physcam_settings =
4536 new const camera_metadata* [halRequest->num_physcam_settings];
4537 } else {
4538 halRequest->physcam_settings = nullptr;
4539 }
Emilian Peevaebbe412018-01-15 13:53:24 +00004540 auto it = ++captureRequest->mSettingsList.begin();
4541 size_t i = 0;
4542 for (; it != captureRequest->mSettingsList.end(); it++, i++) {
4543 halRequest->physcam_id[i] = it->cameraId.c_str();
Emilian Peev00420d22018-02-05 21:33:13 +00004544 if (newRequest) {
4545 it->metadata.sort();
4546 halRequest->physcam_settings[i] = it->metadata.getAndLock();
4547 }
Emilian Peevaebbe412018-01-15 13:53:24 +00004548 }
4549 }
4550
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004551 uint32_t totalNumBuffers = 0;
4552
4553 // Fill in buffers
4554 if (captureRequest->mInputStream != NULL) {
4555 halRequest->input_buffer = &captureRequest->mInputBuffer;
4556 totalNumBuffers += 1;
4557 } else {
4558 halRequest->input_buffer = NULL;
4559 }
4560
4561 outputBuffers->insertAt(camera3_stream_buffer_t(), 0,
4562 captureRequest->mOutputStreams.size());
4563 halRequest->output_buffers = outputBuffers->array();
Shuzhen Wang5c22c152017-12-31 17:12:25 -08004564 std::set<String8> requestedPhysicalCameras;
Yin-Chia Yehb3a80b12018-09-04 12:13:05 -07004565
4566 sp<Camera3Device> parent = mParent.promote();
4567 if (parent == NULL) {
4568 // Should not happen, and nowhere to send errors to, so just log it
4569 CLOGE("RequestThread: Parent is gone");
4570 return INVALID_OPERATION;
4571 }
4572 nsecs_t waitDuration = kBaseGetBufferWait + parent->getExpectedInFlightDuration();
4573
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004574 SurfaceMap uniqueSurfaceIdMap;
Shuzhen Wang4a472662017-02-26 23:29:04 -08004575 for (size_t j = 0; j < captureRequest->mOutputStreams.size(); j++) {
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004576 sp<Camera3OutputStreamInterface> outputStream =
4577 captureRequest->mOutputStreams.editItemAt(j);
4578 int streamId = outputStream->getId();
Chien-Yu Chenc66969b2016-05-19 16:37:51 -07004579
4580 // Prepare video buffers for high speed recording on the first video request.
4581 if (mPrepareVideoStream && outputStream->isVideoStream()) {
4582 // Only try to prepare video stream on the first video request.
4583 mPrepareVideoStream = false;
4584
Shuzhen Wangb3a0fb52018-09-13 17:24:08 -07004585 res = outputStream->startPrepare(Camera3StreamInterface::ALLOCATE_PIPELINE_MAX,
4586 false /*blockRequest*/);
Chien-Yu Chenc66969b2016-05-19 16:37:51 -07004587 while (res == NOT_ENOUGH_DATA) {
4588 res = outputStream->prepareNextBuffer();
4589 }
4590 if (res != OK) {
4591 ALOGW("%s: Preparing video buffers for high speed failed: %s (%d)",
4592 __FUNCTION__, strerror(-res), res);
4593 outputStream->cancelPrepare();
4594 }
4595 }
4596
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004597 std::vector<size_t> uniqueSurfaceIds;
4598 res = outputStream->getUniqueSurfaceIds(
4599 captureRequest->mOutputSurfaces[streamId],
4600 &uniqueSurfaceIds);
4601 // INVALID_OPERATION is normal output for streams not supporting surfaceIds
4602 if (res != OK && res != INVALID_OPERATION) {
4603 ALOGE("%s: failed to query stream %d unique surface IDs",
4604 __FUNCTION__, streamId);
4605 return res;
4606 }
4607 if (res == OK) {
4608 uniqueSurfaceIdMap.insert({streamId, std::move(uniqueSurfaceIds)});
4609 }
4610
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07004611 if (mUseHalBufManager) {
Yin-Chia Yeh110342b2018-11-19 11:47:46 -08004612 if (outputStream->isAbandoned()) {
Yin-Chia Yeha1b56c82019-03-27 15:50:39 -07004613 ALOGV("%s: stream %d is abandoned, skipping request", __FUNCTION__, streamId);
Yin-Chia Yeh110342b2018-11-19 11:47:46 -08004614 return TIMED_OUT;
4615 }
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07004616 // HAL will request buffer through requestStreamBuffer API
4617 camera3_stream_buffer_t& buffer = outputBuffers->editItemAt(j);
4618 buffer.stream = outputStream->asHalStream();
4619 buffer.buffer = nullptr;
4620 buffer.status = CAMERA3_BUFFER_STATUS_OK;
4621 buffer.acquire_fence = -1;
4622 buffer.release_fence = -1;
4623 } else {
4624 res = outputStream->getBuffer(&outputBuffers->editItemAt(j),
4625 waitDuration,
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004626 captureRequest->mOutputSurfaces[streamId]);
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07004627 if (res != OK) {
4628 // Can't get output buffer from gralloc queue - this could be due to
4629 // abandoned queue or other consumer misbehavior, so not a fatal
4630 // error
Yin-Chia Yeha1b56c82019-03-27 15:50:39 -07004631 ALOGV("RequestThread: Can't get output buffer, skipping request:"
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07004632 " %s (%d)", strerror(-res), res);
4633
4634 return TIMED_OUT;
4635 }
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004636 }
Shuzhen Wang68ac7ad2019-01-30 14:03:28 -08004637
4638 {
4639 sp<Camera3Device> parent = mParent.promote();
4640 if (parent != nullptr) {
4641 const String8& streamCameraId = outputStream->getPhysicalCameraId();
4642 for (const auto& settings : captureRequest->mSettingsList) {
4643 if ((streamCameraId.isEmpty() &&
4644 parent->getId() == settings.cameraId.c_str()) ||
4645 streamCameraId == settings.cameraId.c_str()) {
4646 outputStream->fireBufferRequestForFrameNumber(
4647 captureRequest->mResultExtras.frameNumber,
4648 settings.metadata);
4649 }
4650 }
4651 }
4652 }
Shuzhen Wang0129d522016-10-30 22:43:41 -07004653
Shuzhen Wang5c22c152017-12-31 17:12:25 -08004654 String8 physicalCameraId = outputStream->getPhysicalCameraId();
4655
4656 if (!physicalCameraId.isEmpty()) {
4657 // Physical stream isn't supported for input request.
4658 if (halRequest->input_buffer) {
4659 CLOGE("Physical stream is not supported for input request");
4660 return INVALID_OPERATION;
4661 }
4662 requestedPhysicalCameras.insert(physicalCameraId);
4663 }
4664 halRequest->num_output_buffers++;
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004665 }
4666 totalNumBuffers += halRequest->num_output_buffers;
4667
4668 // Log request in the in-flight queue
Shuzhen Wang4a472662017-02-26 23:29:04 -08004669 // If this request list is for constrained high speed recording (not
4670 // preview), and the current request is not the last one in the batch,
4671 // do not send callback to the app.
4672 bool hasCallback = true;
Yin-Chia Yehd07b11e2018-06-01 12:50:02 -07004673 if (batchedRequest && i != mNextRequests.size()-1) {
Shuzhen Wang4a472662017-02-26 23:29:04 -08004674 hasCallback = false;
4675 }
Emilian Peev9dd21f42018-08-03 13:39:29 +01004676 bool isStillCapture = false;
Shuzhen Wang26abaf42018-08-28 15:41:20 -07004677 bool isZslCapture = false;
Emilian Peev9dd21f42018-08-03 13:39:29 +01004678 if (!mNextRequests[0].captureRequest->mSettingsList.begin()->metadata.isEmpty()) {
4679 camera_metadata_ro_entry_t e = camera_metadata_ro_entry_t();
4680 find_camera_metadata_ro_entry(halRequest->settings, ANDROID_CONTROL_CAPTURE_INTENT, &e);
4681 if ((e.count > 0) && (e.data.u8[0] == ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE)) {
4682 isStillCapture = true;
4683 ATRACE_ASYNC_BEGIN("still capture", mNextRequests[i].halRequest.frame_number);
4684 }
Shuzhen Wang26abaf42018-08-28 15:41:20 -07004685
4686 find_camera_metadata_ro_entry(halRequest->settings, ANDROID_CONTROL_ENABLE_ZSL, &e);
4687 if ((e.count > 0) && (e.data.u8[0] == ANDROID_CONTROL_ENABLE_ZSL_TRUE)) {
4688 isZslCapture = true;
4689 }
Emilian Peev9dd21f42018-08-03 13:39:29 +01004690 }
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004691 res = parent->registerInFlight(halRequest->frame_number,
4692 totalNumBuffers, captureRequest->mResultExtras,
4693 /*hasInput*/halRequest->input_buffer != NULL,
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07004694 hasCallback,
Shuzhen Wang5c22c152017-12-31 17:12:25 -08004695 calculateMaxExpectedDuration(halRequest->settings),
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08004696 requestedPhysicalCameras, isStillCapture, isZslCapture,
4697 captureRequest->mRotateAndCropAuto, mPrevCameraIdsWithZoom,
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004698 (mUseHalBufManager) ? uniqueSurfaceIdMap :
4699 SurfaceMap{});
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004700 ALOGVV("%s: registered in flight requestId = %" PRId32 ", frameNumber = %" PRId64
4701 ", burstId = %" PRId32 ".",
4702 __FUNCTION__,
4703 captureRequest->mResultExtras.requestId, captureRequest->mResultExtras.frameNumber,
4704 captureRequest->mResultExtras.burstId);
4705 if (res != OK) {
4706 SET_ERR("RequestThread: Unable to register new in-flight request:"
4707 " %s (%d)", strerror(-res), res);
4708 return INVALID_OPERATION;
4709 }
4710 }
4711
4712 return OK;
4713}
4714
Igor Murashkin1e479c02013-09-06 16:55:14 -07004715CameraMetadata Camera3Device::RequestThread::getLatestRequest() const {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004716 ATRACE_CALL();
Igor Murashkin1e479c02013-09-06 16:55:14 -07004717 Mutex::Autolock al(mLatestRequestMutex);
4718
4719 ALOGV("RequestThread::%s", __FUNCTION__);
4720
4721 return mLatestRequest;
4722}
4723
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07004724bool Camera3Device::RequestThread::isStreamPending(
4725 sp<Camera3StreamInterface>& stream) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004726 ATRACE_CALL();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07004727 Mutex::Autolock l(mRequestLock);
4728
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004729 for (const auto& nextRequest : mNextRequests) {
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004730 if (!nextRequest.submitted) {
4731 for (const auto& s : nextRequest.captureRequest->mOutputStreams) {
4732 if (stream == s) return true;
4733 }
4734 if (stream == nextRequest.captureRequest->mInputStream) return true;
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004735 }
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004736 }
4737
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07004738 for (const auto& request : mRequestQueue) {
4739 for (const auto& s : request->mOutputStreams) {
4740 if (stream == s) return true;
4741 }
4742 if (stream == request->mInputStream) return true;
4743 }
4744
4745 for (const auto& request : mRepeatingRequests) {
4746 for (const auto& s : request->mOutputStreams) {
4747 if (stream == s) return true;
4748 }
4749 if (stream == request->mInputStream) return true;
4750 }
4751
4752 return false;
4753}
Jianing Weicb0652e2014-03-12 18:29:36 -07004754
Emilian Peev40ead602017-09-26 15:46:36 +01004755bool Camera3Device::RequestThread::isOutputSurfacePending(int streamId, size_t surfaceId) {
4756 ATRACE_CALL();
4757 Mutex::Autolock l(mRequestLock);
4758
4759 for (const auto& nextRequest : mNextRequests) {
4760 for (const auto& s : nextRequest.captureRequest->mOutputSurfaces) {
4761 if (s.first == streamId) {
4762 const auto &it = std::find(s.second.begin(), s.second.end(), surfaceId);
4763 if (it != s.second.end()) {
4764 return true;
4765 }
4766 }
4767 }
4768 }
4769
4770 for (const auto& request : mRequestQueue) {
4771 for (const auto& s : request->mOutputSurfaces) {
4772 if (s.first == streamId) {
4773 const auto &it = std::find(s.second.begin(), s.second.end(), surfaceId);
4774 if (it != s.second.end()) {
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004775 return true;
Emilian Peev40ead602017-09-26 15:46:36 +01004776 }
4777 }
4778 }
4779 }
4780
4781 for (const auto& request : mRepeatingRequests) {
4782 for (const auto& s : request->mOutputSurfaces) {
4783 if (s.first == streamId) {
4784 const auto &it = std::find(s.second.begin(), s.second.end(), surfaceId);
4785 if (it != s.second.end()) {
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004786 return true;
Emilian Peev40ead602017-09-26 15:46:36 +01004787 }
4788 }
4789 }
4790 }
4791
4792 return false;
4793}
4794
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07004795void Camera3Device::RequestThread::signalPipelineDrain(const std::vector<int>& streamIds) {
4796 if (!mUseHalBufManager) {
4797 ALOGE("%s called for camera device not supporting HAL buffer management", __FUNCTION__);
4798 return;
4799 }
4800
4801 Mutex::Autolock pl(mPauseLock);
4802 if (mPaused) {
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07004803 mInterface->signalPipelineDrain(streamIds);
4804 return;
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07004805 }
4806 // If request thread is still busy, wait until paused then notify HAL
4807 mNotifyPipelineDrain = true;
4808 mStreamIdsToBeDrained = streamIds;
4809}
4810
Yin-Chia Yehe52b8fa2020-07-28 00:17:58 -07004811void Camera3Device::RequestThread::resetPipelineDrain() {
4812 Mutex::Autolock pl(mPauseLock);
4813 mNotifyPipelineDrain = false;
4814 mStreamIdsToBeDrained.clear();
4815}
4816
Emilian Peevc0fe54c2020-03-11 14:05:07 -07004817void Camera3Device::RequestThread::clearPreviousRequest() {
4818 Mutex::Autolock l(mRequestLock);
4819 mPrevRequest.clear();
4820}
4821
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004822status_t Camera3Device::RequestThread::switchToOffline(
4823 const std::vector<int32_t>& streamsToKeep,
4824 /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004825 /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
4826 /*out*/camera3::BufferRecords* bufferRecords) {
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004827 Mutex::Autolock l(mRequestLock);
4828 clearRepeatingRequestsLocked(/*lastFrameNumber*/nullptr);
4829
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004830 // Wait until request thread is fully stopped
4831 // TBD: check if request thread is being paused by other APIs (shouldn't be)
4832
4833 // We could also check for mRepeatingRequests.empty(), but the API interface
4834 // is serialized by Camera3Device::mInterfaceLock so no one should be able to submit any
4835 // new requests during the call; hence skip that check.
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004836 bool queueEmpty = mNextRequests.empty() && mRequestQueue.empty();
4837 while (!queueEmpty) {
4838 status_t res = mRequestSubmittedSignal.waitRelative(mRequestLock, kRequestSubmitTimeout);
4839 if (res == TIMED_OUT) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004840 ALOGE("%s: request thread failed to submit one request within timeout!", __FUNCTION__);
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004841 return res;
4842 } else if (res != OK) {
4843 ALOGE("%s: request thread failed to submit a request: %s (%d)!",
4844 __FUNCTION__, strerror(-res), res);
4845 return res;
4846 }
4847 queueEmpty = mNextRequests.empty() && mRequestQueue.empty();
4848 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004849
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004850 return mInterface->switchToOffline(
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004851 streamsToKeep, offlineSessionInfo, offlineSession, bufferRecords);
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004852}
4853
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08004854status_t Camera3Device::RequestThread::setRotateAndCropAutoBehavior(
4855 camera_metadata_enum_android_scaler_rotate_and_crop_t rotateAndCropValue) {
4856 ATRACE_CALL();
4857 Mutex::Autolock l(mTriggerMutex);
4858 if (rotateAndCropValue == ANDROID_SCALER_ROTATE_AND_CROP_AUTO) {
4859 return BAD_VALUE;
4860 }
4861 mRotateAndCropOverride = rotateAndCropValue;
4862 return OK;
4863}
4864
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07004865nsecs_t Camera3Device::getExpectedInFlightDuration() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004866 ATRACE_CALL();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004867 std::lock_guard<std::mutex> l(mInFlightLock);
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07004868 return mExpectedInflightDuration > kMinInflightDuration ?
4869 mExpectedInflightDuration : kMinInflightDuration;
4870}
4871
Emilian Peevaebbe412018-01-15 13:53:24 +00004872void Camera3Device::RequestThread::cleanupPhysicalSettings(sp<CaptureRequest> request,
4873 camera3_capture_request_t *halRequest) {
4874 if ((request == nullptr) || (halRequest == nullptr)) {
4875 ALOGE("%s: Invalid request!", __FUNCTION__);
4876 return;
4877 }
4878
4879 if (halRequest->num_physcam_settings > 0) {
4880 if (halRequest->physcam_id != nullptr) {
4881 delete [] halRequest->physcam_id;
4882 halRequest->physcam_id = nullptr;
4883 }
4884 if (halRequest->physcam_settings != nullptr) {
4885 auto it = ++(request->mSettingsList.begin());
4886 size_t i = 0;
4887 for (; it != request->mSettingsList.end(); it++, i++) {
4888 it->metadata.unlock(halRequest->physcam_settings[i]);
4889 }
4890 delete [] halRequest->physcam_settings;
4891 halRequest->physcam_settings = nullptr;
4892 }
4893 }
4894}
4895
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004896void Camera3Device::RequestThread::cleanUpFailedRequests(bool sendRequestError) {
4897 if (mNextRequests.empty()) {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004898 return;
4899 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004900
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004901 for (auto& nextRequest : mNextRequests) {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004902 // Skip the ones that have been submitted successfully.
4903 if (nextRequest.submitted) {
4904 continue;
4905 }
4906
4907 sp<CaptureRequest> captureRequest = nextRequest.captureRequest;
4908 camera3_capture_request_t* halRequest = &nextRequest.halRequest;
4909 Vector<camera3_stream_buffer_t>* outputBuffers = &nextRequest.outputBuffers;
4910
4911 if (halRequest->settings != NULL) {
Emilian Peevaebbe412018-01-15 13:53:24 +00004912 captureRequest->mSettingsList.begin()->metadata.unlock(halRequest->settings);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004913 }
4914
Emilian Peevaebbe412018-01-15 13:53:24 +00004915 cleanupPhysicalSettings(captureRequest, halRequest);
4916
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004917 if (captureRequest->mInputStream != NULL) {
4918 captureRequest->mInputBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
4919 captureRequest->mInputStream->returnInputBuffer(captureRequest->mInputBuffer);
4920 }
4921
Yin-Chia Yeh21cb47b2019-01-18 15:08:17 -08004922 // No output buffer can be returned when using HAL buffer manager
4923 if (!mUseHalBufManager) {
4924 for (size_t i = 0; i < halRequest->num_output_buffers; i++) {
4925 //Buffers that failed processing could still have
4926 //valid acquire fence.
4927 int acquireFence = (*outputBuffers)[i].acquire_fence;
4928 if (0 <= acquireFence) {
4929 close(acquireFence);
4930 outputBuffers->editItemAt(i).acquire_fence = -1;
4931 }
4932 outputBuffers->editItemAt(i).status = CAMERA3_BUFFER_STATUS_ERROR;
4933 captureRequest->mOutputStreams.editItemAt(i)->returnBuffer((*outputBuffers)[i], 0,
4934 /*timestampIncreasing*/true, std::vector<size_t> (),
4935 captureRequest->mResultExtras.frameNumber);
Emilian Peevc58cf4c2017-05-11 17:23:41 +01004936 }
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004937 }
4938
4939 if (sendRequestError) {
4940 Mutex::Autolock l(mRequestLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07004941 sp<NotificationListener> listener = mListener.promote();
4942 if (listener != NULL) {
4943 listener->notifyError(
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08004944 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004945 captureRequest->mResultExtras);
4946 }
4947 }
Shuzhen Wangcadb3302016-11-04 14:17:56 -07004948
4949 // Remove yet-to-be submitted inflight request from inflightMap
4950 {
4951 sp<Camera3Device> parent = mParent.promote();
4952 if (parent != NULL) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004953 std::lock_guard<std::mutex> l(parent->mInFlightLock);
Shuzhen Wangcadb3302016-11-04 14:17:56 -07004954 ssize_t idx = parent->mInFlightMap.indexOfKey(captureRequest->mResultExtras.frameNumber);
4955 if (idx >= 0) {
4956 ALOGV("%s: Remove inflight request from queue: frameNumber %" PRId64,
4957 __FUNCTION__, captureRequest->mResultExtras.frameNumber);
4958 parent->removeInFlightMapEntryLocked(idx);
4959 }
4960 }
4961 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004962 }
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004963
4964 Mutex::Autolock l(mRequestLock);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004965 mNextRequests.clear();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004966}
4967
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004968void Camera3Device::RequestThread::waitForNextRequestBatch() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004969 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004970 // Optimized a bit for the simple steady-state case (single repeating
4971 // request), to avoid putting that request in the queue temporarily.
4972 Mutex::Autolock l(mRequestLock);
4973
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004974 assert(mNextRequests.empty());
4975
4976 NextRequest nextRequest;
4977 nextRequest.captureRequest = waitForNextRequestLocked();
4978 if (nextRequest.captureRequest == nullptr) {
4979 return;
4980 }
4981
4982 nextRequest.halRequest = camera3_capture_request_t();
4983 nextRequest.submitted = false;
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004984 mNextRequests.add(nextRequest);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004985
4986 // Wait for additional requests
4987 const size_t batchSize = nextRequest.captureRequest->mBatchSize;
4988
4989 for (size_t i = 1; i < batchSize; i++) {
4990 NextRequest additionalRequest;
4991 additionalRequest.captureRequest = waitForNextRequestLocked();
4992 if (additionalRequest.captureRequest == nullptr) {
4993 break;
4994 }
4995
4996 additionalRequest.halRequest = camera3_capture_request_t();
4997 additionalRequest.submitted = false;
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004998 mNextRequests.add(additionalRequest);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004999 }
5000
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07005001 if (mNextRequests.size() < batchSize) {
Eino-Ville Talvalad309fb92015-11-25 12:12:45 -08005002 ALOGE("RequestThread: only get %zu out of %zu requests. Skipping requests.",
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07005003 mNextRequests.size(), batchSize);
5004 cleanUpFailedRequests(/*sendRequestError*/true);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07005005 }
5006
5007 return;
5008}
5009
5010sp<Camera3Device::CaptureRequest>
5011 Camera3Device::RequestThread::waitForNextRequestLocked() {
5012 status_t res;
5013 sp<CaptureRequest> nextRequest;
5014
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005015 while (mRequestQueue.empty()) {
5016 if (!mRepeatingRequests.empty()) {
5017 // Always atomically enqueue all requests in a repeating request
5018 // list. Guarantees a complete in-sequence set of captures to
5019 // application.
5020 const RequestList &requests = mRepeatingRequests;
5021 RequestList::const_iterator firstRequest =
5022 requests.begin();
5023 nextRequest = *firstRequest;
5024 mRequestQueue.insert(mRequestQueue.end(),
5025 ++firstRequest,
5026 requests.end());
5027 // No need to wait any longer
Jianing Weicb0652e2014-03-12 18:29:36 -07005028
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07005029 mRepeatingLastFrameNumber = mFrameNumber + requests.size() - 1;
Jianing Weicb0652e2014-03-12 18:29:36 -07005030
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005031 break;
5032 }
5033
5034 res = mRequestSignal.waitRelative(mRequestLock, kRequestTimeout);
5035
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005036 if ((mRequestQueue.empty() && mRepeatingRequests.empty()) ||
5037 exitPending()) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005038 Mutex::Autolock pl(mPauseLock);
5039 if (mPaused == false) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005040 ALOGV("%s: RequestThread: Going idle", __FUNCTION__);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005041 mPaused = true;
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07005042 if (mNotifyPipelineDrain) {
5043 mInterface->signalPipelineDrain(mStreamIdsToBeDrained);
5044 mNotifyPipelineDrain = false;
5045 mStreamIdsToBeDrained.clear();
5046 }
Yin-Chia Yehc300a072019-02-13 14:56:57 -08005047 // Let the tracker know
5048 sp<StatusTracker> statusTracker = mStatusTracker.promote();
5049 if (statusTracker != 0) {
5050 statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);
5051 }
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005052 sp<Camera3Device> parent = mParent.promote();
5053 if (parent != nullptr) {
5054 parent->mRequestBufferSM.onRequestThreadPaused();
5055 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005056 }
5057 // Stop waiting for now and let thread management happen
5058 return NULL;
5059 }
5060 }
5061
5062 if (nextRequest == NULL) {
5063 // Don't have a repeating request already in hand, so queue
5064 // must have an entry now.
5065 RequestList::iterator firstRequest =
5066 mRequestQueue.begin();
5067 nextRequest = *firstRequest;
5068 mRequestQueue.erase(firstRequest);
Shuzhen Wang9d066012016-09-30 11:30:20 -07005069 if (mRequestQueue.empty() && !nextRequest->mRepeating) {
5070 sp<NotificationListener> listener = mListener.promote();
5071 if (listener != NULL) {
5072 listener->notifyRequestQueueEmpty();
5073 }
5074 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005075 }
5076
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07005077 // In case we've been unpaused by setPaused clearing mDoPause, need to
5078 // update internal pause state (capture/setRepeatingRequest unpause
5079 // directly).
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005080 Mutex::Autolock pl(mPauseLock);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005081 if (mPaused) {
5082 ALOGV("%s: RequestThread: Unpaused", __FUNCTION__);
5083 sp<StatusTracker> statusTracker = mStatusTracker.promote();
5084 if (statusTracker != 0) {
5085 statusTracker->markComponentActive(mStatusId);
5086 }
5087 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005088 mPaused = false;
5089
5090 // Check if we've reconfigured since last time, and reset the preview
5091 // request if so. Can't use 'NULL request == repeat' across configure calls.
5092 if (mReconfigured) {
5093 mPrevRequest.clear();
5094 mReconfigured = false;
5095 }
5096
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07005097 if (nextRequest != NULL) {
5098 nextRequest->mResultExtras.frameNumber = mFrameNumber++;
Yin-Chia Yehc00a25c2014-08-21 14:27:44 -07005099 nextRequest->mResultExtras.afTriggerId = mCurrentAfTriggerId;
5100 nextRequest->mResultExtras.precaptureTriggerId = mCurrentPreCaptureTriggerId;
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07005101
5102 // Since RequestThread::clear() removes buffers from the input stream,
5103 // get the right buffer here before unlocking mRequestLock
5104 if (nextRequest->mInputStream != NULL) {
5105 res = nextRequest->mInputStream->getInputBuffer(&nextRequest->mInputBuffer);
5106 if (res != OK) {
5107 // Can't get input buffer from gralloc queue - this could be due to
5108 // disconnected queue or other producer misbehavior, so not a fatal
5109 // error
5110 ALOGE("%s: Can't get input buffer, skipping request:"
5111 " %s (%d)", __FUNCTION__, strerror(-res), res);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005112
5113 sp<NotificationListener> listener = mListener.promote();
5114 if (listener != NULL) {
5115 listener->notifyError(
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08005116 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07005117 nextRequest->mResultExtras);
5118 }
5119 return NULL;
5120 }
5121 }
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07005122 }
Chien-Yu Chend196d612015-06-22 19:49:01 -07005123
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005124 return nextRequest;
5125}
5126
5127bool Camera3Device::RequestThread::waitIfPaused() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005128 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005129 status_t res;
5130 Mutex::Autolock l(mPauseLock);
5131 while (mDoPause) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005132 if (mPaused == false) {
5133 mPaused = true;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005134 ALOGV("%s: RequestThread: Paused", __FUNCTION__);
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07005135 if (mNotifyPipelineDrain) {
5136 mInterface->signalPipelineDrain(mStreamIdsToBeDrained);
5137 mNotifyPipelineDrain = false;
5138 mStreamIdsToBeDrained.clear();
5139 }
Yin-Chia Yehc300a072019-02-13 14:56:57 -08005140 // Let the tracker know
5141 sp<StatusTracker> statusTracker = mStatusTracker.promote();
5142 if (statusTracker != 0) {
5143 statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);
5144 }
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005145 sp<Camera3Device> parent = mParent.promote();
5146 if (parent != nullptr) {
5147 parent->mRequestBufferSM.onRequestThreadPaused();
5148 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005149 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005150
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005151 res = mDoPauseSignal.waitRelative(mPauseLock, kRequestTimeout);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005152 if (res == TIMED_OUT || exitPending()) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005153 return true;
5154 }
5155 }
5156 // We don't set mPaused to false here, because waitForNextRequest needs
5157 // to further manage the paused state in case of starvation.
5158 return false;
5159}
5160
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07005161void Camera3Device::RequestThread::unpauseForNewRequests() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005162 ATRACE_CALL();
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07005163 // With work to do, mark thread as unpaused.
5164 // If paused by request (setPaused), don't resume, to avoid
5165 // extra signaling/waiting overhead to waitUntilPaused
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005166 mRequestSignal.signal();
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07005167 Mutex::Autolock p(mPauseLock);
5168 if (!mDoPause) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005169 ALOGV("%s: RequestThread: Going active", __FUNCTION__);
5170 if (mPaused) {
5171 sp<StatusTracker> statusTracker = mStatusTracker.promote();
5172 if (statusTracker != 0) {
5173 statusTracker->markComponentActive(mStatusId);
5174 }
5175 }
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07005176 mPaused = false;
5177 }
5178}
5179
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07005180void Camera3Device::RequestThread::setErrorState(const char *fmt, ...) {
5181 sp<Camera3Device> parent = mParent.promote();
5182 if (parent != NULL) {
5183 va_list args;
5184 va_start(args, fmt);
5185
5186 parent->setErrorStateV(fmt, args);
5187
5188 va_end(args);
5189 }
5190}
5191
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005192status_t Camera3Device::RequestThread::insertTriggers(
5193 const sp<CaptureRequest> &request) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005194 ATRACE_CALL();
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005195 Mutex::Autolock al(mTriggerMutex);
5196
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07005197 sp<Camera3Device> parent = mParent.promote();
5198 if (parent == NULL) {
5199 CLOGE("RequestThread: Parent is gone");
5200 return DEAD_OBJECT;
5201 }
5202
Emilian Peevaebbe412018-01-15 13:53:24 +00005203 CameraMetadata &metadata = request->mSettingsList.begin()->metadata;
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005204 size_t count = mTriggerMap.size();
5205
5206 for (size_t i = 0; i < count; ++i) {
5207 RequestTrigger trigger = mTriggerMap.valueAt(i);
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005208 uint32_t tag = trigger.metadataTag;
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07005209
5210 if (tag == ANDROID_CONTROL_AF_TRIGGER_ID || tag == ANDROID_CONTROL_AE_PRECAPTURE_ID) {
5211 bool isAeTrigger = (trigger.metadataTag == ANDROID_CONTROL_AE_PRECAPTURE_ID);
5212 uint32_t triggerId = static_cast<uint32_t>(trigger.entryValue);
Yin-Chia Yehc00a25c2014-08-21 14:27:44 -07005213 if (isAeTrigger) {
5214 request->mResultExtras.precaptureTriggerId = triggerId;
5215 mCurrentPreCaptureTriggerId = triggerId;
5216 } else {
5217 request->mResultExtras.afTriggerId = triggerId;
5218 mCurrentAfTriggerId = triggerId;
5219 }
Emilian Peev7e25e5e2017-04-07 15:48:49 +01005220 continue;
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07005221 }
5222
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005223 camera_metadata_entry entry = metadata.find(tag);
5224
5225 if (entry.count > 0) {
5226 /**
5227 * Already has an entry for this trigger in the request.
5228 * Rewrite it with our requested trigger value.
5229 */
5230 RequestTrigger oldTrigger = trigger;
5231
5232 oldTrigger.entryValue = entry.data.u8[0];
5233
5234 mTriggerReplacedMap.add(tag, oldTrigger);
5235 } else {
5236 /**
5237 * More typical, no trigger entry, so we just add it
5238 */
5239 mTriggerRemovedMap.add(tag, trigger);
5240 }
5241
5242 status_t res;
5243
5244 switch (trigger.getTagType()) {
5245 case TYPE_BYTE: {
5246 uint8_t entryValue = static_cast<uint8_t>(trigger.entryValue);
5247 res = metadata.update(tag,
5248 &entryValue,
5249 /*count*/1);
5250 break;
5251 }
5252 case TYPE_INT32:
5253 res = metadata.update(tag,
5254 &trigger.entryValue,
5255 /*count*/1);
5256 break;
5257 default:
5258 ALOGE("%s: Type not supported: 0x%x",
5259 __FUNCTION__,
5260 trigger.getTagType());
5261 return INVALID_OPERATION;
5262 }
5263
5264 if (res != OK) {
5265 ALOGE("%s: Failed to update request metadata with trigger tag %s"
5266 ", value %d", __FUNCTION__, trigger.getTagName(),
5267 trigger.entryValue);
5268 return res;
5269 }
5270
5271 ALOGV("%s: Mixed in trigger %s, value %d", __FUNCTION__,
5272 trigger.getTagName(),
5273 trigger.entryValue);
5274 }
5275
5276 mTriggerMap.clear();
5277
5278 return count;
5279}
5280
5281status_t Camera3Device::RequestThread::removeTriggers(
5282 const sp<CaptureRequest> &request) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005283 ATRACE_CALL();
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005284 Mutex::Autolock al(mTriggerMutex);
5285
Emilian Peevaebbe412018-01-15 13:53:24 +00005286 CameraMetadata &metadata = request->mSettingsList.begin()->metadata;
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005287
5288 /**
5289 * Replace all old entries with their old values.
5290 */
5291 for (size_t i = 0; i < mTriggerReplacedMap.size(); ++i) {
5292 RequestTrigger trigger = mTriggerReplacedMap.valueAt(i);
5293
5294 status_t res;
5295
5296 uint32_t tag = trigger.metadataTag;
5297 switch (trigger.getTagType()) {
5298 case TYPE_BYTE: {
5299 uint8_t entryValue = static_cast<uint8_t>(trigger.entryValue);
5300 res = metadata.update(tag,
5301 &entryValue,
5302 /*count*/1);
5303 break;
5304 }
5305 case TYPE_INT32:
5306 res = metadata.update(tag,
5307 &trigger.entryValue,
5308 /*count*/1);
5309 break;
5310 default:
5311 ALOGE("%s: Type not supported: 0x%x",
5312 __FUNCTION__,
5313 trigger.getTagType());
5314 return INVALID_OPERATION;
5315 }
5316
5317 if (res != OK) {
5318 ALOGE("%s: Failed to restore request metadata with trigger tag %s"
5319 ", trigger value %d", __FUNCTION__,
5320 trigger.getTagName(), trigger.entryValue);
5321 return res;
5322 }
5323 }
5324 mTriggerReplacedMap.clear();
5325
5326 /**
5327 * Remove all new entries.
5328 */
5329 for (size_t i = 0; i < mTriggerRemovedMap.size(); ++i) {
5330 RequestTrigger trigger = mTriggerRemovedMap.valueAt(i);
5331 status_t res = metadata.erase(trigger.metadataTag);
5332
5333 if (res != OK) {
5334 ALOGE("%s: Failed to erase metadata with trigger tag %s"
5335 ", trigger value %d", __FUNCTION__,
5336 trigger.getTagName(), trigger.entryValue);
5337 return res;
5338 }
5339 }
5340 mTriggerRemovedMap.clear();
5341
5342 return OK;
5343}
5344
Eino-Ville Talvala2f876f92013-09-13 11:39:24 -07005345status_t Camera3Device::RequestThread::addDummyTriggerIds(
5346 const sp<CaptureRequest> &request) {
Eino-Ville Talvalad309fb92015-11-25 12:12:45 -08005347 // Trigger ID 0 had special meaning in the HAL2 spec, so avoid it here
Eino-Ville Talvala2f876f92013-09-13 11:39:24 -07005348 static const int32_t dummyTriggerId = 1;
5349 status_t res;
5350
Emilian Peevaebbe412018-01-15 13:53:24 +00005351 CameraMetadata &metadata = request->mSettingsList.begin()->metadata;
Eino-Ville Talvala2f876f92013-09-13 11:39:24 -07005352
5353 // If AF trigger is active, insert a dummy AF trigger ID if none already
5354 // exists
5355 camera_metadata_entry afTrigger = metadata.find(ANDROID_CONTROL_AF_TRIGGER);
5356 camera_metadata_entry afId = metadata.find(ANDROID_CONTROL_AF_TRIGGER_ID);
5357 if (afTrigger.count > 0 &&
5358 afTrigger.data.u8[0] != ANDROID_CONTROL_AF_TRIGGER_IDLE &&
5359 afId.count == 0) {
5360 res = metadata.update(ANDROID_CONTROL_AF_TRIGGER_ID, &dummyTriggerId, 1);
5361 if (res != OK) return res;
5362 }
5363
5364 // If AE precapture trigger is active, insert a dummy precapture trigger ID
5365 // if none already exists
5366 camera_metadata_entry pcTrigger =
5367 metadata.find(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER);
5368 camera_metadata_entry pcId = metadata.find(ANDROID_CONTROL_AE_PRECAPTURE_ID);
5369 if (pcTrigger.count > 0 &&
5370 pcTrigger.data.u8[0] != ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE &&
5371 pcId.count == 0) {
5372 res = metadata.update(ANDROID_CONTROL_AE_PRECAPTURE_ID,
5373 &dummyTriggerId, 1);
5374 if (res != OK) return res;
5375 }
5376
5377 return OK;
5378}
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005379
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08005380bool Camera3Device::RequestThread::overrideAutoRotateAndCrop(
5381 const sp<CaptureRequest> &request) {
5382 ATRACE_CALL();
5383
5384 if (request->mRotateAndCropAuto) {
5385 Mutex::Autolock l(mTriggerMutex);
5386 CameraMetadata &metadata = request->mSettingsList.begin()->metadata;
5387
5388 auto rotateAndCropEntry = metadata.find(ANDROID_SCALER_ROTATE_AND_CROP);
5389 if (rotateAndCropEntry.count > 0) {
5390 if (rotateAndCropEntry.data.u8[0] == mRotateAndCropOverride) {
5391 return false;
5392 } else {
5393 rotateAndCropEntry.data.u8[0] = mRotateAndCropOverride;
5394 return true;
5395 }
5396 } else {
5397 uint8_t rotateAndCrop_u8 = mRotateAndCropOverride;
5398 metadata.update(ANDROID_SCALER_ROTATE_AND_CROP,
5399 &rotateAndCrop_u8, 1);
5400 return true;
5401 }
5402 }
5403 return false;
5404}
5405
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005406/**
5407 * PreparerThread inner class methods
5408 */
5409
5410Camera3Device::PreparerThread::PreparerThread() :
Eino-Ville Talvala77c1a352016-06-13 12:32:43 -07005411 Thread(/*canCallJava*/false), mListener(nullptr),
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005412 mActive(false), mCancelNow(false), mCurrentMaxCount(0), mCurrentPrepareComplete(false) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005413}
5414
5415Camera3Device::PreparerThread::~PreparerThread() {
5416 Thread::requestExitAndWait();
5417 if (mCurrentStream != nullptr) {
5418 mCurrentStream->cancelPrepare();
5419 ATRACE_ASYNC_END("stream prepare", mCurrentStream->getId());
5420 mCurrentStream.clear();
5421 }
5422 clear();
5423}
5424
Ruben Brunkc78ac262015-08-13 17:58:46 -07005425status_t Camera3Device::PreparerThread::prepare(int maxCount, sp<Camera3StreamInterface>& stream) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005426 ATRACE_CALL();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005427 status_t res;
5428
5429 Mutex::Autolock l(mLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005430 sp<NotificationListener> listener = mListener.promote();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005431
Shuzhen Wangb3a0fb52018-09-13 17:24:08 -07005432 res = stream->startPrepare(maxCount, true /*blockRequest*/);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005433 if (res == OK) {
5434 // No preparation needed, fire listener right off
5435 ALOGV("%s: Stream %d already prepared", __FUNCTION__, stream->getId());
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005436 if (listener != NULL) {
5437 listener->notifyPrepared(stream->getId());
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005438 }
5439 return OK;
5440 } else if (res != NOT_ENOUGH_DATA) {
5441 return res;
5442 }
5443
5444 // Need to prepare, start up thread if necessary
5445 if (!mActive) {
5446 // mRunning will change to false before the thread fully shuts down, so wait to be sure it
5447 // isn't running
5448 Thread::requestExitAndWait();
5449 res = Thread::run("C3PrepThread", PRIORITY_BACKGROUND);
5450 if (res != OK) {
5451 ALOGE("%s: Unable to start preparer stream: %d (%s)", __FUNCTION__, res, strerror(-res));
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005452 if (listener != NULL) {
5453 listener->notifyPrepared(stream->getId());
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005454 }
5455 return res;
5456 }
5457 mCancelNow = false;
5458 mActive = true;
5459 ALOGV("%s: Preparer stream started", __FUNCTION__);
5460 }
5461
5462 // queue up the work
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005463 mPendingStreams.emplace(maxCount, stream);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005464 ALOGV("%s: Stream %d queued for preparing", __FUNCTION__, stream->getId());
5465
5466 return OK;
5467}
5468
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005469void Camera3Device::PreparerThread::pause() {
5470 ATRACE_CALL();
5471
5472 Mutex::Autolock l(mLock);
5473
5474 std::unordered_map<int, sp<camera3::Camera3StreamInterface> > pendingStreams;
5475 pendingStreams.insert(mPendingStreams.begin(), mPendingStreams.end());
5476 sp<camera3::Camera3StreamInterface> currentStream = mCurrentStream;
5477 int currentMaxCount = mCurrentMaxCount;
5478 mPendingStreams.clear();
5479 mCancelNow = true;
5480 while (mActive) {
5481 auto res = mThreadActiveSignal.waitRelative(mLock, kActiveTimeout);
5482 if (res == TIMED_OUT) {
5483 ALOGE("%s: Timed out waiting on prepare thread!", __FUNCTION__);
5484 return;
5485 } else if (res != OK) {
5486 ALOGE("%s: Encountered an error: %d waiting on prepare thread!", __FUNCTION__, res);
5487 return;
5488 }
5489 }
5490
5491 //Check whether the prepare thread was able to complete the current
5492 //stream. In case work is still pending emplace it along with the rest
5493 //of the streams in the pending list.
5494 if (currentStream != nullptr) {
5495 if (!mCurrentPrepareComplete) {
5496 pendingStreams.emplace(currentMaxCount, currentStream);
5497 }
5498 }
5499
5500 mPendingStreams.insert(pendingStreams.begin(), pendingStreams.end());
5501 for (const auto& it : mPendingStreams) {
5502 it.second->cancelPrepare();
5503 }
5504}
5505
5506status_t Camera3Device::PreparerThread::resume() {
5507 ATRACE_CALL();
5508 status_t res;
5509
5510 Mutex::Autolock l(mLock);
5511 sp<NotificationListener> listener = mListener.promote();
5512
5513 if (mActive) {
5514 ALOGE("%s: Trying to resume an already active prepare thread!", __FUNCTION__);
5515 return NO_INIT;
5516 }
5517
5518 auto it = mPendingStreams.begin();
5519 for (; it != mPendingStreams.end();) {
Shuzhen Wangb3a0fb52018-09-13 17:24:08 -07005520 res = it->second->startPrepare(it->first, true /*blockRequest*/);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005521 if (res == OK) {
5522 if (listener != NULL) {
5523 listener->notifyPrepared(it->second->getId());
5524 }
5525 it = mPendingStreams.erase(it);
5526 } else if (res != NOT_ENOUGH_DATA) {
5527 ALOGE("%s: Unable to start preparer stream: %d (%s)", __FUNCTION__,
5528 res, strerror(-res));
5529 it = mPendingStreams.erase(it);
5530 } else {
5531 it++;
5532 }
5533 }
5534
5535 if (mPendingStreams.empty()) {
5536 return OK;
5537 }
5538
5539 res = Thread::run("C3PrepThread", PRIORITY_BACKGROUND);
5540 if (res != OK) {
5541 ALOGE("%s: Unable to start preparer stream: %d (%s)",
5542 __FUNCTION__, res, strerror(-res));
5543 return res;
5544 }
5545 mCancelNow = false;
5546 mActive = true;
5547 ALOGV("%s: Preparer stream started", __FUNCTION__);
5548
5549 return OK;
5550}
5551
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005552status_t Camera3Device::PreparerThread::clear() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005553 ATRACE_CALL();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005554 Mutex::Autolock l(mLock);
5555
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005556 for (const auto& it : mPendingStreams) {
5557 it.second->cancelPrepare();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005558 }
5559 mPendingStreams.clear();
5560 mCancelNow = true;
5561
5562 return OK;
5563}
5564
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005565void Camera3Device::PreparerThread::setNotificationListener(wp<NotificationListener> listener) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005566 ATRACE_CALL();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005567 Mutex::Autolock l(mLock);
5568 mListener = listener;
5569}
5570
5571bool Camera3Device::PreparerThread::threadLoop() {
5572 status_t res;
5573 {
5574 Mutex::Autolock l(mLock);
5575 if (mCurrentStream == nullptr) {
5576 // End thread if done with work
5577 if (mPendingStreams.empty()) {
5578 ALOGV("%s: Preparer stream out of work", __FUNCTION__);
5579 // threadLoop _must not_ re-acquire mLock after it sets mActive to false; would
5580 // cause deadlock with prepare()'s requestExitAndWait triggered by !mActive.
5581 mActive = false;
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005582 mThreadActiveSignal.signal();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005583 return false;
5584 }
5585
5586 // Get next stream to prepare
5587 auto it = mPendingStreams.begin();
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005588 mCurrentStream = it->second;
5589 mCurrentMaxCount = it->first;
5590 mCurrentPrepareComplete = false;
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005591 mPendingStreams.erase(it);
5592 ATRACE_ASYNC_BEGIN("stream prepare", mCurrentStream->getId());
5593 ALOGV("%s: Preparing stream %d", __FUNCTION__, mCurrentStream->getId());
5594 } else if (mCancelNow) {
5595 mCurrentStream->cancelPrepare();
5596 ATRACE_ASYNC_END("stream prepare", mCurrentStream->getId());
5597 ALOGV("%s: Cancelling stream %d prepare", __FUNCTION__, mCurrentStream->getId());
5598 mCurrentStream.clear();
5599 mCancelNow = false;
5600 return true;
5601 }
5602 }
5603
5604 res = mCurrentStream->prepareNextBuffer();
5605 if (res == NOT_ENOUGH_DATA) return true;
5606 if (res != OK) {
5607 // Something bad happened; try to recover by cancelling prepare and
5608 // signalling listener anyway
5609 ALOGE("%s: Stream %d returned error %d (%s) during prepare", __FUNCTION__,
5610 mCurrentStream->getId(), res, strerror(-res));
5611 mCurrentStream->cancelPrepare();
5612 }
5613
5614 // This stream has finished, notify listener
5615 Mutex::Autolock l(mLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005616 sp<NotificationListener> listener = mListener.promote();
5617 if (listener != NULL) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005618 ALOGV("%s: Stream %d prepare done, signaling listener", __FUNCTION__,
5619 mCurrentStream->getId());
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005620 listener->notifyPrepared(mCurrentStream->getId());
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005621 }
5622
5623 ATRACE_ASYNC_END("stream prepare", mCurrentStream->getId());
5624 mCurrentStream.clear();
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005625 mCurrentPrepareComplete = true;
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005626
5627 return true;
5628}
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005629
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005630status_t Camera3Device::RequestBufferStateMachine::initialize(
5631 sp<camera3::StatusTracker> statusTracker) {
5632 if (statusTracker == nullptr) {
5633 ALOGE("%s: statusTracker is null", __FUNCTION__);
5634 return BAD_VALUE;
5635 }
5636
5637 std::lock_guard<std::mutex> lock(mLock);
5638 mStatusTracker = statusTracker;
5639 mRequestBufferStatusId = statusTracker->addComponent();
5640 return OK;
5641}
5642
5643bool Camera3Device::RequestBufferStateMachine::startRequestBuffer() {
5644 std::lock_guard<std::mutex> lock(mLock);
Yin-Chia Yeh8a4ccb02018-11-16 15:43:36 -08005645 if (mStatus == RB_STATUS_READY || mStatus == RB_STATUS_PENDING_STOP) {
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005646 mRequestBufferOngoing = true;
Yin-Chia Yeh8a4ccb02018-11-16 15:43:36 -08005647 notifyTrackerLocked(/*active*/true);
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005648 return true;
5649 }
5650 return false;
5651}
5652
5653void Camera3Device::RequestBufferStateMachine::endRequestBuffer() {
5654 std::lock_guard<std::mutex> lock(mLock);
5655 if (!mRequestBufferOngoing) {
5656 ALOGE("%s called without a successful startRequestBuffer call first!", __FUNCTION__);
5657 return;
5658 }
5659 mRequestBufferOngoing = false;
5660 if (mStatus == RB_STATUS_PENDING_STOP) {
5661 checkSwitchToStopLocked();
5662 }
Yin-Chia Yeh8a4ccb02018-11-16 15:43:36 -08005663 notifyTrackerLocked(/*active*/false);
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005664}
5665
5666void Camera3Device::RequestBufferStateMachine::onStreamsConfigured() {
5667 std::lock_guard<std::mutex> lock(mLock);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005668 mSwitchedToOffline = false;
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005669 mStatus = RB_STATUS_READY;
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005670 return;
5671}
5672
Yin-Chia Yehcd333fe2019-02-08 13:45:41 -08005673void Camera3Device::RequestBufferStateMachine::onSubmittingRequest() {
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005674 std::lock_guard<std::mutex> lock(mLock);
5675 mRequestThreadPaused = false;
Yin-Chia Yehcd333fe2019-02-08 13:45:41 -08005676 // inflight map register actually happens in prepareHalRequest now, but it is close enough
5677 // approximation.
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005678 mInflightMapEmpty = false;
5679 if (mStatus == RB_STATUS_STOPPED) {
5680 mStatus = RB_STATUS_READY;
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005681 }
5682 return;
5683}
5684
5685void Camera3Device::RequestBufferStateMachine::onRequestThreadPaused() {
5686 std::lock_guard<std::mutex> lock(mLock);
5687 mRequestThreadPaused = true;
5688 if (mStatus == RB_STATUS_PENDING_STOP) {
5689 checkSwitchToStopLocked();
5690 }
5691 return;
5692}
5693
5694void Camera3Device::RequestBufferStateMachine::onInflightMapEmpty() {
5695 std::lock_guard<std::mutex> lock(mLock);
5696 mInflightMapEmpty = true;
5697 if (mStatus == RB_STATUS_PENDING_STOP) {
5698 checkSwitchToStopLocked();
5699 }
5700 return;
5701}
5702
5703void Camera3Device::RequestBufferStateMachine::onWaitUntilIdle() {
5704 std::lock_guard<std::mutex> lock(mLock);
5705 if (!checkSwitchToStopLocked()) {
5706 mStatus = RB_STATUS_PENDING_STOP;
5707 }
5708 return;
5709}
5710
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005711bool Camera3Device::RequestBufferStateMachine::onSwitchToOfflineSuccess() {
5712 std::lock_guard<std::mutex> lock(mLock);
5713 if (mRequestBufferOngoing) {
5714 ALOGE("%s: HAL must not be requesting buffer after HAL returns switchToOffline!",
5715 __FUNCTION__);
5716 return false;
5717 }
5718 mSwitchedToOffline = true;
5719 mInflightMapEmpty = true;
5720 mRequestThreadPaused = true;
5721 mStatus = RB_STATUS_STOPPED;
5722 return true;
5723}
5724
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005725void Camera3Device::RequestBufferStateMachine::notifyTrackerLocked(bool active) {
5726 sp<StatusTracker> statusTracker = mStatusTracker.promote();
5727 if (statusTracker != nullptr) {
5728 if (active) {
5729 statusTracker->markComponentActive(mRequestBufferStatusId);
5730 } else {
5731 statusTracker->markComponentIdle(mRequestBufferStatusId, Fence::NO_FENCE);
5732 }
5733 }
5734}
5735
5736bool Camera3Device::RequestBufferStateMachine::checkSwitchToStopLocked() {
5737 if (mInflightMapEmpty && mRequestThreadPaused && !mRequestBufferOngoing) {
5738 mStatus = RB_STATUS_STOPPED;
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005739 return true;
5740 }
5741 return false;
5742}
5743
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005744bool Camera3Device::startRequestBuffer() {
5745 return mRequestBufferSM.startRequestBuffer();
5746}
Shuzhen Wang268a1362018-10-16 16:32:59 -07005747
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005748void Camera3Device::endRequestBuffer() {
5749 mRequestBufferSM.endRequestBuffer();
5750}
Shuzhen Wang268a1362018-10-16 16:32:59 -07005751
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005752nsecs_t Camera3Device::getWaitDuration() {
5753 return kBaseGetBufferWait + getExpectedInFlightDuration();
5754}
Shuzhen Wang268a1362018-10-16 16:32:59 -07005755
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005756void Camera3Device::getInflightBufferKeys(std::vector<std::pair<int32_t, int32_t>>* out) {
5757 mInterface->getInflightBufferKeys(out);
5758}
Shuzhen Wang268a1362018-10-16 16:32:59 -07005759
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005760void Camera3Device::getInflightRequestBufferKeys(std::vector<uint64_t>* out) {
5761 mInterface->getInflightRequestBufferKeys(out);
5762}
Shuzhen Wang268a1362018-10-16 16:32:59 -07005763
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005764std::vector<sp<Camera3StreamInterface>> Camera3Device::getAllStreams() {
5765 std::vector<sp<Camera3StreamInterface>> ret;
5766 bool hasInputStream = mInputStream != nullptr;
5767 ret.reserve(mOutputStreams.size() + mDeletedStreams.size() + ((hasInputStream) ? 1 : 0));
5768 if (hasInputStream) {
5769 ret.push_back(mInputStream);
Shuzhen Wang268a1362018-10-16 16:32:59 -07005770 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005771 for (size_t i = 0; i < mOutputStreams.size(); i++) {
5772 ret.push_back(mOutputStreams[i]);
5773 }
5774 for (size_t i = 0; i < mDeletedStreams.size(); i++) {
5775 ret.push_back(mDeletedStreams[i]);
5776 }
5777 return ret;
Shuzhen Wang268a1362018-10-16 16:32:59 -07005778}
5779
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005780status_t Camera3Device::switchToOffline(
5781 const std::vector<int32_t>& streamsToKeep,
5782 /*out*/ sp<CameraOfflineSessionBase>* session) {
5783 ATRACE_CALL();
5784 if (session == nullptr) {
5785 ALOGE("%s: session must not be null", __FUNCTION__);
5786 return BAD_VALUE;
5787 }
5788
5789 Mutex::Autolock il(mInterfaceLock);
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005790
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005791 bool hasInputStream = mInputStream != nullptr;
5792 int32_t inputStreamId = hasInputStream ? mInputStream->getId() : -1;
5793 bool inputStreamSupportsOffline = hasInputStream ?
5794 mInputStream->getOfflineProcessingSupport() : false;
5795 auto outputStreamIds = mOutputStreams.getStreamIds();
5796 auto streamIds = outputStreamIds;
5797 if (hasInputStream) {
5798 streamIds.push_back(mInputStream->getId());
5799 }
5800
5801 // Check all streams in streamsToKeep supports offline mode
5802 for (auto id : streamsToKeep) {
5803 if (std::find(streamIds.begin(), streamIds.end(), id) == streamIds.end()) {
5804 ALOGE("%s: Unknown stream ID %d", __FUNCTION__, id);
5805 return BAD_VALUE;
5806 } else if (id == inputStreamId) {
5807 if (!inputStreamSupportsOffline) {
5808 ALOGE("%s: input stream %d cannot be switched to offline",
5809 __FUNCTION__, id);
5810 return BAD_VALUE;
5811 }
5812 } else {
5813 sp<camera3::Camera3OutputStreamInterface> stream = mOutputStreams.get(id);
5814 if (!stream->getOfflineProcessingSupport()) {
5815 ALOGE("%s: output stream %d cannot be switched to offline",
5816 __FUNCTION__, id);
5817 return BAD_VALUE;
5818 }
5819 }
5820 }
5821
5822 // TODO: block surface sharing and surface group streams until we can support them
5823
5824 // Stop repeating request, wait until all remaining requests are submitted, then call into
5825 // HAL switchToOffline
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005826 hardware::camera::device::V3_6::CameraOfflineSessionInfo offlineSessionInfo;
5827 sp<hardware::camera::device::V3_6::ICameraOfflineSession> offlineSession;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005828 camera3::BufferRecords bufferRecords;
5829 status_t ret = mRequestThread->switchToOffline(
5830 streamsToKeep, &offlineSessionInfo, &offlineSession, &bufferRecords);
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005831
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005832 if (ret != OK) {
5833 SET_ERR("Switch to offline failed: %s (%d)", strerror(-ret), ret);
5834 return ret;
5835 }
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005836
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005837 bool succ = mRequestBufferSM.onSwitchToOfflineSuccess();
5838 if (!succ) {
5839 SET_ERR("HAL must not be calling requestStreamBuffers call");
5840 // TODO: block ALL callbacks from HAL till app configured new streams?
5841 return UNKNOWN_ERROR;
5842 }
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005843
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005844 // Verify offlineSessionInfo
5845 std::vector<int32_t> offlineStreamIds;
5846 offlineStreamIds.reserve(offlineSessionInfo.offlineStreams.size());
5847 for (auto offlineStream : offlineSessionInfo.offlineStreams) {
5848 // verify stream IDs
5849 int32_t id = offlineStream.id;
5850 if (std::find(streamIds.begin(), streamIds.end(), id) == streamIds.end()) {
5851 SET_ERR("stream ID %d not found!", id);
5852 return UNKNOWN_ERROR;
5853 }
5854
5855 // When not using HAL buf manager, only allow streams requested by app to be preserved
5856 if (!mUseHalBufManager) {
5857 if (std::find(streamsToKeep.begin(), streamsToKeep.end(), id) == streamsToKeep.end()) {
5858 SET_ERR("stream ID %d must not be switched to offline!", id);
5859 return UNKNOWN_ERROR;
5860 }
5861 }
5862
5863 offlineStreamIds.push_back(id);
5864 sp<Camera3StreamInterface> stream = (id == inputStreamId) ?
5865 static_cast<sp<Camera3StreamInterface>>(mInputStream) :
5866 static_cast<sp<Camera3StreamInterface>>(mOutputStreams.get(id));
5867 // Verify number of outstanding buffers
5868 if (stream->getOutstandingBuffersCount() != offlineStream.numOutstandingBuffers) {
5869 SET_ERR("Offline stream %d # of remaining buffer mismatch: (%zu,%d) (service/HAL)",
5870 id, stream->getOutstandingBuffersCount(), offlineStream.numOutstandingBuffers);
5871 return UNKNOWN_ERROR;
5872 }
5873 }
5874
5875 // Verify all streams to be deleted don't have any outstanding buffers
5876 if (hasInputStream && std::find(offlineStreamIds.begin(), offlineStreamIds.end(),
5877 inputStreamId) == offlineStreamIds.end()) {
5878 if (mInputStream->hasOutstandingBuffers()) {
5879 SET_ERR("Input stream %d still has %zu outstanding buffer!",
5880 inputStreamId, mInputStream->getOutstandingBuffersCount());
5881 return UNKNOWN_ERROR;
5882 }
5883 }
5884
5885 for (const auto& outStreamId : outputStreamIds) {
5886 if (std::find(offlineStreamIds.begin(), offlineStreamIds.end(),
5887 outStreamId) == offlineStreamIds.end()) {
5888 auto outStream = mOutputStreams.get(outStreamId);
5889 if (outStream->hasOutstandingBuffers()) {
5890 SET_ERR("Output stream %d still has %zu outstanding buffer!",
5891 outStreamId, outStream->getOutstandingBuffersCount());
5892 return UNKNOWN_ERROR;
5893 }
5894 }
5895 }
5896
5897 InFlightRequestMap offlineReqs;
5898 // Verify inflight requests and their pending buffers
5899 {
5900 std::lock_guard<std::mutex> l(mInFlightLock);
5901 for (auto offlineReq : offlineSessionInfo.offlineRequests) {
5902 int idx = mInFlightMap.indexOfKey(offlineReq.frameNumber);
5903 if (idx == NAME_NOT_FOUND) {
5904 SET_ERR("Offline request frame number %d not found!", offlineReq.frameNumber);
5905 return UNKNOWN_ERROR;
5906 }
5907
5908 const auto& inflightReq = mInFlightMap.valueAt(idx);
5909 // TODO: check specific stream IDs
5910 size_t numBuffersLeft = static_cast<size_t>(inflightReq.numBuffersLeft);
5911 if (numBuffersLeft != offlineReq.pendingStreams.size()) {
5912 SET_ERR("Offline request # of remaining buffer mismatch: (%d,%d) (service/HAL)",
5913 inflightReq.numBuffersLeft, offlineReq.pendingStreams.size());
5914 return UNKNOWN_ERROR;
5915 }
5916 offlineReqs.add(offlineReq.frameNumber, inflightReq);
5917 }
5918 }
5919
5920 // Create Camera3OfflineSession and transfer object ownership
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005921 // (streams, inflight requests, buffer caches)
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005922 camera3::StreamSet offlineStreamSet;
5923 sp<camera3::Camera3Stream> inputStream;
5924 for (auto offlineStream : offlineSessionInfo.offlineStreams) {
5925 int32_t id = offlineStream.id;
5926 if (mInputStream != nullptr && id == mInputStream->getId()) {
5927 inputStream = mInputStream;
5928 } else {
5929 offlineStreamSet.add(id, mOutputStreams.get(id));
5930 }
5931 }
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005932
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005933 // TODO: check if we need to lock before copying states
5934 // though technically no other thread should be talking to Camera3Device at this point
5935 Camera3OfflineStates offlineStates(
5936 mTagMonitor, mVendorTagId, mUseHalBufManager, mNeedFixupMonochromeTags,
Shuzhen Wangb7b42652020-05-07 11:59:02 -07005937 mUsePartialResult, mNumPartialResults, mLastCompletedRegularFrameNumber,
5938 mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
5939 mNextResultFrameNumber, mNextReprocessResultFrameNumber,
5940 mNextZslStillResultFrameNumber, mNextShutterFrameNumber,
5941 mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
5942 mDeviceInfo, mPhysicalDeviceInfoMap, mDistortionMappers,
5943 mZoomRatioMappers, mRotateAndCropMappers);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005944
5945 *session = new Camera3OfflineSession(mId, inputStream, offlineStreamSet,
5946 std::move(bufferRecords), offlineReqs, offlineStates, offlineSession);
5947
5948 // Delete all streams that has been transferred to offline session
5949 Mutex::Autolock l(mLock);
5950 for (auto offlineStream : offlineSessionInfo.offlineStreams) {
5951 int32_t id = offlineStream.id;
5952 if (mInputStream != nullptr && id == mInputStream->getId()) {
5953 mInputStream.clear();
5954 } else {
5955 mOutputStreams.remove(id);
5956 }
5957 }
5958
5959 // disconnect all other streams and switch to UNCONFIGURED state
5960 if (mInputStream != nullptr) {
5961 ret = mInputStream->disconnect();
5962 if (ret != OK) {
5963 SET_ERR_L("disconnect input stream failed!");
5964 return UNKNOWN_ERROR;
5965 }
5966 }
5967
5968 for (auto streamId : mOutputStreams.getStreamIds()) {
5969 sp<Camera3StreamInterface> stream = mOutputStreams.get(streamId);
5970 ret = stream->disconnect();
5971 if (ret != OK) {
5972 SET_ERR_L("disconnect output stream %d failed!", streamId);
5973 return UNKNOWN_ERROR;
5974 }
5975 }
5976
5977 mInputStream.clear();
5978 mOutputStreams.clear();
5979 mNeedConfig = true;
5980 internalUpdateStatusLocked(STATUS_UNCONFIGURED);
5981 mOperatingMode = NO_MODE;
5982 mIsConstrainedHighSpeedConfiguration = false;
Emilian Peevc0fe54c2020-03-11 14:05:07 -07005983 mRequestThread->clearPreviousRequest();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005984
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005985 return OK;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005986 // TO be done by CameraDeviceClient/Camera3OfflineSession
5987 // register the offline client to camera service
5988 // Setup result passthing threads etc
5989 // Initialize offline session so HAL can start sending callback to it (result Fmq)
5990 // TODO: check how many onIdle callback will be sent
5991 // Java side to make sure the CameraCaptureSession is properly closed
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005992}
5993
Emilian Peevcc0b7952020-01-07 13:54:47 -08005994void Camera3Device::getOfflineStreamIds(std::vector<int> *offlineStreamIds) {
5995 ATRACE_CALL();
5996
5997 if (offlineStreamIds == nullptr) {
5998 return;
5999 }
6000
6001 Mutex::Autolock il(mInterfaceLock);
6002
6003 auto streamIds = mOutputStreams.getStreamIds();
6004 bool hasInputStream = mInputStream != nullptr;
6005 if (hasInputStream && mInputStream->getOfflineProcessingSupport()) {
6006 offlineStreamIds->push_back(mInputStream->getId());
6007 }
6008
6009 for (const auto & streamId : streamIds) {
6010 sp<camera3::Camera3OutputStreamInterface> stream = mOutputStreams.get(streamId);
6011 // Streams that use the camera buffer manager are currently not supported in
6012 // offline mode
6013 if (stream->getOfflineProcessingSupport() &&
6014 (stream->getStreamSetId() == CAMERA3_STREAM_SET_ID_INVALID)) {
6015 offlineStreamIds->push_back(streamId);
6016 }
6017 }
6018}
6019
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08006020status_t Camera3Device::setRotateAndCropAutoBehavior(
6021 camera_metadata_enum_android_scaler_rotate_and_crop_t rotateAndCropValue) {
6022 ATRACE_CALL();
6023 Mutex::Autolock il(mInterfaceLock);
6024 Mutex::Autolock l(mLock);
6025 if (mRequestThread == nullptr) {
6026 return INVALID_OPERATION;
6027 }
6028 return mRequestThread->setRotateAndCropAutoBehavior(rotateAndCropValue);
6029}
6030
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08006031}; // namespace android