blob: b00a2d95cdb2e9ed614ba43c1890c7cc924ff6fc [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"
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -080063
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -080064#include <algorithm>
Yin-Chia Yeh84be5782019-03-01 11:47:02 -080065#include <tuple>
66
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -080067using namespace android::camera3;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -080068using namespace android::hardware::camera;
69using namespace android::hardware::camera::device::V3_2;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -080070
71namespace android {
72
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -080073Camera3Device::Camera3Device(const String8 &id):
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -080074 mId(id),
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -080075 mOperatingMode(NO_MODE),
Eino-Ville Talvala9a179412015-06-09 13:15:16 -070076 mIsConstrainedHighSpeedConfiguration(false),
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -070077 mStatus(STATUS_UNINITIALIZED),
Ruben Brunk183f0562015-08-12 12:55:02 -070078 mStatusWaiters(0),
Zhijun He204e3292014-07-14 17:09:23 -070079 mUsePartialResult(false),
80 mNumPartialResults(1),
Shuzhen Wangc28dccc2016-02-11 23:48:46 -080081 mTimestampOffset(0),
Eino-Ville Talvala42368d92013-04-09 14:13:50 -070082 mNextResultFrameNumber(0),
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -070083 mNextReprocessResultFrameNumber(0),
Shuzhen Wang5ee99842019-04-12 11:55:48 -070084 mNextZslStillResultFrameNumber(0),
Eino-Ville Talvala42368d92013-04-09 14:13:50 -070085 mNextShutterFrameNumber(0),
Chien-Yu Chen3df11ce2015-09-30 14:13:30 -070086 mNextReprocessShutterFrameNumber(0),
Shuzhen Wang5ee99842019-04-12 11:55:48 -070087 mNextZslStillShutterFrameNumber(0),
Emilian Peev71c73a22017-03-21 16:35:51 +000088 mListener(NULL),
Emilian Peev811d2952018-05-25 11:08:40 +010089 mVendorTagId(CAMERA_METADATA_INVALID_VENDOR_ID),
Shuzhen Wang268a1362018-10-16 16:32:59 -070090 mLastTemplateId(-1),
91 mNeedFixupMonochromeTags(false)
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -080092{
93 ATRACE_CALL();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -080094 ALOGV("%s: Created device for camera %s", __FUNCTION__, mId.string());
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -080095}
96
97Camera3Device::~Camera3Device()
98{
99 ATRACE_CALL();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800100 ALOGV("%s: Tearing down for camera id %s", __FUNCTION__, mId.string());
Yin-Chia Yehc5248132018-08-15 12:19:20 -0700101 disconnectImpl();
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800102}
103
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800104const String8& Camera3Device::getId() const {
Igor Murashkin71381052013-03-04 14:53:08 -0800105 return mId;
106}
107
Emilian Peevbd8c5032018-02-14 23:05:40 +0000108status_t Camera3Device::initialize(sp<CameraProviderManager> manager, const String8& monitorTags) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800109 ATRACE_CALL();
110 Mutex::Autolock il(mInterfaceLock);
111 Mutex::Autolock l(mLock);
112
113 ALOGV("%s: Initializing HIDL device for camera %s", __FUNCTION__, mId.string());
114 if (mStatus != STATUS_UNINITIALIZED) {
115 CLOGE("Already initialized!");
116 return INVALID_OPERATION;
117 }
118 if (manager == nullptr) return INVALID_OPERATION;
119
120 sp<ICameraDeviceSession> session;
121 ATRACE_BEGIN("CameraHal::openSession");
Steven Moreland5ff9c912017-03-09 23:13:00 -0800122 status_t res = manager->openSession(mId.string(), this,
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800123 /*out*/ &session);
124 ATRACE_END();
125 if (res != OK) {
126 SET_ERR_L("Could not open camera session: %s (%d)", strerror(-res), res);
127 return res;
128 }
129
Steven Moreland5ff9c912017-03-09 23:13:00 -0800130 res = manager->getCameraCharacteristics(mId.string(), &mDeviceInfo);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800131 if (res != OK) {
Shuzhen Wang2e7f58f2018-07-11 14:00:29 -0700132 SET_ERR_L("Could not retrieve camera characteristics: %s (%d)", strerror(-res), res);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800133 session->close();
134 return res;
135 }
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -0800136 mSupportNativeZoomRatio = manager->supportNativeZoomRatio(mId.string());
Yin-Chia Yeh52778d42016-12-22 18:20:43 -0800137
Shuzhen Wang2e7f58f2018-07-11 14:00:29 -0700138 std::vector<std::string> physicalCameraIds;
Shuzhen Wang03d8cc12018-09-12 14:17:09 -0700139 bool isLogical = manager->isLogicalCamera(mId.string(), &physicalCameraIds);
Shuzhen Wang2e7f58f2018-07-11 14:00:29 -0700140 if (isLogical) {
141 for (auto& physicalId : physicalCameraIds) {
Shuzhen Wang4f6fa9d2019-03-29 10:40:35 -0700142 res = manager->getCameraCharacteristics(
143 physicalId, &mPhysicalDeviceInfoMap[physicalId]);
Shuzhen Wang2e7f58f2018-07-11 14:00:29 -0700144 if (res != OK) {
145 SET_ERR_L("Could not retrieve camera %s characteristics: %s (%d)",
146 physicalId.c_str(), strerror(-res), res);
147 session->close();
148 return res;
149 }
Shuzhen Wang4f6fa9d2019-03-29 10:40:35 -0700150
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -0800151 bool usePrecorrectArray =
152 DistortionMapper::isDistortionSupported(mPhysicalDeviceInfoMap[physicalId]);
153 if (usePrecorrectArray) {
154 res = mDistortionMappers[physicalId].setupStaticInfo(
155 mPhysicalDeviceInfoMap[physicalId]);
Shuzhen Wang4f6fa9d2019-03-29 10:40:35 -0700156 if (res != OK) {
157 SET_ERR_L("Unable to read camera %s's calibration fields for distortion "
158 "correction", physicalId.c_str());
159 session->close();
160 return res;
161 }
162 }
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -0800163
Shuzhen Wang1c834da2019-12-18 11:17:03 -0800164 mZoomRatioMappers[physicalId] = ZoomRatioMapper(
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -0800165 &mPhysicalDeviceInfoMap[physicalId],
166 mSupportNativeZoomRatio, usePrecorrectArray);
Shuzhen Wang2e7f58f2018-07-11 14:00:29 -0700167 }
168 }
169
Yifan Hongf79b5542017-04-11 14:44:25 -0700170 std::shared_ptr<RequestMetadataQueue> queue;
Yifan Honga640c5a2017-04-12 16:30:31 -0700171 auto requestQueueRet = session->getCaptureRequestMetadataQueue(
172 [&queue](const auto& descriptor) {
173 queue = std::make_shared<RequestMetadataQueue>(descriptor);
174 if (!queue->isValid() || queue->availableToWrite() <= 0) {
175 ALOGE("HAL returns empty request metadata fmq, not use it");
176 queue = nullptr;
177 // don't use the queue onwards.
178 }
179 });
180 if (!requestQueueRet.isOk()) {
181 ALOGE("Transaction error when getting request metadata fmq: %s, not use it",
182 requestQueueRet.description().c_str());
Eino-Ville Talvalac5cbb872017-04-27 12:48:33 -0700183 return DEAD_OBJECT;
Yifan Hongf79b5542017-04-11 14:44:25 -0700184 }
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700185
186 std::unique_ptr<ResultMetadataQueue>& resQueue = mResultMetadataQueue;
Yifan Honga640c5a2017-04-12 16:30:31 -0700187 auto resultQueueRet = session->getCaptureResultMetadataQueue(
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700188 [&resQueue](const auto& descriptor) {
189 resQueue = std::make_unique<ResultMetadataQueue>(descriptor);
190 if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
Yifan Honga640c5a2017-04-12 16:30:31 -0700191 ALOGE("HAL returns empty result metadata fmq, not use it");
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700192 resQueue = nullptr;
193 // Don't use the resQueue onwards.
Yifan Honga640c5a2017-04-12 16:30:31 -0700194 }
195 });
196 if (!resultQueueRet.isOk()) {
197 ALOGE("Transaction error when getting result metadata queue from camera session: %s",
198 resultQueueRet.description().c_str());
Eino-Ville Talvalac5cbb872017-04-27 12:48:33 -0700199 return DEAD_OBJECT;
Yifan Honga640c5a2017-04-12 16:30:31 -0700200 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -0700201 IF_ALOGV() {
202 session->interfaceChain([](
203 ::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
204 ALOGV("Session interface chain:");
Chih-Hung Hsieh3ef324d2018-12-11 11:48:12 -0800205 for (const auto& iface : interfaceChain) {
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -0700206 ALOGV(" %s", iface.c_str());
207 }
208 });
209 }
Yifan Hongf79b5542017-04-11 14:44:25 -0700210
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -0800211 camera_metadata_entry bufMgrMode =
212 mDeviceInfo.find(ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION);
213 if (bufMgrMode.count > 0) {
214 mUseHalBufManager = (bufMgrMode.data.u8[0] ==
215 ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5);
216 }
217
Yin-Chia Yehb978c382019-10-30 00:22:37 -0700218 camera_metadata_entry_t capabilities = mDeviceInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
219 for (size_t i = 0; i < capabilities.count; i++) {
220 uint8_t capability = capabilities.data.u8[i];
221 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_OFFLINE_PROCESSING) {
222 mSupportOfflineProcessing = true;
223 }
224 }
225
226 mInterface = new HalInterface(session, queue, mUseHalBufManager, mSupportOfflineProcessing);
Emilian Peev71c73a22017-03-21 16:35:51 +0000227 std::string providerType;
228 mVendorTagId = manager->getProviderTagIdLocked(mId.string());
Emilian Peevbd8c5032018-02-14 23:05:40 +0000229 mTagMonitor.initialize(mVendorTagId);
230 if (!monitorTags.isEmpty()) {
231 mTagMonitor.parseTagsToMonitor(String8(monitorTags));
232 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800233
Shuzhen Wang268a1362018-10-16 16:32:59 -0700234 // Metadata tags needs fixup for monochrome camera device version less
235 // than 3.5.
236 hardware::hidl_version maxVersion{0,0};
237 res = manager->getHighestSupportedVersion(mId.string(), &maxVersion);
238 if (res != OK) {
239 ALOGE("%s: Error in getting camera device version id: %s (%d)",
240 __FUNCTION__, strerror(-res), res);
241 return res;
242 }
243 int deviceVersion = HARDWARE_DEVICE_API_VERSION(
244 maxVersion.get_major(), maxVersion.get_minor());
245
246 bool isMonochrome = false;
Yin-Chia Yehb978c382019-10-30 00:22:37 -0700247 for (size_t i = 0; i < capabilities.count; i++) {
248 uint8_t capability = capabilities.data.u8[i];
Shuzhen Wang268a1362018-10-16 16:32:59 -0700249 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME) {
250 isMonochrome = true;
251 }
252 }
253 mNeedFixupMonochromeTags = (isMonochrome && deviceVersion < CAMERA_DEVICE_API_VERSION_3_5);
254
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800255 return initializeCommonLocked();
256}
257
258status_t Camera3Device::initializeCommonLocked() {
259
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700260 /** Start up status tracker thread */
261 mStatusTracker = new StatusTracker(this);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800262 status_t res = mStatusTracker->run(String8::format("C3Dev-%s-Status", mId.string()).string());
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700263 if (res != OK) {
264 SET_ERR_L("Unable to start status tracking thread: %s (%d)",
265 strerror(-res), res);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800266 mInterface->close();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700267 mStatusTracker.clear();
268 return res;
269 }
270
Eino-Ville Talvala24b366e2016-07-21 12:53:07 -0700271 /** Register in-flight map to the status tracker */
272 mInFlightStatusId = mStatusTracker->addComponent();
273
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -0700274 if (mUseHalBufManager) {
275 res = mRequestBufferSM.initialize(mStatusTracker);
276 if (res != OK) {
277 SET_ERR_L("Unable to start request buffer state machine: %s (%d)",
278 strerror(-res), res);
279 mInterface->close();
280 mStatusTracker.clear();
281 return res;
282 }
283 }
284
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -0800285 /** Create buffer manager */
286 mBufferManager = new Camera3BufferManager();
287
288 Vector<int32_t> sessionParamKeys;
289 camera_metadata_entry_t sessionKeysEntry = mDeviceInfo.find(
290 ANDROID_REQUEST_AVAILABLE_SESSION_KEYS);
291 if (sessionKeysEntry.count > 0) {
292 sessionParamKeys.insertArrayAt(sessionKeysEntry.data.i32, 0, sessionKeysEntry.count);
293 }
294
Chien-Yu Chenab5135b2015-06-30 11:20:58 -0700295 /** Start up request queue thread */
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -0700296 mRequestThread = new RequestThread(
297 this, mStatusTracker, mInterface, sessionParamKeys, mUseHalBufManager);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800298 res = mRequestThread->run(String8::format("C3Dev-%s-ReqQueue", mId.string()).string());
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800299 if (res != OK) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -0700300 SET_ERR_L("Unable to start request queue thread: %s (%d)",
301 strerror(-res), res);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800302 mInterface->close();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800303 mRequestThread.clear();
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800304 return res;
305 }
306
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -0700307 mPreparerThread = new PreparerThread();
308
Ruben Brunk183f0562015-08-12 12:55:02 -0700309 internalUpdateStatusLocked(STATUS_UNCONFIGURED);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800310 mNextStreamId = 0;
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -0700311 mDummyStreamId = NO_STREAM;
Eino-Ville Talvalaea26c772013-06-11 16:04:06 -0700312 mNeedConfig = true;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700313 mPauseStateNotify = false;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800314
Shuzhen Wangc28dccc2016-02-11 23:48:46 -0800315 // Measure the clock domain offset between camera and video/hw_composer
316 camera_metadata_entry timestampSource =
317 mDeviceInfo.find(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE);
318 if (timestampSource.count > 0 && timestampSource.data.u8[0] ==
319 ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME) {
320 mTimestampOffset = getMonoToBoottimeOffset();
321 }
322
Eino-Ville Talvalafd6ecdd2013-10-11 09:51:09 -0700323 // Will the HAL be sending in early partial result metadata?
Emilian Peev08dd2452017-04-06 16:55:14 +0100324 camera_metadata_entry partialResultsCount =
325 mDeviceInfo.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
326 if (partialResultsCount.count > 0) {
327 mNumPartialResults = partialResultsCount.data.i32[0];
328 mUsePartialResult = (mNumPartialResults > 1);
Eino-Ville Talvalafd6ecdd2013-10-11 09:51:09 -0700329 }
330
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700331 camera_metadata_entry configs =
332 mDeviceInfo.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
333 for (uint32_t i = 0; i < configs.count; i += 4) {
334 if (configs.data.i32[i] == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED &&
335 configs.data.i32[i + 3] ==
336 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT) {
337 mSupportedOpaqueInputSizes.add(Size(configs.data.i32[i + 1],
338 configs.data.i32[i + 2]));
339 }
340 }
341
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -0800342 bool usePrecorrectArray = DistortionMapper::isDistortionSupported(mDeviceInfo);
343 if (usePrecorrectArray) {
Shuzhen Wang4f6fa9d2019-03-29 10:40:35 -0700344 res = mDistortionMappers[mId.c_str()].setupStaticInfo(mDeviceInfo);
Eino-Ville Talvala7b8a1fd2018-05-22 15:30:35 -0700345 if (res != OK) {
346 SET_ERR_L("Unable to read necessary calibration fields for distortion correction");
347 return res;
348 }
349 }
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -0800350
Shuzhen Wang1c834da2019-12-18 11:17:03 -0800351 mZoomRatioMappers[mId.c_str()] = ZoomRatioMapper(&mDeviceInfo,
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -0800352 mSupportNativeZoomRatio, usePrecorrectArray);
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -0800353
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -0800354 if (RotateAndCropMapper::isNeeded(&mDeviceInfo)) {
355 mRotateAndCropMappers.emplace(mId.c_str(), &mDeviceInfo);
356 }
357
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800358 return OK;
359}
360
361status_t Camera3Device::disconnect() {
Yin-Chia Yehc5248132018-08-15 12:19:20 -0700362 return disconnectImpl();
363}
364
365status_t Camera3Device::disconnectImpl() {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800366 ATRACE_CALL();
Yin-Chia Yehe1c80632016-08-08 14:48:05 -0700367 ALOGI("%s: E", __FUNCTION__);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800368
Eino-Ville Talvala214a17f2013-06-13 12:20:02 -0700369 status_t res = OK;
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700370 std::vector<wp<Camera3StreamInterface>> streams;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700371 {
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800372 Mutex::Autolock il(mInterfaceLock);
373 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
374 {
375 Mutex::Autolock l(mLock);
376 if (mStatus == STATUS_UNINITIALIZED) return res;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700377
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800378 if (mStatus == STATUS_ACTIVE ||
379 (mStatus == STATUS_ERROR && mRequestThread != NULL)) {
380 res = mRequestThread->clearRepeatingRequests();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700381 if (res != OK) {
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800382 SET_ERR_L("Can't stop streaming");
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700383 // Continue to close device even in case of error
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800384 } else {
385 res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration);
386 if (res != OK) {
387 SET_ERR_L("Timeout waiting for HAL to drain (% " PRIi64 " ns)",
388 maxExpectedDuration);
389 // Continue to close device even in case of error
390 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700391 }
Eino-Ville Talvala214a17f2013-06-13 12:20:02 -0700392 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800393
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800394 if (mStatus == STATUS_ERROR) {
395 CLOGE("Shutting down in an error state");
396 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700397
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800398 if (mStatusTracker != NULL) {
399 mStatusTracker->requestExit();
400 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700401
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800402 if (mRequestThread != NULL) {
403 mRequestThread->requestExit();
404 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700405
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800406 streams.reserve(mOutputStreams.size() + (mInputStream != nullptr ? 1 : 0));
407 for (size_t i = 0; i < mOutputStreams.size(); i++) {
408 streams.push_back(mOutputStreams[i]);
409 }
410 if (mInputStream != nullptr) {
411 streams.push_back(mInputStream);
412 }
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700413 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700414 }
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800415 // Joining done without holding mLock and mInterfaceLock, otherwise deadlocks may ensue
416 // as the threads try to access parent state (b/143513518)
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700417 if (mRequestThread != NULL && mStatus != STATUS_ERROR) {
418 // HAL may be in a bad state, so waiting for request thread
419 // (which may be stuck in the HAL processCaptureRequest call)
420 // could be dangerous.
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800421 // give up mInterfaceLock here and then lock it again. Could this lead
422 // to other deadlocks
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700423 mRequestThread->join();
424 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700425 {
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800426 Mutex::Autolock il(mInterfaceLock);
427 if (mStatusTracker != NULL) {
428 mStatusTracker->join();
429 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800430
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800431 HalInterface* interface;
432 {
433 Mutex::Autolock l(mLock);
434 mRequestThread.clear();
435 Mutex::Autolock stLock(mTrackerLock);
436 mStatusTracker.clear();
437 interface = mInterface.get();
438 }
Eino-Ville Talvalaefff1c42015-08-28 16:27:27 -0700439
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800440 // Call close without internal mutex held, as the HAL close may need to
441 // wait on assorted callbacks,etc, to complete before it can return.
442 interface->close();
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700443
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800444 flushInflightRequests();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800445
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800446 {
447 Mutex::Autolock l(mLock);
448 mInterface->clear();
449 mOutputStreams.clear();
450 mInputStream.clear();
451 mDeletedStreams.clear();
452 mBufferManager.clear();
453 internalUpdateStatusLocked(STATUS_UNINITIALIZED);
454 }
455
456 for (auto& weakStream : streams) {
457 sp<Camera3StreamInterface> stream = weakStream.promote();
458 if (stream != nullptr) {
459 ALOGE("%s: Stream %d leaked! strong reference (%d)!",
460 __FUNCTION__, stream->getId(), stream->getStrongCount() - 1);
461 }
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700462 }
463 }
Yin-Chia Yehe1c80632016-08-08 14:48:05 -0700464 ALOGI("%s: X", __FUNCTION__);
Eino-Ville Talvala214a17f2013-06-13 12:20:02 -0700465 return res;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800466}
467
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700468// For dumping/debugging only -
469// try to acquire a lock a few times, eventually give up to proceed with
470// debug/dump operations
471bool Camera3Device::tryLockSpinRightRound(Mutex& lock) {
472 bool gotLock = false;
473 for (size_t i = 0; i < kDumpLockAttempts; ++i) {
474 if (lock.tryLock() == NO_ERROR) {
475 gotLock = true;
476 break;
477 } else {
478 usleep(kDumpSleepDuration);
479 }
480 }
481 return gotLock;
482}
483
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700484Camera3Device::Size Camera3Device::getMaxJpegResolution() const {
485 int32_t maxJpegWidth = 0, maxJpegHeight = 0;
Emilian Peev08dd2452017-04-06 16:55:14 +0100486 const int STREAM_CONFIGURATION_SIZE = 4;
487 const int STREAM_FORMAT_OFFSET = 0;
488 const int STREAM_WIDTH_OFFSET = 1;
489 const int STREAM_HEIGHT_OFFSET = 2;
490 const int STREAM_IS_INPUT_OFFSET = 3;
491 camera_metadata_ro_entry_t availableStreamConfigs =
492 mDeviceInfo.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
493 if (availableStreamConfigs.count == 0 ||
494 availableStreamConfigs.count % STREAM_CONFIGURATION_SIZE != 0) {
495 return Size(0, 0);
496 }
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700497
Emilian Peev08dd2452017-04-06 16:55:14 +0100498 // Get max jpeg size (area-wise).
499 for (size_t i=0; i < availableStreamConfigs.count; i+= STREAM_CONFIGURATION_SIZE) {
500 int32_t format = availableStreamConfigs.data.i32[i + STREAM_FORMAT_OFFSET];
501 int32_t width = availableStreamConfigs.data.i32[i + STREAM_WIDTH_OFFSET];
502 int32_t height = availableStreamConfigs.data.i32[i + STREAM_HEIGHT_OFFSET];
503 int32_t isInput = availableStreamConfigs.data.i32[i + STREAM_IS_INPUT_OFFSET];
504 if (isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT
505 && format == HAL_PIXEL_FORMAT_BLOB &&
506 (width * height > maxJpegWidth * maxJpegHeight)) {
507 maxJpegWidth = width;
508 maxJpegHeight = height;
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700509 }
510 }
Emilian Peev08dd2452017-04-06 16:55:14 +0100511
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700512 return Size(maxJpegWidth, maxJpegHeight);
513}
514
Shuzhen Wangc28dccc2016-02-11 23:48:46 -0800515nsecs_t Camera3Device::getMonoToBoottimeOffset() {
516 // try three times to get the clock offset, choose the one
517 // with the minimum gap in measurements.
518 const int tries = 3;
519 nsecs_t bestGap, measured;
520 for (int i = 0; i < tries; ++i) {
521 const nsecs_t tmono = systemTime(SYSTEM_TIME_MONOTONIC);
522 const nsecs_t tbase = systemTime(SYSTEM_TIME_BOOTTIME);
523 const nsecs_t tmono2 = systemTime(SYSTEM_TIME_MONOTONIC);
524 const nsecs_t gap = tmono2 - tmono;
525 if (i == 0 || gap < bestGap) {
526 bestGap = gap;
527 measured = tbase - ((tmono + tmono2) >> 1);
528 }
529 }
530 return measured;
531}
532
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800533hardware::graphics::common::V1_0::PixelFormat Camera3Device::mapToPixelFormat(
534 int frameworkFormat) {
535 return (hardware::graphics::common::V1_0::PixelFormat) frameworkFormat;
536}
537
538DataspaceFlags Camera3Device::mapToHidlDataspace(
539 android_dataspace dataSpace) {
540 return dataSpace;
541}
542
Chia-I Wu67a0c0e2017-04-06 13:37:01 -0700543BufferUsageFlags Camera3Device::mapToConsumerUsage(
Emilian Peev050f5dc2017-05-18 14:43:56 +0100544 uint64_t usage) {
Yin-Chia Yeh47cf8e62017-04-04 13:00:03 -0700545 return usage;
546}
547
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800548StreamRotation Camera3Device::mapToStreamRotation(camera3_stream_rotation_t rotation) {
549 switch (rotation) {
550 case CAMERA3_STREAM_ROTATION_0:
551 return StreamRotation::ROTATION_0;
552 case CAMERA3_STREAM_ROTATION_90:
553 return StreamRotation::ROTATION_90;
554 case CAMERA3_STREAM_ROTATION_180:
555 return StreamRotation::ROTATION_180;
556 case CAMERA3_STREAM_ROTATION_270:
557 return StreamRotation::ROTATION_270;
558 }
559 ALOGE("%s: Unknown stream rotation %d", __FUNCTION__, rotation);
560 return StreamRotation::ROTATION_0;
561}
562
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -0800563status_t Camera3Device::mapToStreamConfigurationMode(
564 camera3_stream_configuration_mode_t operationMode, StreamConfigurationMode *mode) {
565 if (mode == nullptr) return BAD_VALUE;
566 if (operationMode < CAMERA3_VENDOR_STREAM_CONFIGURATION_MODE_START) {
567 switch(operationMode) {
568 case CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE:
569 *mode = StreamConfigurationMode::NORMAL_MODE;
570 break;
571 case CAMERA3_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE:
572 *mode = StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE;
573 break;
574 default:
575 ALOGE("%s: Unknown stream configuration mode %d", __FUNCTION__, operationMode);
576 return BAD_VALUE;
577 }
578 } else {
579 *mode = static_cast<StreamConfigurationMode>(operationMode);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800580 }
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -0800581 return OK;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800582}
583
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800584int Camera3Device::mapToFrameworkFormat(
585 hardware::graphics::common::V1_0::PixelFormat pixelFormat) {
586 return static_cast<uint32_t>(pixelFormat);
587}
588
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -0700589android_dataspace Camera3Device::mapToFrameworkDataspace(
590 DataspaceFlags dataSpace) {
591 return static_cast<android_dataspace>(dataSpace);
592}
593
Emilian Peev050f5dc2017-05-18 14:43:56 +0100594uint64_t Camera3Device::mapConsumerToFrameworkUsage(
Chia-I Wu67a0c0e2017-04-06 13:37:01 -0700595 BufferUsageFlags usage) {
Yin-Chia Yeh47cf8e62017-04-04 13:00:03 -0700596 return usage;
597}
598
Emilian Peev050f5dc2017-05-18 14:43:56 +0100599uint64_t Camera3Device::mapProducerToFrameworkUsage(
Chia-I Wu67a0c0e2017-04-06 13:37:01 -0700600 BufferUsageFlags usage) {
Yin-Chia Yeh47cf8e62017-04-04 13:00:03 -0700601 return usage;
602}
603
Zhijun Hef7da0962014-04-24 13:27:56 -0700604ssize_t Camera3Device::getJpegBufferSize(uint32_t width, uint32_t height) const {
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700605 // Get max jpeg size (area-wise).
606 Size maxJpegResolution = getMaxJpegResolution();
607 if (maxJpegResolution.width == 0) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800608 ALOGE("%s: Camera %s: Can't find valid available jpeg sizes in static metadata!",
609 __FUNCTION__, mId.string());
Zhijun Hef7da0962014-04-24 13:27:56 -0700610 return BAD_VALUE;
611 }
612
Zhijun Hef7da0962014-04-24 13:27:56 -0700613 // Get max jpeg buffer size
614 ssize_t maxJpegBufferSize = 0;
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700615 camera_metadata_ro_entry jpegBufMaxSize = mDeviceInfo.find(ANDROID_JPEG_MAX_SIZE);
616 if (jpegBufMaxSize.count == 0) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800617 ALOGE("%s: Camera %s: Can't find maximum JPEG size in static metadata!", __FUNCTION__,
618 mId.string());
Zhijun Hef7da0962014-04-24 13:27:56 -0700619 return BAD_VALUE;
620 }
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700621 maxJpegBufferSize = jpegBufMaxSize.data.i32[0];
Yin-Chia Yeh0c4e56d2015-01-09 15:21:27 -0800622 assert(kMinJpegBufferSize < maxJpegBufferSize);
Zhijun Hef7da0962014-04-24 13:27:56 -0700623
624 // Calculate final jpeg buffer size for the given resolution.
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700625 float scaleFactor = ((float) (width * height)) /
626 (maxJpegResolution.width * maxJpegResolution.height);
Yin-Chia Yeh0c4e56d2015-01-09 15:21:27 -0800627 ssize_t jpegBufferSize = scaleFactor * (maxJpegBufferSize - kMinJpegBufferSize) +
628 kMinJpegBufferSize;
Zhijun Hef7da0962014-04-24 13:27:56 -0700629 if (jpegBufferSize > maxJpegBufferSize) {
630 jpegBufferSize = maxJpegBufferSize;
Zhijun Hef7da0962014-04-24 13:27:56 -0700631 }
632
633 return jpegBufferSize;
634}
635
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -0700636ssize_t Camera3Device::getPointCloudBufferSize() const {
637 const int FLOATS_PER_POINT=4;
638 camera_metadata_ro_entry maxPointCount = mDeviceInfo.find(ANDROID_DEPTH_MAX_DEPTH_SAMPLES);
639 if (maxPointCount.count == 0) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800640 ALOGE("%s: Camera %s: Can't find maximum depth point cloud size in static metadata!",
641 __FUNCTION__, mId.string());
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -0700642 return BAD_VALUE;
643 }
644 ssize_t maxBytesForPointCloud = sizeof(android_depth_points) +
645 maxPointCount.data.i32[0] * sizeof(float) * FLOATS_PER_POINT;
646 return maxBytesForPointCloud;
647}
648
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800649ssize_t Camera3Device::getRawOpaqueBufferSize(int32_t width, int32_t height) const {
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800650 const int PER_CONFIGURATION_SIZE = 3;
651 const int WIDTH_OFFSET = 0;
652 const int HEIGHT_OFFSET = 1;
653 const int SIZE_OFFSET = 2;
654 camera_metadata_ro_entry rawOpaqueSizes =
655 mDeviceInfo.find(ANDROID_SENSOR_OPAQUE_RAW_SIZE);
Aurimas Liutikasbc57b122016-02-16 09:59:16 -0800656 size_t count = rawOpaqueSizes.count;
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800657 if (count == 0 || (count % PER_CONFIGURATION_SIZE)) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800658 ALOGE("%s: Camera %s: bad opaque RAW size static metadata length(%zu)!",
659 __FUNCTION__, mId.string(), count);
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800660 return BAD_VALUE;
661 }
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -0700662
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800663 for (size_t i = 0; i < count; i += PER_CONFIGURATION_SIZE) {
664 if (width == rawOpaqueSizes.data.i32[i + WIDTH_OFFSET] &&
665 height == rawOpaqueSizes.data.i32[i + HEIGHT_OFFSET]) {
666 return rawOpaqueSizes.data.i32[i + SIZE_OFFSET];
667 }
668 }
669
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800670 ALOGE("%s: Camera %s: cannot find size for %dx%d opaque RAW image!",
671 __FUNCTION__, mId.string(), width, height);
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800672 return BAD_VALUE;
673}
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -0700674
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800675status_t Camera3Device::dump(int fd, const Vector<String16> &args) {
676 ATRACE_CALL();
677 (void)args;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700678
679 // Try to lock, but continue in case of failure (to avoid blocking in
680 // deadlocks)
681 bool gotInterfaceLock = tryLockSpinRightRound(mInterfaceLock);
682 bool gotLock = tryLockSpinRightRound(mLock);
683
684 ALOGW_IF(!gotInterfaceLock,
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800685 "Camera %s: %s: Unable to lock interface lock, proceeding anyway",
686 mId.string(), __FUNCTION__);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700687 ALOGW_IF(!gotLock,
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800688 "Camera %s: %s: Unable to lock main lock, proceeding anyway",
689 mId.string(), __FUNCTION__);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700690
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800691 bool dumpTemplates = false;
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700692
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800693 String16 templatesOption("-t");
694 int n = args.size();
695 for (int i = 0; i < n; i++) {
696 if (args[i] == templatesOption) {
697 dumpTemplates = true;
698 }
Emilian Peevbd8c5032018-02-14 23:05:40 +0000699 if (args[i] == TagMonitor::kMonitorOption) {
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700700 if (i + 1 < n) {
701 String8 monitorTags = String8(args[i + 1]);
702 if (monitorTags == "off") {
703 mTagMonitor.disableMonitoring();
704 } else {
705 mTagMonitor.parseTagsToMonitor(monitorTags);
706 }
707 } else {
708 mTagMonitor.disableMonitoring();
709 }
710 }
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800711 }
712
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800713 String8 lines;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800714
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800715 const char *status =
716 mStatus == STATUS_ERROR ? "ERROR" :
717 mStatus == STATUS_UNINITIALIZED ? "UNINITIALIZED" :
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700718 mStatus == STATUS_UNCONFIGURED ? "UNCONFIGURED" :
719 mStatus == STATUS_CONFIGURED ? "CONFIGURED" :
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800720 mStatus == STATUS_ACTIVE ? "ACTIVE" :
721 "Unknown";
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700722
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800723 lines.appendFormat(" Device status: %s\n", status);
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -0700724 if (mStatus == STATUS_ERROR) {
725 lines.appendFormat(" Error cause: %s\n", mErrorCause.string());
726 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800727 lines.appendFormat(" Stream configuration:\n");
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -0800728 const char *mode =
729 mOperatingMode == static_cast<int>(StreamConfigurationMode::NORMAL_MODE) ? "NORMAL" :
730 mOperatingMode == static_cast<int>(
731 StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE) ? "CONSTRAINED_HIGH_SPEED" :
732 "CUSTOM";
733 lines.appendFormat(" Operation mode: %s (%d) \n", mode, mOperatingMode);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800734
735 if (mInputStream != NULL) {
736 write(fd, lines.string(), lines.size());
737 mInputStream->dump(fd, args);
738 } else {
739 lines.appendFormat(" No input stream.\n");
740 write(fd, lines.string(), lines.size());
741 }
742 for (size_t i = 0; i < mOutputStreams.size(); i++) {
743 mOutputStreams[i]->dump(fd,args);
744 }
745
Zhijun He431503c2016-03-07 17:30:16 -0800746 if (mBufferManager != NULL) {
747 lines = String8(" Camera3 Buffer Manager:\n");
748 write(fd, lines.string(), lines.size());
749 mBufferManager->dump(fd, args);
750 }
Zhijun He125684a2015-12-26 15:07:30 -0800751
Eino-Ville Talvala42368d92013-04-09 14:13:50 -0700752 lines = String8(" In-flight requests:\n");
753 if (mInFlightMap.size() == 0) {
754 lines.append(" None\n");
755 } else {
756 for (size_t i = 0; i < mInFlightMap.size(); i++) {
757 InFlightRequest r = mInFlightMap.valueAt(i);
Colin Crosse5729fa2014-03-21 15:04:25 -0700758 lines.appendFormat(" Frame %d | Timestamp: %" PRId64 ", metadata"
Eino-Ville Talvala42368d92013-04-09 14:13:50 -0700759 " arrived: %s, buffers left: %d\n", mInFlightMap.keyAt(i),
Chien-Yu Chen43e69a62014-11-25 16:38:33 -0800760 r.shutterTimestamp, r.haveResultMetadata ? "true" : "false",
Eino-Ville Talvala42368d92013-04-09 14:13:50 -0700761 r.numBuffersLeft);
762 }
763 }
764 write(fd, lines.string(), lines.size());
765
Shuzhen Wang686f6442017-06-20 16:16:04 -0700766 if (mRequestThread != NULL) {
767 mRequestThread->dumpCaptureRequestLatency(fd,
768 " ProcessCaptureRequest latency histogram:");
769 }
770
Igor Murashkin1e479c02013-09-06 16:55:14 -0700771 {
772 lines = String8(" Last request sent:\n");
773 write(fd, lines.string(), lines.size());
774
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700775 CameraMetadata lastRequest = getLatestRequestLocked();
Igor Murashkin1e479c02013-09-06 16:55:14 -0700776 lastRequest.dump(fd, /*verbosity*/2, /*indentation*/6);
777 }
778
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800779 if (dumpTemplates) {
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -0800780 const char *templateNames[CAMERA3_TEMPLATE_COUNT] = {
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800781 "TEMPLATE_PREVIEW",
782 "TEMPLATE_STILL_CAPTURE",
783 "TEMPLATE_VIDEO_RECORD",
784 "TEMPLATE_VIDEO_SNAPSHOT",
785 "TEMPLATE_ZERO_SHUTTER_LAG",
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -0800786 "TEMPLATE_MANUAL",
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800787 };
788
789 for (int i = 1; i < CAMERA3_TEMPLATE_COUNT; i++) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800790 camera_metadata_t *templateRequest = nullptr;
791 mInterface->constructDefaultRequestSettings(
792 (camera3_request_template_t) i, &templateRequest);
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800793 lines = String8::format(" HAL Request %s:\n", templateNames[i-1]);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800794 if (templateRequest == nullptr) {
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800795 lines.append(" Not supported\n");
796 write(fd, lines.string(), lines.size());
797 } else {
798 write(fd, lines.string(), lines.size());
799 dump_indented_camera_metadata(templateRequest,
800 fd, /*verbosity*/2, /*indentation*/8);
801 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800802 free_camera_metadata(templateRequest);
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800803 }
804 }
805
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700806 mTagMonitor.dumpMonitoredMetadata(fd);
807
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800808 if (mInterface->valid()) {
Eino-Ville Talvalad00111e2017-01-31 11:59:12 -0800809 lines = String8(" HAL device dump:\n");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800810 write(fd, lines.string(), lines.size());
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800811 mInterface->dump(fd);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800812 }
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800813
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700814 if (gotLock) mLock.unlock();
815 if (gotInterfaceLock) mInterfaceLock.unlock();
816
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800817 return OK;
818}
819
Emilian Peevfaa4bde2020-01-23 12:19:37 -0800820const CameraMetadata& Camera3Device::infoPhysical(const String8& physicalId) const {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800821 ALOGVV("%s: E", __FUNCTION__);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800822 if (CC_UNLIKELY(mStatus == STATUS_UNINITIALIZED ||
823 mStatus == STATUS_ERROR)) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -0700824 ALOGW("%s: Access to static info %s!", __FUNCTION__,
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800825 mStatus == STATUS_ERROR ?
826 "when in error state" : "before init");
827 }
Shuzhen Wang2e7f58f2018-07-11 14:00:29 -0700828 if (physicalId.isEmpty()) {
829 return mDeviceInfo;
830 } else {
831 std::string id(physicalId.c_str());
832 if (mPhysicalDeviceInfoMap.find(id) != mPhysicalDeviceInfoMap.end()) {
833 return mPhysicalDeviceInfoMap.at(id);
834 } else {
835 ALOGE("%s: Invalid physical camera id %s", __FUNCTION__, physicalId.c_str());
836 return mDeviceInfo;
837 }
838 }
839}
840
841const CameraMetadata& Camera3Device::info() const {
842 String8 emptyId;
Emilian Peevfaa4bde2020-01-23 12:19:37 -0800843 return infoPhysical(emptyId);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800844}
845
Jianing Wei90e59c92014-03-12 18:29:36 -0700846status_t Camera3Device::checkStatusOkToCaptureLocked() {
847 switch (mStatus) {
848 case STATUS_ERROR:
849 CLOGE("Device has encountered a serious error");
850 return INVALID_OPERATION;
851 case STATUS_UNINITIALIZED:
852 CLOGE("Device not initialized");
853 return INVALID_OPERATION;
854 case STATUS_UNCONFIGURED:
855 case STATUS_CONFIGURED:
856 case STATUS_ACTIVE:
857 // OK
858 break;
859 default:
860 SET_ERR_L("Unexpected status: %d", mStatus);
861 return INVALID_OPERATION;
862 }
863 return OK;
864}
865
866status_t Camera3Device::convertMetadataListToRequestListLocked(
Emilian Peevaebbe412018-01-15 13:53:24 +0000867 const List<const PhysicalCameraSettingsList> &metadataList,
Shuzhen Wang0129d522016-10-30 22:43:41 -0700868 const std::list<const SurfaceMap> &surfaceMaps,
869 bool repeating,
Shuzhen Wang9d066012016-09-30 11:30:20 -0700870 RequestList *requestList) {
Jianing Wei90e59c92014-03-12 18:29:36 -0700871 if (requestList == NULL) {
872 CLOGE("requestList cannot be NULL.");
873 return BAD_VALUE;
874 }
875
Jianing Weicb0652e2014-03-12 18:29:36 -0700876 int32_t burstId = 0;
Emilian Peevaebbe412018-01-15 13:53:24 +0000877 List<const PhysicalCameraSettingsList>::const_iterator metadataIt = metadataList.begin();
Shuzhen Wang0129d522016-10-30 22:43:41 -0700878 std::list<const SurfaceMap>::const_iterator surfaceMapIt = surfaceMaps.begin();
879 for (; metadataIt != metadataList.end() && surfaceMapIt != surfaceMaps.end();
880 ++metadataIt, ++surfaceMapIt) {
881 sp<CaptureRequest> newRequest = setUpRequestLocked(*metadataIt, *surfaceMapIt);
Jianing Wei90e59c92014-03-12 18:29:36 -0700882 if (newRequest == 0) {
883 CLOGE("Can't create capture request");
884 return BAD_VALUE;
885 }
Jianing Weicb0652e2014-03-12 18:29:36 -0700886
Shuzhen Wang9d066012016-09-30 11:30:20 -0700887 newRequest->mRepeating = repeating;
888
Jianing Weicb0652e2014-03-12 18:29:36 -0700889 // Setup burst Id and request Id
890 newRequest->mResultExtras.burstId = burstId++;
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -0800891 auto requestIdEntry = metadataIt->begin()->metadata.find(ANDROID_REQUEST_ID);
892 if (requestIdEntry.count == 0) {
Jianing Weicb0652e2014-03-12 18:29:36 -0700893 CLOGE("RequestID does not exist in metadata");
894 return BAD_VALUE;
895 }
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -0800896 newRequest->mResultExtras.requestId = requestIdEntry.data.i32[0];
Jianing Weicb0652e2014-03-12 18:29:36 -0700897
Jianing Wei90e59c92014-03-12 18:29:36 -0700898 requestList->push_back(newRequest);
Jianing Wei2d6bb3f2014-04-11 10:00:31 -0700899
900 ALOGV("%s: requestId = %" PRId32, __FUNCTION__, newRequest->mResultExtras.requestId);
Jianing Wei90e59c92014-03-12 18:29:36 -0700901 }
Shuzhen Wang0129d522016-10-30 22:43:41 -0700902 if (metadataIt != metadataList.end() || surfaceMapIt != surfaceMaps.end()) {
903 ALOGE("%s: metadataList and surfaceMaps are not the same size!", __FUNCTION__);
904 return BAD_VALUE;
905 }
Chien-Yu Chen85a64552015-08-28 15:46:12 -0700906
907 // Setup batch size if this is a high speed video recording request.
908 if (mIsConstrainedHighSpeedConfiguration && requestList->size() > 0) {
909 auto firstRequest = requestList->begin();
910 for (auto& outputStream : (*firstRequest)->mOutputStreams) {
911 if (outputStream->isVideoStream()) {
912 (*firstRequest)->mBatchSize = requestList->size();
913 break;
914 }
915 }
916 }
917
Jianing Wei90e59c92014-03-12 18:29:36 -0700918 return OK;
919}
920
Yin-Chia Yeh7e5a2042019-02-06 16:01:06 -0800921status_t Camera3Device::capture(CameraMetadata &request, int64_t* lastFrameNumber) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800922 ATRACE_CALL();
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800923
Emilian Peevaebbe412018-01-15 13:53:24 +0000924 List<const PhysicalCameraSettingsList> requestsList;
Shuzhen Wang0129d522016-10-30 22:43:41 -0700925 std::list<const SurfaceMap> surfaceMaps;
Emilian Peevaebbe412018-01-15 13:53:24 +0000926 convertToRequestList(requestsList, surfaceMaps, request);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700927
Yin-Chia Yeh7e5a2042019-02-06 16:01:06 -0800928 return captureList(requestsList, surfaceMaps, lastFrameNumber);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700929}
930
Emilian Peevaebbe412018-01-15 13:53:24 +0000931void Camera3Device::convertToRequestList(List<const PhysicalCameraSettingsList>& requestsList,
Shuzhen Wang0129d522016-10-30 22:43:41 -0700932 std::list<const SurfaceMap>& surfaceMaps,
933 const CameraMetadata& request) {
Emilian Peevaebbe412018-01-15 13:53:24 +0000934 PhysicalCameraSettingsList requestList;
935 requestList.push_back({std::string(getId().string()), request});
936 requestsList.push_back(requestList);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700937
938 SurfaceMap surfaceMap;
939 camera_metadata_ro_entry streams = request.find(ANDROID_REQUEST_OUTPUT_STREAMS);
940 // With no surface list passed in, stream and surface will have 1-to-1
941 // mapping. So the surface index is 0 for each stream in the surfaceMap.
942 for (size_t i = 0; i < streams.count; i++) {
943 surfaceMap[streams.data.i32[i]].push_back(0);
944 }
945 surfaceMaps.push_back(surfaceMap);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800946}
947
Jianing Wei90e59c92014-03-12 18:29:36 -0700948status_t Camera3Device::submitRequestsHelper(
Emilian Peevaebbe412018-01-15 13:53:24 +0000949 const List<const PhysicalCameraSettingsList> &requests,
Shuzhen Wang0129d522016-10-30 22:43:41 -0700950 const std::list<const SurfaceMap> &surfaceMaps,
951 bool repeating,
Jianing Wei2d6bb3f2014-04-11 10:00:31 -0700952 /*out*/
953 int64_t *lastFrameNumber) {
Jianing Wei90e59c92014-03-12 18:29:36 -0700954 ATRACE_CALL();
955 Mutex::Autolock il(mInterfaceLock);
956 Mutex::Autolock l(mLock);
957
958 status_t res = checkStatusOkToCaptureLocked();
959 if (res != OK) {
960 // error logged by previous call
961 return res;
962 }
963
964 RequestList requestList;
965
Shuzhen Wang0129d522016-10-30 22:43:41 -0700966 res = convertMetadataListToRequestListLocked(requests, surfaceMaps,
967 repeating, /*out*/&requestList);
Jianing Wei90e59c92014-03-12 18:29:36 -0700968 if (res != OK) {
969 // error logged by previous call
970 return res;
971 }
972
973 if (repeating) {
Jianing Wei2d6bb3f2014-04-11 10:00:31 -0700974 res = mRequestThread->setRepeatingRequests(requestList, lastFrameNumber);
Jianing Wei90e59c92014-03-12 18:29:36 -0700975 } else {
Jianing Wei2d6bb3f2014-04-11 10:00:31 -0700976 res = mRequestThread->queueRequestList(requestList, lastFrameNumber);
Jianing Wei90e59c92014-03-12 18:29:36 -0700977 }
978
979 if (res == OK) {
980 waitUntilStateThenRelock(/*active*/true, kActiveTimeout);
981 if (res != OK) {
982 SET_ERR_L("Can't transition to active in %f seconds!",
983 kActiveTimeout/1e9);
984 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800985 ALOGV("Camera %s: Capture request %" PRId32 " enqueued", mId.string(),
Jianing Wei2d6bb3f2014-04-11 10:00:31 -0700986 (*(requestList.begin()))->mResultExtras.requestId);
Jianing Wei90e59c92014-03-12 18:29:36 -0700987 } else {
988 CLOGE("Cannot queue request. Impossible.");
989 return BAD_VALUE;
990 }
991
992 return res;
993}
994
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -0700995hardware::Return<void> Camera3Device::requestStreamBuffers(
996 const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& bufReqs,
997 requestStreamBuffers_cb _hidl_cb) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800998 RequestBufferStates states {
999 mId, mRequestBufferInterfaceLock, mUseHalBufManager, mOutputStreams,
1000 *this, *mInterface, *this};
1001 camera3::requestStreamBuffers(states, bufReqs, _hidl_cb);
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07001002 return hardware::Void();
1003}
1004
1005hardware::Return<void> Camera3Device::returnStreamBuffers(
1006 const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer>& buffers) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001007 ReturnBufferStates states {
1008 mId, mUseHalBufManager, mOutputStreams, *mInterface};
1009 camera3::returnStreamBuffers(states, buffers);
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07001010 return hardware::Void();
1011}
1012
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001013hardware::Return<void> Camera3Device::processCaptureResult_3_4(
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001014 const hardware::hidl_vec<
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001015 hardware::camera::device::V3_4::CaptureResult>& results) {
Yin-Chia Yeh657c1872017-07-18 18:09:57 -07001016 // Ideally we should grab mLock, but that can lead to deadlock, and
1017 // it's not super important to get up to date value of mStatus for this
1018 // warning print, hence skipping the lock here
1019 if (mStatus == STATUS_ERROR) {
1020 // Per API contract, HAL should act as closed after device error
1021 // But mStatus can be set to error by framework as well, so just log
1022 // a warning here.
1023 ALOGW("%s: received capture result in error state.", __FUNCTION__);
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07001024 }
Yifan Honga640c5a2017-04-12 16:30:31 -07001025
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001026 sp<NotificationListener> listener;
1027 {
1028 std::lock_guard<std::mutex> l(mOutputLock);
1029 listener = mListener.promote();
1030 }
1031
Yifan Honga640c5a2017-04-12 16:30:31 -07001032 if (mProcessCaptureResultLock.tryLock() != OK) {
1033 // This should never happen; it indicates a wrong client implementation
1034 // that doesn't follow the contract. But, we can be tolerant here.
1035 ALOGE("%s: callback overlapped! waiting 1s...",
1036 __FUNCTION__);
1037 if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
1038 ALOGE("%s: cannot acquire lock in 1s, dropping results",
1039 __FUNCTION__);
1040 // really don't know what to do, so bail out.
1041 return hardware::Void();
1042 }
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001043 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001044 CaptureOutputStates states {
1045 mId,
1046 mInFlightLock, mInFlightMap,
1047 mOutputLock, mResultQueue, mResultSignal,
1048 mNextShutterFrameNumber,
1049 mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
1050 mNextResultFrameNumber,
1051 mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
1052 mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
1053 mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08001054 mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
1055 mTagMonitor, mInputStream, mOutputStreams, listener, *this, *this, *mInterface
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001056 };
1057
Yifan Honga640c5a2017-04-12 16:30:31 -07001058 for (const auto& result : results) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001059 processOneCaptureResultLocked(states, result.v3_2, result.physicalCameraMetadata);
Yifan Honga640c5a2017-04-12 16:30:31 -07001060 }
1061 mProcessCaptureResultLock.unlock();
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001062 return hardware::Void();
1063}
1064
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001065// Only one processCaptureResult should be called at a time, so
1066// the locks won't block. The locks are present here simply to enforce this.
1067hardware::Return<void> Camera3Device::processCaptureResult(
1068 const hardware::hidl_vec<
1069 hardware::camera::device::V3_2::CaptureResult>& results) {
1070 hardware::hidl_vec<hardware::camera::device::V3_4::PhysicalCameraMetadata> noPhysMetadata;
1071
1072 // Ideally we should grab mLock, but that can lead to deadlock, and
1073 // it's not super important to get up to date value of mStatus for this
1074 // warning print, hence skipping the lock here
1075 if (mStatus == STATUS_ERROR) {
1076 // Per API contract, HAL should act as closed after device error
1077 // But mStatus can be set to error by framework as well, so just log
1078 // a warning here.
1079 ALOGW("%s: received capture result in error state.", __FUNCTION__);
1080 }
1081
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001082 sp<NotificationListener> listener;
1083 {
1084 std::lock_guard<std::mutex> l(mOutputLock);
1085 listener = mListener.promote();
1086 }
1087
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001088 if (mProcessCaptureResultLock.tryLock() != OK) {
1089 // This should never happen; it indicates a wrong client implementation
1090 // that doesn't follow the contract. But, we can be tolerant here.
1091 ALOGE("%s: callback overlapped! waiting 1s...",
1092 __FUNCTION__);
1093 if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
1094 ALOGE("%s: cannot acquire lock in 1s, dropping results",
1095 __FUNCTION__);
1096 // really don't know what to do, so bail out.
1097 return hardware::Void();
1098 }
1099 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001100
1101 CaptureOutputStates states {
1102 mId,
1103 mInFlightLock, mInFlightMap,
1104 mOutputLock, mResultQueue, mResultSignal,
1105 mNextShutterFrameNumber,
1106 mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
1107 mNextResultFrameNumber,
1108 mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
1109 mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
1110 mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08001111 mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
1112 mTagMonitor, mInputStream, mOutputStreams, listener, *this, *this, *mInterface
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001113 };
1114
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001115 for (const auto& result : results) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001116 processOneCaptureResultLocked(states, result, noPhysMetadata);
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001117 }
1118 mProcessCaptureResultLock.unlock();
1119 return hardware::Void();
1120}
1121
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001122hardware::Return<void> Camera3Device::notify(
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001123 const hardware::hidl_vec<hardware::camera::device::V3_2::NotifyMsg>& msgs) {
Yin-Chia Yeh657c1872017-07-18 18:09:57 -07001124 // Ideally we should grab mLock, but that can lead to deadlock, and
1125 // it's not super important to get up to date value of mStatus for this
1126 // warning print, hence skipping the lock here
1127 if (mStatus == STATUS_ERROR) {
1128 // Per API contract, HAL should act as closed after device error
1129 // But mStatus can be set to error by framework as well, so just log
1130 // a warning here.
1131 ALOGW("%s: received notify message in error state.", __FUNCTION__);
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07001132 }
Yin-Chia Yeh657c1872017-07-18 18:09:57 -07001133
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001134 sp<NotificationListener> listener;
1135 {
1136 std::lock_guard<std::mutex> l(mOutputLock);
1137 listener = mListener.promote();
1138 }
1139
1140 CaptureOutputStates states {
1141 mId,
1142 mInFlightLock, mInFlightMap,
1143 mOutputLock, mResultQueue, mResultSignal,
1144 mNextShutterFrameNumber,
1145 mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
1146 mNextResultFrameNumber,
1147 mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
1148 mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
1149 mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08001150 mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
1151 mTagMonitor, mInputStream, mOutputStreams, listener, *this, *this, *mInterface
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001152 };
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001153 for (const auto& msg : msgs) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001154 camera3::notify(states, msg);
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001155 }
1156 return hardware::Void();
1157}
1158
Emilian Peevaebbe412018-01-15 13:53:24 +00001159status_t Camera3Device::captureList(const List<const PhysicalCameraSettingsList> &requestsList,
Shuzhen Wang0129d522016-10-30 22:43:41 -07001160 const std::list<const SurfaceMap> &surfaceMaps,
Jianing Weicb0652e2014-03-12 18:29:36 -07001161 int64_t *lastFrameNumber) {
Jianing Wei90e59c92014-03-12 18:29:36 -07001162 ATRACE_CALL();
1163
Emilian Peevaebbe412018-01-15 13:53:24 +00001164 return submitRequestsHelper(requestsList, surfaceMaps, /*repeating*/false, lastFrameNumber);
Jianing Wei90e59c92014-03-12 18:29:36 -07001165}
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001166
Jianing Weicb0652e2014-03-12 18:29:36 -07001167status_t Camera3Device::setStreamingRequest(const CameraMetadata &request,
1168 int64_t* /*lastFrameNumber*/) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001169 ATRACE_CALL();
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001170
Emilian Peevaebbe412018-01-15 13:53:24 +00001171 List<const PhysicalCameraSettingsList> requestsList;
Shuzhen Wang0129d522016-10-30 22:43:41 -07001172 std::list<const SurfaceMap> surfaceMaps;
Emilian Peevaebbe412018-01-15 13:53:24 +00001173 convertToRequestList(requestsList, surfaceMaps, request);
Shuzhen Wang0129d522016-10-30 22:43:41 -07001174
Emilian Peevaebbe412018-01-15 13:53:24 +00001175 return setStreamingRequestList(requestsList, /*surfaceMap*/surfaceMaps,
Shuzhen Wang0129d522016-10-30 22:43:41 -07001176 /*lastFrameNumber*/NULL);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001177}
1178
Emilian Peevaebbe412018-01-15 13:53:24 +00001179status_t Camera3Device::setStreamingRequestList(
1180 const List<const PhysicalCameraSettingsList> &requestsList,
1181 const std::list<const SurfaceMap> &surfaceMaps, int64_t *lastFrameNumber) {
Jianing Wei90e59c92014-03-12 18:29:36 -07001182 ATRACE_CALL();
1183
Emilian Peevaebbe412018-01-15 13:53:24 +00001184 return submitRequestsHelper(requestsList, surfaceMaps, /*repeating*/true, lastFrameNumber);
Jianing Wei90e59c92014-03-12 18:29:36 -07001185}
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001186
1187sp<Camera3Device::CaptureRequest> Camera3Device::setUpRequestLocked(
Emilian Peevaebbe412018-01-15 13:53:24 +00001188 const PhysicalCameraSettingsList &request, const SurfaceMap &surfaceMap) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001189 status_t res;
1190
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001191 if (mStatus == STATUS_UNCONFIGURED || mNeedConfig) {
Eino-Ville Talvalae7091aa2017-03-07 15:23:06 -08001192 // This point should only be reached via API1 (API2 must explicitly call configureStreams)
1193 // so unilaterally select normal operating mode.
Emilian Peevaebbe412018-01-15 13:53:24 +00001194 res = filterParamsAndConfigureLocked(request.begin()->metadata,
1195 CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE);
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07001196 // Stream configuration failed. Client might try other configuraitons.
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001197 if (res != OK) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07001198 CLOGE("Can't set up streams: %s (%d)", strerror(-res), res);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001199 return NULL;
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07001200 } else if (mStatus == STATUS_UNCONFIGURED) {
1201 // Stream configuration successfully configure to empty stream configuration.
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001202 CLOGE("No streams configured");
1203 return NULL;
1204 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001205 }
1206
Shuzhen Wang0129d522016-10-30 22:43:41 -07001207 sp<CaptureRequest> newRequest = createCaptureRequest(request, surfaceMap);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001208 return newRequest;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001209}
1210
Jianing Weicb0652e2014-03-12 18:29:36 -07001211status_t Camera3Device::clearStreamingRequest(int64_t *lastFrameNumber) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001212 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001213 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001214 Mutex::Autolock l(mLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001215
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001216 switch (mStatus) {
1217 case STATUS_ERROR:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001218 CLOGE("Device has encountered a serious error");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001219 return INVALID_OPERATION;
1220 case STATUS_UNINITIALIZED:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001221 CLOGE("Device not initialized");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001222 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001223 case STATUS_UNCONFIGURED:
1224 case STATUS_CONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001225 case STATUS_ACTIVE:
1226 // OK
1227 break;
1228 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001229 SET_ERR_L("Unexpected status: %d", mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001230 return INVALID_OPERATION;
1231 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001232 ALOGV("Camera %s: Clearing repeating request", mId.string());
Jianing Weicb0652e2014-03-12 18:29:36 -07001233
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07001234 return mRequestThread->clearRepeatingRequests(lastFrameNumber);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001235}
1236
1237status_t Camera3Device::waitUntilRequestReceived(int32_t requestId, nsecs_t timeout) {
1238 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001239 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001240
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001241 return mRequestThread->waitUntilRequestProcessed(requestId, timeout);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001242}
1243
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001244status_t Camera3Device::createInputStream(
1245 uint32_t width, uint32_t height, int format, int *id) {
1246 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001247 Mutex::Autolock il(mInterfaceLock);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001248 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001249 Mutex::Autolock l(mLock);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001250 ALOGV("Camera %s: Creating new input stream %d: %d x %d, format %d",
1251 mId.string(), mNextStreamId, width, height, format);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001252
1253 status_t res;
1254 bool wasActive = false;
1255
1256 switch (mStatus) {
1257 case STATUS_ERROR:
1258 ALOGE("%s: Device has encountered a serious error", __FUNCTION__);
1259 return INVALID_OPERATION;
1260 case STATUS_UNINITIALIZED:
1261 ALOGE("%s: Device not initialized", __FUNCTION__);
1262 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001263 case STATUS_UNCONFIGURED:
1264 case STATUS_CONFIGURED:
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001265 // OK
1266 break;
1267 case STATUS_ACTIVE:
1268 ALOGV("%s: Stopping activity to reconfigure streams", __FUNCTION__);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001269 res = internalPauseAndWaitLocked(maxExpectedDuration);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001270 if (res != OK) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001271 SET_ERR_L("Can't pause captures to reconfigure streams!");
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001272 return res;
1273 }
1274 wasActive = true;
1275 break;
1276 default:
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001277 SET_ERR_L("%s: Unexpected status: %d", mStatus);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001278 return INVALID_OPERATION;
1279 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001280 assert(mStatus != STATUS_ACTIVE);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001281
1282 if (mInputStream != 0) {
1283 ALOGE("%s: Cannot create more than 1 input stream", __FUNCTION__);
1284 return INVALID_OPERATION;
1285 }
1286
1287 sp<Camera3InputStream> newStream = new Camera3InputStream(mNextStreamId,
1288 width, height, format);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001289 newStream->setStatusTracker(mStatusTracker);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001290
1291 mInputStream = newStream;
1292
1293 *id = mNextStreamId++;
1294
1295 // Continue captures if active at start
1296 if (wasActive) {
1297 ALOGV("%s: Restarting activity to reconfigure streams", __FUNCTION__);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001298 // Reuse current operating mode and session parameters for new stream config
1299 res = configureStreamsLocked(mOperatingMode, mSessionParams);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001300 if (res != OK) {
1301 ALOGE("%s: Can't reconfigure device for new stream %d: %s (%d)",
1302 __FUNCTION__, mNextStreamId, strerror(-res), res);
1303 return res;
1304 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001305 internalResumeLocked();
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001306 }
1307
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001308 ALOGV("Camera %s: Created input stream", mId.string());
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001309 return OK;
1310}
1311
Eino-Ville Talvala727d1722015-06-09 13:44:19 -07001312status_t Camera3Device::createStream(sp<Surface> consumer,
Shuzhen Wang0129d522016-10-30 22:43:41 -07001313 uint32_t width, uint32_t height, int format,
1314 android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001315 const String8& physicalCameraId,
Emilian Peev40ead602017-09-26 15:46:36 +01001316 std::vector<int> *surfaceIds, int streamSetId, bool isShared, uint64_t consumerUsage) {
Shuzhen Wang0129d522016-10-30 22:43:41 -07001317 ATRACE_CALL();
1318
1319 if (consumer == nullptr) {
1320 ALOGE("%s: consumer must not be null", __FUNCTION__);
1321 return BAD_VALUE;
1322 }
1323
1324 std::vector<sp<Surface>> consumers;
1325 consumers.push_back(consumer);
1326
1327 return createStream(consumers, /*hasDeferredConsumer*/ false, width, height,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001328 format, dataSpace, rotation, id, physicalCameraId, surfaceIds, streamSetId,
1329 isShared, consumerUsage);
Shuzhen Wang0129d522016-10-30 22:43:41 -07001330}
1331
1332status_t Camera3Device::createStream(const std::vector<sp<Surface>>& consumers,
1333 bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
1334 android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001335 const String8& physicalCameraId,
Emilian Peev40ead602017-09-26 15:46:36 +01001336 std::vector<int> *surfaceIds, int streamSetId, bool isShared, uint64_t consumerUsage) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001337 ATRACE_CALL();
Emilian Peev40ead602017-09-26 15:46:36 +01001338
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001339 Mutex::Autolock il(mInterfaceLock);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001340 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001341 Mutex::Autolock l(mLock);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001342 ALOGV("Camera %s: Creating new stream %d: %d x %d, format %d, dataspace %d rotation %d"
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001343 " consumer usage %" PRIu64 ", isShared %d, physicalCameraId %s", mId.string(),
1344 mNextStreamId, width, height, format, dataSpace, rotation, consumerUsage, isShared,
1345 physicalCameraId.string());
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001346
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001347 status_t res;
1348 bool wasActive = false;
1349
1350 switch (mStatus) {
1351 case STATUS_ERROR:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001352 CLOGE("Device has encountered a serious error");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001353 return INVALID_OPERATION;
1354 case STATUS_UNINITIALIZED:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001355 CLOGE("Device not initialized");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001356 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001357 case STATUS_UNCONFIGURED:
1358 case STATUS_CONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001359 // OK
1360 break;
1361 case STATUS_ACTIVE:
1362 ALOGV("%s: Stopping activity to reconfigure streams", __FUNCTION__);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001363 res = internalPauseAndWaitLocked(maxExpectedDuration);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001364 if (res != OK) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001365 SET_ERR_L("Can't pause captures to reconfigure streams!");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001366 return res;
1367 }
1368 wasActive = true;
1369 break;
1370 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001371 SET_ERR_L("Unexpected status: %d", mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001372 return INVALID_OPERATION;
1373 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001374 assert(mStatus != STATUS_ACTIVE);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001375
1376 sp<Camera3OutputStream> newStream;
Zhijun He5d677d12016-05-29 16:52:39 -07001377
Shuzhen Wang0129d522016-10-30 22:43:41 -07001378 if (consumers.size() == 0 && !hasDeferredConsumer) {
1379 ALOGE("%s: Number of consumers cannot be smaller than 1", __FUNCTION__);
1380 return BAD_VALUE;
1381 }
Zhijun He5d677d12016-05-29 16:52:39 -07001382
Shuzhen Wang0129d522016-10-30 22:43:41 -07001383 if (hasDeferredConsumer && format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
Zhijun He5d677d12016-05-29 16:52:39 -07001384 ALOGE("Deferred consumer stream creation only support IMPLEMENTATION_DEFINED format");
1385 return BAD_VALUE;
1386 }
1387
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001388 if (format == HAL_PIXEL_FORMAT_BLOB) {
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -07001389 ssize_t blobBufferSize;
Shuzhen Wang68ac7ad2019-01-30 14:03:28 -08001390 if (dataSpace == HAL_DATASPACE_DEPTH) {
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -07001391 blobBufferSize = getPointCloudBufferSize();
1392 if (blobBufferSize <= 0) {
1393 SET_ERR_L("Invalid point cloud buffer size %zd", blobBufferSize);
1394 return BAD_VALUE;
1395 }
Shuzhen Wang68ac7ad2019-01-30 14:03:28 -08001396 } else if (dataSpace == static_cast<android_dataspace>(HAL_DATASPACE_JPEG_APP_SEGMENTS)) {
1397 blobBufferSize = width * height;
1398 } else {
1399 blobBufferSize = getJpegBufferSize(width, height);
1400 if (blobBufferSize <= 0) {
1401 SET_ERR_L("Invalid jpeg buffer size %zd", blobBufferSize);
1402 return BAD_VALUE;
1403 }
Zhijun Hef7da0962014-04-24 13:27:56 -07001404 }
Shuzhen Wang0129d522016-10-30 22:43:41 -07001405 newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
Shuzhen Wangc28dccc2016-02-11 23:48:46 -08001406 width, height, blobBufferSize, format, dataSpace, rotation,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001407 mTimestampOffset, physicalCameraId, streamSetId);
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -08001408 } else if (format == HAL_PIXEL_FORMAT_RAW_OPAQUE) {
1409 ssize_t rawOpaqueBufferSize = getRawOpaqueBufferSize(width, height);
1410 if (rawOpaqueBufferSize <= 0) {
1411 SET_ERR_L("Invalid RAW opaque buffer size %zd", rawOpaqueBufferSize);
1412 return BAD_VALUE;
1413 }
Shuzhen Wang0129d522016-10-30 22:43:41 -07001414 newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
Shuzhen Wangc28dccc2016-02-11 23:48:46 -08001415 width, height, rawOpaqueBufferSize, format, dataSpace, rotation,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001416 mTimestampOffset, physicalCameraId, streamSetId);
Shuzhen Wang758c2152017-01-10 18:26:18 -08001417 } else if (isShared) {
1418 newStream = new Camera3SharedOutputStream(mNextStreamId, consumers,
1419 width, height, format, consumerUsage, dataSpace, rotation,
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07001420 mTimestampOffset, physicalCameraId, streamSetId,
1421 mUseHalBufManager);
Shuzhen Wang0129d522016-10-30 22:43:41 -07001422 } else if (consumers.size() == 0 && hasDeferredConsumer) {
Zhijun He5d677d12016-05-29 16:52:39 -07001423 newStream = new Camera3OutputStream(mNextStreamId,
1424 width, height, format, consumerUsage, dataSpace, rotation,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001425 mTimestampOffset, physicalCameraId, streamSetId);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001426 } else {
Shuzhen Wang0129d522016-10-30 22:43:41 -07001427 newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
Shuzhen Wangc28dccc2016-02-11 23:48:46 -08001428 width, height, format, dataSpace, rotation,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001429 mTimestampOffset, physicalCameraId, streamSetId);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001430 }
Emilian Peev40ead602017-09-26 15:46:36 +01001431
1432 size_t consumerCount = consumers.size();
1433 for (size_t i = 0; i < consumerCount; i++) {
1434 int id = newStream->getSurfaceId(consumers[i]);
1435 if (id < 0) {
1436 SET_ERR_L("Invalid surface id");
1437 return BAD_VALUE;
1438 }
1439 if (surfaceIds != nullptr) {
1440 surfaceIds->push_back(id);
1441 }
1442 }
1443
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001444 newStream->setStatusTracker(mStatusTracker);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001445
Emilian Peev08dd2452017-04-06 16:55:14 +01001446 newStream->setBufferManager(mBufferManager);
Zhijun He125684a2015-12-26 15:07:30 -08001447
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001448 res = mOutputStreams.add(mNextStreamId, newStream);
1449 if (res < 0) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001450 SET_ERR_L("Can't add new stream to set: %s (%d)", strerror(-res), res);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001451 return res;
1452 }
1453
1454 *id = mNextStreamId++;
Eino-Ville Talvalaea26c772013-06-11 16:04:06 -07001455 mNeedConfig = true;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001456
1457 // Continue captures if active at start
1458 if (wasActive) {
1459 ALOGV("%s: Restarting activity to reconfigure streams", __FUNCTION__);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001460 // Reuse current operating mode and session parameters for new stream config
1461 res = configureStreamsLocked(mOperatingMode, mSessionParams);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001462 if (res != OK) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001463 CLOGE("Can't reconfigure device for new stream %d: %s (%d)",
1464 mNextStreamId, strerror(-res), res);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001465 return res;
1466 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001467 internalResumeLocked();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001468 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001469 ALOGV("Camera %s: Created new stream", mId.string());
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001470 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001471}
1472
Emilian Peev710c1422017-08-30 11:19:38 +01001473status_t Camera3Device::getStreamInfo(int id, StreamInfo *streamInfo) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001474 ATRACE_CALL();
Emilian Peev710c1422017-08-30 11:19:38 +01001475 if (nullptr == streamInfo) {
1476 return BAD_VALUE;
1477 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001478 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001479 Mutex::Autolock l(mLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001480
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001481 switch (mStatus) {
1482 case STATUS_ERROR:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001483 CLOGE("Device has encountered a serious error");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001484 return INVALID_OPERATION;
1485 case STATUS_UNINITIALIZED:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001486 CLOGE("Device not initialized!");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001487 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001488 case STATUS_UNCONFIGURED:
1489 case STATUS_CONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001490 case STATUS_ACTIVE:
1491 // OK
1492 break;
1493 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001494 SET_ERR_L("Unexpected status: %d", mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001495 return INVALID_OPERATION;
1496 }
1497
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001498 sp<Camera3StreamInterface> stream = mOutputStreams.get(id);
1499 if (stream == nullptr) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001500 CLOGE("Stream %d is unknown", id);
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001501 return BAD_VALUE;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001502 }
1503
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001504 streamInfo->width = stream->getWidth();
1505 streamInfo->height = stream->getHeight();
1506 streamInfo->format = stream->getFormat();
1507 streamInfo->dataSpace = stream->getDataSpace();
1508 streamInfo->formatOverridden = stream->isFormatOverridden();
1509 streamInfo->originalFormat = stream->getOriginalFormat();
1510 streamInfo->dataSpaceOverridden = stream->isDataSpaceOverridden();
1511 streamInfo->originalDataSpace = stream->getOriginalDataSpace();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001512 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001513}
1514
1515status_t Camera3Device::setStreamTransform(int id,
1516 int transform) {
1517 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001518 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001519 Mutex::Autolock l(mLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001520
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001521 switch (mStatus) {
1522 case STATUS_ERROR:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001523 CLOGE("Device has encountered a serious error");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001524 return INVALID_OPERATION;
1525 case STATUS_UNINITIALIZED:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001526 CLOGE("Device not initialized");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001527 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001528 case STATUS_UNCONFIGURED:
1529 case STATUS_CONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001530 case STATUS_ACTIVE:
1531 // OK
1532 break;
1533 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001534 SET_ERR_L("Unexpected status: %d", mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001535 return INVALID_OPERATION;
1536 }
1537
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001538 sp<Camera3OutputStreamInterface> stream = mOutputStreams.get(id);
1539 if (stream == nullptr) {
1540 CLOGE("Stream %d does not exist", id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001541 return BAD_VALUE;
1542 }
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001543 return stream->setTransform(transform);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001544}
1545
1546status_t Camera3Device::deleteStream(int id) {
1547 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001548 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001549 Mutex::Autolock l(mLock);
1550 status_t res;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001551
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001552 ALOGV("%s: Camera %s: Deleting stream %d", __FUNCTION__, mId.string(), id);
Igor Murashkine2172be2013-05-28 15:31:39 -07001553
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001554 // CameraDevice semantics require device to already be idle before
1555 // deleteStream is called, unlike for createStream.
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001556 if (mStatus == STATUS_ACTIVE) {
Yin-Chia Yeh693047d2018-03-08 12:14:19 -08001557 ALOGW("%s: Camera %s: Device not idle", __FUNCTION__, mId.string());
Igor Murashkin52827132013-05-13 14:53:44 -07001558 return -EBUSY;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001559 }
1560
Yin-Chia Yeh5090c732017-07-20 16:05:29 -07001561 if (mStatus == STATUS_ERROR) {
1562 ALOGW("%s: Camera %s: deleteStream not allowed in ERROR state",
1563 __FUNCTION__, mId.string());
1564 return -EBUSY;
1565 }
1566
Igor Murashkin2fba5842013-04-22 14:03:54 -07001567 sp<Camera3StreamInterface> deletedStream;
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001568 sp<Camera3StreamInterface> stream = mOutputStreams.get(id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001569 if (mInputStream != NULL && id == mInputStream->getId()) {
1570 deletedStream = mInputStream;
1571 mInputStream.clear();
1572 } else {
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001573 if (stream == nullptr) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001574 CLOGE("Stream %d does not exist", id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001575 return BAD_VALUE;
1576 }
Zhijun He5f446352014-01-22 09:49:33 -08001577 }
1578
1579 // Delete output stream or the output part of a bi-directional stream.
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001580 if (stream != nullptr) {
1581 deletedStream = stream;
1582 mOutputStreams.remove(id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001583 }
1584
1585 // Free up the stream endpoint so that it can be used by some other stream
1586 res = deletedStream->disconnect();
1587 if (res != OK) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001588 SET_ERR_L("Can't disconnect deleted stream %d", id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001589 // fall through since we want to still list the stream as deleted.
1590 }
1591 mDeletedStreams.add(deletedStream);
Eino-Ville Talvalaea26c772013-06-11 16:04:06 -07001592 mNeedConfig = true;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001593
1594 return res;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001595}
1596
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001597status_t Camera3Device::configureStreams(const CameraMetadata& sessionParams, int operatingMode) {
Igor Murashkine2d167e2014-08-19 16:19:59 -07001598 ATRACE_CALL();
1599 ALOGV("%s: E", __FUNCTION__);
1600
1601 Mutex::Autolock il(mInterfaceLock);
1602 Mutex::Autolock l(mLock);
Chien-Yu Chen17338fc2015-06-18 16:30:12 -07001603
Emilian Peev811d2952018-05-25 11:08:40 +01001604 // In case the client doesn't include any session parameter, try a
1605 // speculative configuration using the values from the last cached
1606 // default request.
1607 if (sessionParams.isEmpty() &&
1608 ((mLastTemplateId > 0) && (mLastTemplateId < CAMERA3_TEMPLATE_COUNT)) &&
1609 (!mRequestTemplateCache[mLastTemplateId].isEmpty())) {
1610 ALOGV("%s: Speculative session param configuration with template id: %d", __func__,
1611 mLastTemplateId);
1612 return filterParamsAndConfigureLocked(mRequestTemplateCache[mLastTemplateId],
1613 operatingMode);
1614 }
1615
Emilian Peevac3ce6c2017-12-12 15:27:02 +00001616 return filterParamsAndConfigureLocked(sessionParams, operatingMode);
1617}
1618
1619status_t Camera3Device::filterParamsAndConfigureLocked(const CameraMetadata& sessionParams,
1620 int operatingMode) {
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001621 //Filter out any incoming session parameters
1622 const CameraMetadata params(sessionParams);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001623 camera_metadata_entry_t availableSessionKeys = mDeviceInfo.find(
1624 ANDROID_REQUEST_AVAILABLE_SESSION_KEYS);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00001625 CameraMetadata filteredParams(availableSessionKeys.count);
1626 camera_metadata_t *meta = const_cast<camera_metadata_t *>(
1627 filteredParams.getAndLock());
1628 set_camera_metadata_vendor_id(meta, mVendorTagId);
1629 filteredParams.unlock(meta);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001630 if (availableSessionKeys.count > 0) {
1631 for (size_t i = 0; i < availableSessionKeys.count; i++) {
1632 camera_metadata_ro_entry entry = params.find(
1633 availableSessionKeys.data.i32[i]);
1634 if (entry.count > 0) {
1635 filteredParams.update(entry);
1636 }
1637 }
1638 }
1639
1640 return configureStreamsLocked(operatingMode, filteredParams);
Igor Murashkine2d167e2014-08-19 16:19:59 -07001641}
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001642
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -07001643status_t Camera3Device::getInputBufferProducer(
1644 sp<IGraphicBufferProducer> *producer) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07001645 ATRACE_CALL();
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -07001646 Mutex::Autolock il(mInterfaceLock);
1647 Mutex::Autolock l(mLock);
1648
1649 if (producer == NULL) {
1650 return BAD_VALUE;
1651 } else if (mInputStream == NULL) {
1652 return INVALID_OPERATION;
1653 }
1654
1655 return mInputStream->getInputBufferProducer(producer);
1656}
1657
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001658status_t Camera3Device::createDefaultRequest(int templateId,
1659 CameraMetadata *request) {
1660 ATRACE_CALL();
Alex Rayfe7e0c62013-05-30 00:12:13 -07001661 ALOGV("%s: for template %d", __FUNCTION__, templateId);
Chien-Yu Chen9cd14022016-03-09 12:21:01 -08001662
1663 if (templateId <= 0 || templateId >= CAMERA3_TEMPLATE_COUNT) {
1664 android_errorWriteWithInfoLog(CameraService::SN_EVENT_LOG_ID, "26866110",
Jayant Chowdhary12361932018-08-27 14:46:13 -07001665 CameraThreadState::getCallingUid(), nullptr, 0);
Chien-Yu Chen9cd14022016-03-09 12:21:01 -08001666 return BAD_VALUE;
1667 }
1668
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001669 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001670
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001671 {
1672 Mutex::Autolock l(mLock);
1673 switch (mStatus) {
1674 case STATUS_ERROR:
1675 CLOGE("Device has encountered a serious error");
1676 return INVALID_OPERATION;
1677 case STATUS_UNINITIALIZED:
1678 CLOGE("Device is not initialized!");
1679 return INVALID_OPERATION;
1680 case STATUS_UNCONFIGURED:
1681 case STATUS_CONFIGURED:
1682 case STATUS_ACTIVE:
1683 // OK
1684 break;
1685 default:
1686 SET_ERR_L("Unexpected status: %d", mStatus);
1687 return INVALID_OPERATION;
1688 }
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001689
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001690 if (!mRequestTemplateCache[templateId].isEmpty()) {
1691 *request = mRequestTemplateCache[templateId];
Emilian Peev811d2952018-05-25 11:08:40 +01001692 mLastTemplateId = templateId;
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001693 return OK;
1694 }
Zhijun Hea1530f12014-09-14 12:44:20 -07001695 }
1696
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001697 camera_metadata_t *rawRequest;
1698 status_t res = mInterface->constructDefaultRequestSettings(
1699 (camera3_request_template_t) templateId, &rawRequest);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001700
1701 {
1702 Mutex::Autolock l(mLock);
1703 if (res == BAD_VALUE) {
1704 ALOGI("%s: template %d is not supported on this camera device",
1705 __FUNCTION__, templateId);
1706 return res;
1707 } else if (res != OK) {
1708 CLOGE("Unable to construct request template %d: %s (%d)",
1709 templateId, strerror(-res), res);
1710 return res;
1711 }
1712
1713 set_camera_metadata_vendor_id(rawRequest, mVendorTagId);
1714 mRequestTemplateCache[templateId].acquire(rawRequest);
1715
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08001716 // Override the template request with zoomRatioMapper
1717 res = mZoomRatioMappers[mId.c_str()].initZoomRatioInTemplate(
1718 &mRequestTemplateCache[templateId]);
1719 if (res != OK) {
1720 CLOGE("Failed to update zoom ratio for template %d: %s (%d)",
1721 templateId, strerror(-res), res);
1722 return res;
1723 }
1724
Shuzhen Wangd25dc972020-03-24 17:11:43 -07001725 // Fill in JPEG_QUALITY if not available
1726 if (!mRequestTemplateCache[templateId].exists(ANDROID_JPEG_QUALITY)) {
1727 static const uint8_t kDefaultJpegQuality = 95;
1728 mRequestTemplateCache[templateId].update(ANDROID_JPEG_QUALITY,
1729 &kDefaultJpegQuality, 1);
1730 }
1731
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001732 *request = mRequestTemplateCache[templateId];
Emilian Peev811d2952018-05-25 11:08:40 +01001733 mLastTemplateId = templateId;
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001734 }
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001735 return OK;
1736}
1737
1738status_t Camera3Device::waitUntilDrained() {
1739 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001740 Mutex::Autolock il(mInterfaceLock);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001741 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001742 Mutex::Autolock l(mLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001743
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001744 return waitUntilDrainedLocked(maxExpectedDuration);
Zhijun He69a37482014-03-23 18:44:49 -07001745}
1746
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001747status_t Camera3Device::waitUntilDrainedLocked(nsecs_t maxExpectedDuration) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001748 switch (mStatus) {
1749 case STATUS_UNINITIALIZED:
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001750 case STATUS_UNCONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001751 ALOGV("%s: Already idle", __FUNCTION__);
1752 return OK;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001753 case STATUS_CONFIGURED:
1754 // To avoid race conditions, check with tracker to be sure
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001755 case STATUS_ERROR:
1756 case STATUS_ACTIVE:
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001757 // Need to verify shut down
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001758 break;
1759 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001760 SET_ERR_L("Unexpected status: %d",mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001761 return INVALID_OPERATION;
1762 }
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07001763 ALOGV("%s: Camera %s: Waiting until idle (%" PRIi64 "ns)", __FUNCTION__, mId.string(),
1764 maxExpectedDuration);
1765 status_t res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration);
Eino-Ville Talvala9c8a0912014-09-14 14:52:19 -07001766 if (res != OK) {
1767 SET_ERR_L("Error waiting for HAL to drain: %s (%d)", strerror(-res),
1768 res);
1769 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001770 return res;
1771}
1772
Ruben Brunk183f0562015-08-12 12:55:02 -07001773
1774void Camera3Device::internalUpdateStatusLocked(Status status) {
1775 mStatus = status;
1776 mRecentStatusUpdates.add(mStatus);
1777 mStatusChanged.broadcast();
1778}
1779
Eino-Ville Talvala002001b2018-01-23 16:53:50 -08001780void Camera3Device::pauseStateNotify(bool enable) {
Jayant Chowdhary646c31b2020-01-30 13:09:59 -08001781 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvala002001b2018-01-23 16:53:50 -08001782 Mutex::Autolock l(mLock);
1783
1784 mPauseStateNotify = enable;
1785}
1786
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001787// Pause to reconfigure
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001788status_t Camera3Device::internalPauseAndWaitLocked(nsecs_t maxExpectedDuration) {
Emilian Peeve86358b2019-02-15 13:51:39 -08001789 if (mRequestThread.get() != nullptr) {
1790 mRequestThread->setPaused(true);
1791 } else {
1792 return NO_INIT;
1793 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001794
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07001795 ALOGV("%s: Camera %s: Internal wait until idle (% " PRIi64 " ns)", __FUNCTION__, mId.string(),
1796 maxExpectedDuration);
1797 status_t res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001798 if (res != OK) {
1799 SET_ERR_L("Can't idle device in %f seconds!",
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07001800 maxExpectedDuration/1e9);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001801 }
1802
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001803 return res;
1804}
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001805
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001806// Resume after internalPauseAndWaitLocked
1807status_t Camera3Device::internalResumeLocked() {
1808 status_t res;
1809
1810 mRequestThread->setPaused(false);
1811
Eino-Ville Talvala002001b2018-01-23 16:53:50 -08001812 ALOGV("%s: Camera %s: Internal wait until active (% " PRIi64 " ns)", __FUNCTION__, mId.string(),
1813 kActiveTimeout);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001814 res = waitUntilStateThenRelock(/*active*/ true, kActiveTimeout);
1815 if (res != OK) {
1816 SET_ERR_L("Can't transition to active in %f seconds!",
1817 kActiveTimeout/1e9);
1818 }
1819 mPauseStateNotify = false;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001820 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001821}
1822
Ruben Brunk183f0562015-08-12 12:55:02 -07001823status_t Camera3Device::waitUntilStateThenRelock(bool active, nsecs_t timeout) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001824 status_t res = OK;
Ruben Brunk183f0562015-08-12 12:55:02 -07001825
1826 size_t startIndex = 0;
1827 if (mStatusWaiters == 0) {
1828 // Clear the list of recent statuses if there are no existing threads waiting on updates to
1829 // this status list
1830 mRecentStatusUpdates.clear();
1831 } else {
1832 // If other threads are waiting on updates to this status list, set the position of the
1833 // first element that this list will check rather than clearing the list.
1834 startIndex = mRecentStatusUpdates.size();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001835 }
1836
Ruben Brunk183f0562015-08-12 12:55:02 -07001837 mStatusWaiters++;
1838
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07001839 if (!active && mUseHalBufManager) {
1840 auto streamIds = mOutputStreams.getStreamIds();
Yin-Chia Yehcd333fe2019-02-08 13:45:41 -08001841 if (mStatus == STATUS_ACTIVE) {
1842 mRequestThread->signalPipelineDrain(streamIds);
1843 }
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07001844 mRequestBufferSM.onWaitUntilIdle();
1845 }
1846
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001847 bool stateSeen = false;
1848 do {
Ruben Brunk183f0562015-08-12 12:55:02 -07001849 if (active == (mStatus == STATUS_ACTIVE)) {
1850 // Desired state is current
1851 break;
1852 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001853
1854 res = mStatusChanged.waitRelative(mLock, timeout);
1855 if (res != OK) break;
1856
Ruben Brunk183f0562015-08-12 12:55:02 -07001857 // This is impossible, but if not, could result in subtle deadlocks and invalid state
1858 // transitions.
1859 LOG_ALWAYS_FATAL_IF(startIndex > mRecentStatusUpdates.size(),
1860 "%s: Skipping status updates in Camera3Device, may result in deadlock.",
1861 __FUNCTION__);
1862
1863 // Encountered desired state since we began waiting
1864 for (size_t i = startIndex; i < mRecentStatusUpdates.size(); i++) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001865 if (active == (mRecentStatusUpdates[i] == STATUS_ACTIVE) ) {
1866 stateSeen = true;
1867 break;
1868 }
1869 }
1870 } while (!stateSeen);
1871
Ruben Brunk183f0562015-08-12 12:55:02 -07001872 mStatusWaiters--;
1873
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001874 return res;
1875}
1876
1877
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07001878status_t Camera3Device::setNotifyCallback(wp<NotificationListener> listener) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001879 ATRACE_CALL();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001880 std::lock_guard<std::mutex> l(mOutputLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001881
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001882 if (listener != NULL && mListener != NULL) {
1883 ALOGW("%s: Replacing old callback listener", __FUNCTION__);
1884 }
1885 mListener = listener;
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07001886 mRequestThread->setNotificationListener(listener);
1887 mPreparerThread->setNotificationListener(listener);
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001888
1889 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001890}
1891
Eino-Ville Talvala46910bd2013-07-18 19:15:17 -07001892bool Camera3Device::willNotify3A() {
1893 return false;
1894}
1895
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001896status_t Camera3Device::waitForNextFrame(nsecs_t timeout) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07001897 ATRACE_CALL();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001898 std::unique_lock<std::mutex> l(mOutputLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001899
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001900 while (mResultQueue.empty()) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001901 auto st = mResultSignal.wait_for(l, std::chrono::nanoseconds(timeout));
1902 if (st == std::cv_status::timeout) {
1903 return TIMED_OUT;
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001904 }
1905 }
1906 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001907}
1908
Jianing Weicb0652e2014-03-12 18:29:36 -07001909status_t Camera3Device::getNextResult(CaptureResult *frame) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001910 ATRACE_CALL();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001911 std::lock_guard<std::mutex> l(mOutputLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001912
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001913 if (mResultQueue.empty()) {
1914 return NOT_ENOUGH_DATA;
1915 }
1916
Jianing Weicb0652e2014-03-12 18:29:36 -07001917 if (frame == NULL) {
1918 ALOGE("%s: argument cannot be NULL", __FUNCTION__);
1919 return BAD_VALUE;
1920 }
1921
1922 CaptureResult &result = *(mResultQueue.begin());
1923 frame->mResultExtras = result.mResultExtras;
1924 frame->mMetadata.acquire(result.mMetadata);
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001925 frame->mPhysicalMetadatas = std::move(result.mPhysicalMetadatas);
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001926 mResultQueue.erase(mResultQueue.begin());
1927
1928 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001929}
1930
1931status_t Camera3Device::triggerAutofocus(uint32_t id) {
1932 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001933 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001934
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001935 ALOGV("%s: Triggering autofocus, id %d", __FUNCTION__, id);
1936 // Mix-in this trigger into the next request and only the next request.
1937 RequestTrigger trigger[] = {
1938 {
1939 ANDROID_CONTROL_AF_TRIGGER,
1940 ANDROID_CONTROL_AF_TRIGGER_START
1941 },
1942 {
1943 ANDROID_CONTROL_AF_TRIGGER_ID,
1944 static_cast<int32_t>(id)
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07001945 }
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001946 };
1947
1948 return mRequestThread->queueTrigger(trigger,
1949 sizeof(trigger)/sizeof(trigger[0]));
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001950}
1951
1952status_t Camera3Device::triggerCancelAutofocus(uint32_t id) {
1953 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001954 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001955
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001956 ALOGV("%s: Triggering cancel autofocus, id %d", __FUNCTION__, id);
1957 // Mix-in this trigger into the next request and only the next request.
1958 RequestTrigger trigger[] = {
1959 {
1960 ANDROID_CONTROL_AF_TRIGGER,
1961 ANDROID_CONTROL_AF_TRIGGER_CANCEL
1962 },
1963 {
1964 ANDROID_CONTROL_AF_TRIGGER_ID,
1965 static_cast<int32_t>(id)
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07001966 }
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001967 };
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001968
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001969 return mRequestThread->queueTrigger(trigger,
1970 sizeof(trigger)/sizeof(trigger[0]));
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001971}
1972
1973status_t Camera3Device::triggerPrecaptureMetering(uint32_t id) {
1974 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001975 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001976
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001977 ALOGV("%s: Triggering precapture metering, id %d", __FUNCTION__, id);
1978 // Mix-in this trigger into the next request and only the next request.
1979 RequestTrigger trigger[] = {
1980 {
1981 ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
1982 ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_START
1983 },
1984 {
1985 ANDROID_CONTROL_AE_PRECAPTURE_ID,
1986 static_cast<int32_t>(id)
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07001987 }
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001988 };
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001989
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001990 return mRequestThread->queueTrigger(trigger,
1991 sizeof(trigger)/sizeof(trigger[0]));
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001992}
1993
Jianing Weicb0652e2014-03-12 18:29:36 -07001994status_t Camera3Device::flush(int64_t *frameNumber) {
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07001995 ATRACE_CALL();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001996 ALOGV("%s: Camera %s: Flushing all requests", __FUNCTION__, mId.string());
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001997 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07001998
Zhijun He7ef20392014-04-21 16:04:17 -07001999 {
2000 Mutex::Autolock l(mLock);
Emilian Peeved2ebe42018-09-25 16:59:09 +01002001
2002 // b/116514106 "disconnect()" can get called twice for the same device. The
2003 // camera device will not be initialized during the second run.
2004 if (mStatus == STATUS_UNINITIALIZED) {
2005 return OK;
2006 }
2007
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07002008 mRequestThread->clear(/*out*/frameNumber);
Zhijun He7ef20392014-04-21 16:04:17 -07002009 }
2010
Emilian Peev08dd2452017-04-06 16:55:14 +01002011 return mRequestThread->flush();
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07002012}
2013
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002014status_t Camera3Device::prepare(int streamId) {
Ruben Brunkc78ac262015-08-13 17:58:46 -07002015 return prepare(camera3::Camera3StreamInterface::ALLOCATE_PIPELINE_MAX, streamId);
2016}
2017
2018status_t Camera3Device::prepare(int maxCount, int streamId) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002019 ATRACE_CALL();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002020 ALOGV("%s: Camera %s: Preparing stream %d", __FUNCTION__, mId.string(), streamId);
Eino-Ville Talvala261394e2015-05-13 14:28:38 -07002021 Mutex::Autolock il(mInterfaceLock);
2022 Mutex::Autolock l(mLock);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002023
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002024 sp<Camera3StreamInterface> stream = mOutputStreams.get(streamId);
2025 if (stream == nullptr) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002026 CLOGE("Stream %d does not exist", streamId);
2027 return BAD_VALUE;
2028 }
2029
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002030 if (stream->isUnpreparable() || stream->hasOutstandingBuffers() ) {
Eino-Ville Talvala261394e2015-05-13 14:28:38 -07002031 CLOGE("Stream %d has already been a request target", streamId);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002032 return BAD_VALUE;
2033 }
2034
2035 if (mRequestThread->isStreamPending(stream)) {
Eino-Ville Talvala261394e2015-05-13 14:28:38 -07002036 CLOGE("Stream %d is already a target in a pending request", streamId);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002037 return BAD_VALUE;
2038 }
2039
Ruben Brunkc78ac262015-08-13 17:58:46 -07002040 return mPreparerThread->prepare(maxCount, stream);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002041}
2042
Eino-Ville Talvalab25e3c82015-07-15 16:04:27 -07002043status_t Camera3Device::tearDown(int streamId) {
2044 ATRACE_CALL();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002045 ALOGV("%s: Camera %s: Tearing down stream %d", __FUNCTION__, mId.string(), streamId);
Eino-Ville Talvalab25e3c82015-07-15 16:04:27 -07002046 Mutex::Autolock il(mInterfaceLock);
2047 Mutex::Autolock l(mLock);
2048
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002049 sp<Camera3StreamInterface> stream = mOutputStreams.get(streamId);
2050 if (stream == nullptr) {
Eino-Ville Talvalab25e3c82015-07-15 16:04:27 -07002051 CLOGE("Stream %d does not exist", streamId);
2052 return BAD_VALUE;
2053 }
2054
Eino-Ville Talvalab25e3c82015-07-15 16:04:27 -07002055 if (stream->hasOutstandingBuffers() || mRequestThread->isStreamPending(stream)) {
2056 CLOGE("Stream %d is a target of a in-progress request", streamId);
2057 return BAD_VALUE;
2058 }
2059
2060 return stream->tearDown();
2061}
2062
Shuzhen Wangb0fdc1e2016-03-20 23:21:39 -07002063status_t Camera3Device::addBufferListenerForStream(int streamId,
2064 wp<Camera3StreamBufferListener> listener) {
2065 ATRACE_CALL();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002066 ALOGV("%s: Camera %s: Adding buffer listener for stream %d", __FUNCTION__, mId.string(), streamId);
Shuzhen Wangb0fdc1e2016-03-20 23:21:39 -07002067 Mutex::Autolock il(mInterfaceLock);
2068 Mutex::Autolock l(mLock);
2069
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002070 sp<Camera3StreamInterface> stream = mOutputStreams.get(streamId);
2071 if (stream == nullptr) {
Shuzhen Wangb0fdc1e2016-03-20 23:21:39 -07002072 CLOGE("Stream %d does not exist", streamId);
2073 return BAD_VALUE;
2074 }
Shuzhen Wangb0fdc1e2016-03-20 23:21:39 -07002075 stream->addBufferListener(listener);
2076
2077 return OK;
2078}
2079
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002080/**
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002081 * Methods called by subclasses
2082 */
2083
2084void Camera3Device::notifyStatus(bool idle) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07002085 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002086 {
2087 // Need mLock to safely update state and synchronize to current
2088 // state of methods in flight.
2089 Mutex::Autolock l(mLock);
2090 // We can get various system-idle notices from the status tracker
2091 // while starting up. Only care about them if we've actually sent
2092 // in some requests recently.
2093 if (mStatus != STATUS_ACTIVE && mStatus != STATUS_CONFIGURED) {
2094 return;
2095 }
Eino-Ville Talvala002001b2018-01-23 16:53:50 -08002096 ALOGV("%s: Camera %s: Now %s, pauseState: %s", __FUNCTION__, mId.string(),
2097 idle ? "idle" : "active", mPauseStateNotify ? "true" : "false");
Ruben Brunk183f0562015-08-12 12:55:02 -07002098 internalUpdateStatusLocked(idle ? STATUS_CONFIGURED : STATUS_ACTIVE);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002099
2100 // Skip notifying listener if we're doing some user-transparent
2101 // state changes
2102 if (mPauseStateNotify) return;
2103 }
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07002104
2105 sp<NotificationListener> listener;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002106 {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002107 std::lock_guard<std::mutex> l(mOutputLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07002108 listener = mListener.promote();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002109 }
2110 if (idle && listener != NULL) {
2111 listener->notifyIdle();
2112 }
2113}
2114
Shuzhen Wang758c2152017-01-10 18:26:18 -08002115status_t Camera3Device::setConsumerSurfaces(int streamId,
Emilian Peev40ead602017-09-26 15:46:36 +01002116 const std::vector<sp<Surface>>& consumers, std::vector<int> *surfaceIds) {
Zhijun He5d677d12016-05-29 16:52:39 -07002117 ATRACE_CALL();
Shuzhen Wang758c2152017-01-10 18:26:18 -08002118 ALOGV("%s: Camera %s: set consumer surface for stream %d",
2119 __FUNCTION__, mId.string(), streamId);
Emilian Peev40ead602017-09-26 15:46:36 +01002120
2121 if (surfaceIds == nullptr) {
2122 return BAD_VALUE;
2123 }
2124
Zhijun He5d677d12016-05-29 16:52:39 -07002125 Mutex::Autolock il(mInterfaceLock);
2126 Mutex::Autolock l(mLock);
2127
Shuzhen Wang758c2152017-01-10 18:26:18 -08002128 if (consumers.size() == 0) {
2129 CLOGE("No consumer is passed!");
Zhijun He5d677d12016-05-29 16:52:39 -07002130 return BAD_VALUE;
2131 }
2132
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002133 sp<Camera3OutputStreamInterface> stream = mOutputStreams.get(streamId);
2134 if (stream == nullptr) {
Zhijun He5d677d12016-05-29 16:52:39 -07002135 CLOGE("Stream %d is unknown", streamId);
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002136 return BAD_VALUE;
Zhijun He5d677d12016-05-29 16:52:39 -07002137 }
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002138
2139 // isConsumerConfigurationDeferred will be off after setConsumers
2140 bool isDeferred = stream->isConsumerConfigurationDeferred();
Shuzhen Wang758c2152017-01-10 18:26:18 -08002141 status_t res = stream->setConsumers(consumers);
Zhijun He5d677d12016-05-29 16:52:39 -07002142 if (res != OK) {
2143 CLOGE("Stream %d set consumer failed (error %d %s) ", streamId, res, strerror(-res));
2144 return res;
2145 }
2146
Emilian Peev40ead602017-09-26 15:46:36 +01002147 for (auto &consumer : consumers) {
2148 int id = stream->getSurfaceId(consumer);
2149 if (id < 0) {
2150 CLOGE("Invalid surface id!");
2151 return BAD_VALUE;
2152 }
2153 surfaceIds->push_back(id);
2154 }
2155
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002156 if (isDeferred) {
Shuzhen Wang0129d522016-10-30 22:43:41 -07002157 if (!stream->isConfiguring()) {
2158 CLOGE("Stream %d was already fully configured.", streamId);
2159 return INVALID_OPERATION;
2160 }
Zhijun He5d677d12016-05-29 16:52:39 -07002161
Shuzhen Wang0129d522016-10-30 22:43:41 -07002162 res = stream->finishConfiguration();
2163 if (res != OK) {
Shuzhen Wang210ba5c2018-07-25 16:47:40 -07002164 // If finishConfiguration fails due to abandoned surface, do not set
2165 // device to error state.
2166 bool isSurfaceAbandoned =
2167 (res == NO_INIT || res == DEAD_OBJECT) && stream->isAbandoned();
2168 if (!isSurfaceAbandoned) {
2169 SET_ERR_L("Can't finish configuring output stream %d: %s (%d)",
2170 stream->getId(), strerror(-res), res);
2171 }
Shuzhen Wang0129d522016-10-30 22:43:41 -07002172 return res;
2173 }
Zhijun He5d677d12016-05-29 16:52:39 -07002174 }
2175
2176 return OK;
2177}
2178
Emilian Peev40ead602017-09-26 15:46:36 +01002179status_t Camera3Device::updateStream(int streamId, const std::vector<sp<Surface>> &newSurfaces,
2180 const std::vector<OutputStreamInfo> &outputInfo,
2181 const std::vector<size_t> &removedSurfaceIds, KeyedVector<sp<Surface>, size_t> *outputMap) {
2182 Mutex::Autolock il(mInterfaceLock);
2183 Mutex::Autolock l(mLock);
2184
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002185 sp<Camera3OutputStreamInterface> stream = mOutputStreams.get(streamId);
2186 if (stream == nullptr) {
Emilian Peev40ead602017-09-26 15:46:36 +01002187 CLOGE("Stream %d is unknown", streamId);
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002188 return BAD_VALUE;
Emilian Peev40ead602017-09-26 15:46:36 +01002189 }
2190
2191 for (const auto &it : removedSurfaceIds) {
2192 if (mRequestThread->isOutputSurfacePending(streamId, it)) {
2193 CLOGE("Shared surface still part of a pending request!");
2194 return -EBUSY;
2195 }
2196 }
2197
Emilian Peev40ead602017-09-26 15:46:36 +01002198 status_t res = stream->updateStream(newSurfaces, outputInfo, removedSurfaceIds, outputMap);
2199 if (res != OK) {
2200 CLOGE("Stream %d failed to update stream (error %d %s) ",
2201 streamId, res, strerror(-res));
2202 if (res == UNKNOWN_ERROR) {
2203 SET_ERR_L("%s: Stream update failed to revert to previous output configuration!",
2204 __FUNCTION__);
2205 }
2206 return res;
2207 }
2208
2209 return res;
2210}
2211
Chien-Yu Chena936ac22017-10-23 15:59:49 -07002212status_t Camera3Device::dropStreamBuffers(bool dropping, int streamId) {
2213 Mutex::Autolock il(mInterfaceLock);
2214 Mutex::Autolock l(mLock);
2215
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002216 sp<Camera3OutputStreamInterface> stream = mOutputStreams.get(streamId);
2217 if (stream == nullptr) {
Chien-Yu Chena936ac22017-10-23 15:59:49 -07002218 ALOGE("%s: Stream %d is not found.", __FUNCTION__, streamId);
2219 return BAD_VALUE;
2220 }
Chien-Yu Chena936ac22017-10-23 15:59:49 -07002221 return stream->dropBuffers(dropping);
2222}
2223
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002224/**
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002225 * Camera3Device private methods
2226 */
2227
2228sp<Camera3Device::CaptureRequest> Camera3Device::createCaptureRequest(
Emilian Peevaebbe412018-01-15 13:53:24 +00002229 const PhysicalCameraSettingsList &request, const SurfaceMap &surfaceMap) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002230 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002231
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08002232 sp<CaptureRequest> newRequest = new CaptureRequest();
Emilian Peevaebbe412018-01-15 13:53:24 +00002233 newRequest->mSettingsList = request;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002234
2235 camera_metadata_entry_t inputStreams =
Emilian Peevaebbe412018-01-15 13:53:24 +00002236 newRequest->mSettingsList.begin()->metadata.find(ANDROID_REQUEST_INPUT_STREAMS);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002237 if (inputStreams.count > 0) {
2238 if (mInputStream == NULL ||
Zhijun Hed1d64672013-09-06 15:00:01 -07002239 mInputStream->getId() != inputStreams.data.i32[0]) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002240 CLOGE("Request references unknown input stream %d",
2241 inputStreams.data.u8[0]);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002242 return NULL;
2243 }
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002244
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002245 if (mInputStream->isConfiguring()) {
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002246 SET_ERR_L("%s: input stream %d is not configured!",
2247 __FUNCTION__, mInputStream->getId());
2248 return NULL;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002249 }
Shuzhen Wangb3a0fb52018-09-13 17:24:08 -07002250 // Check if stream prepare is blocking requests.
2251 if (mInputStream->isBlockedByPrepare()) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002252 CLOGE("Request references an input stream that's being prepared!");
2253 return NULL;
2254 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002255
2256 newRequest->mInputStream = mInputStream;
Emilian Peevaebbe412018-01-15 13:53:24 +00002257 newRequest->mSettingsList.begin()->metadata.erase(ANDROID_REQUEST_INPUT_STREAMS);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002258 }
2259
2260 camera_metadata_entry_t streams =
Emilian Peevaebbe412018-01-15 13:53:24 +00002261 newRequest->mSettingsList.begin()->metadata.find(ANDROID_REQUEST_OUTPUT_STREAMS);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002262 if (streams.count == 0) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002263 CLOGE("Zero output streams specified!");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002264 return NULL;
2265 }
2266
2267 for (size_t i = 0; i < streams.count; i++) {
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002268 sp<Camera3OutputStreamInterface> stream = mOutputStreams.get(streams.data.i32[i]);
2269 if (stream == nullptr) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002270 CLOGE("Request references unknown stream %d",
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002271 streams.data.i32[i]);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002272 return NULL;
2273 }
Zhijun He5d677d12016-05-29 16:52:39 -07002274 // It is illegal to include a deferred consumer output stream into a request
Shuzhen Wang0129d522016-10-30 22:43:41 -07002275 auto iter = surfaceMap.find(streams.data.i32[i]);
2276 if (iter != surfaceMap.end()) {
2277 const std::vector<size_t>& surfaces = iter->second;
2278 for (const auto& surface : surfaces) {
2279 if (stream->isConsumerConfigurationDeferred(surface)) {
2280 CLOGE("Stream %d surface %zu hasn't finished configuration yet "
2281 "due to deferred consumer", stream->getId(), surface);
2282 return NULL;
2283 }
2284 }
Yin-Chia Yeh0b287572018-10-15 12:38:13 -07002285 newRequest->mOutputSurfaces[streams.data.i32[i]] = surfaces;
Zhijun He5d677d12016-05-29 16:52:39 -07002286 }
2287
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002288 if (stream->isConfiguring()) {
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002289 SET_ERR_L("%s: stream %d is not configured!", __FUNCTION__, stream->getId());
2290 return NULL;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002291 }
Shuzhen Wangb3a0fb52018-09-13 17:24:08 -07002292 // Check if stream prepare is blocking requests.
2293 if (stream->isBlockedByPrepare()) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002294 CLOGE("Request references an output stream that's being prepared!");
2295 return NULL;
2296 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002297
2298 newRequest->mOutputStreams.push(stream);
2299 }
Emilian Peevaebbe412018-01-15 13:53:24 +00002300 newRequest->mSettingsList.begin()->metadata.erase(ANDROID_REQUEST_OUTPUT_STREAMS);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07002301 newRequest->mBatchSize = 1;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002302
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08002303 auto rotateAndCropEntry =
2304 newRequest->mSettingsList.begin()->metadata.find(ANDROID_SCALER_ROTATE_AND_CROP);
2305 if (rotateAndCropEntry.count > 0 &&
2306 rotateAndCropEntry.data.u8[0] == ANDROID_SCALER_ROTATE_AND_CROP_AUTO) {
2307 newRequest->mRotateAndCropAuto = true;
2308 } else {
2309 newRequest->mRotateAndCropAuto = false;
2310 }
2311
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002312 return newRequest;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002313}
2314
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002315void Camera3Device::cancelStreamsConfigurationLocked() {
2316 int res = OK;
2317 if (mInputStream != NULL && mInputStream->isConfiguring()) {
2318 res = mInputStream->cancelConfiguration();
2319 if (res != OK) {
2320 CLOGE("Can't cancel configuring input stream %d: %s (%d)",
2321 mInputStream->getId(), strerror(-res), res);
2322 }
2323 }
2324
2325 for (size_t i = 0; i < mOutputStreams.size(); i++) {
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002326 sp<Camera3OutputStreamInterface> outputStream = mOutputStreams[i];
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002327 if (outputStream->isConfiguring()) {
2328 res = outputStream->cancelConfiguration();
2329 if (res != OK) {
2330 CLOGE("Can't cancel configuring output stream %d: %s (%d)",
2331 outputStream->getId(), strerror(-res), res);
2332 }
2333 }
2334 }
2335
2336 // Return state to that at start of call, so that future configures
2337 // properly clean things up
2338 internalUpdateStatusLocked(STATUS_UNCONFIGURED);
2339 mNeedConfig = true;
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002340
2341 res = mPreparerThread->resume();
2342 if (res != OK) {
2343 ALOGE("%s: Camera %s: Preparer thread failed to resume!", __FUNCTION__, mId.string());
2344 }
2345}
2346
Emilian Peev0d0191e2020-04-21 17:01:18 -07002347bool Camera3Device::checkAbandonedStreamsLocked() {
2348 if ((mInputStream.get() != nullptr) && (mInputStream->isAbandoned())) {
2349 return true;
2350 }
2351
2352 for (size_t i = 0; i < mOutputStreams.size(); i++) {
2353 auto stream = mOutputStreams[i];
2354 if ((stream.get() != nullptr) && (stream->isAbandoned())) {
2355 return true;
2356 }
2357 }
2358
2359 return false;
2360}
2361
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002362bool Camera3Device::reconfigureCamera(const CameraMetadata& sessionParams) {
2363 ATRACE_CALL();
2364 bool ret = false;
2365
Jayant Chowdhary646c31b2020-01-30 13:09:59 -08002366 Mutex::Autolock il(mInterfaceLock);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002367 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
2368
2369 Mutex::Autolock l(mLock);
Emilian Peev0d0191e2020-04-21 17:01:18 -07002370 if (checkAbandonedStreamsLocked()) {
2371 ALOGW("%s: Abandoned stream detected, session parameters can't be applied correctly!",
2372 __FUNCTION__);
2373 return true;
2374 }
2375
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002376 auto rc = internalPauseAndWaitLocked(maxExpectedDuration);
2377 if (rc == NO_ERROR) {
2378 mNeedConfig = true;
2379 rc = configureStreamsLocked(mOperatingMode, sessionParams, /*notifyRequestThread*/ false);
2380 if (rc == NO_ERROR) {
2381 ret = true;
2382 mPauseStateNotify = false;
2383 //Moving to active state while holding 'mLock' is important.
2384 //There could be pending calls to 'create-/deleteStream' which
2385 //will trigger another stream configuration while the already
2386 //present streams end up with outstanding buffers that will
2387 //not get drained.
2388 internalUpdateStatusLocked(STATUS_ACTIVE);
Shuzhen Wang210ba5c2018-07-25 16:47:40 -07002389 } else if (rc == DEAD_OBJECT) {
2390 // DEAD_OBJECT can be returned if either the consumer surface is
2391 // abandoned, or the HAL has died.
2392 // - If the HAL has died, configureStreamsLocked call will set
2393 // device to error state,
2394 // - If surface is abandoned, we should not set device to error
2395 // state.
2396 ALOGE("Failed to re-configure camera due to abandoned surface");
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002397 } else {
Shuzhen Wang210ba5c2018-07-25 16:47:40 -07002398 SET_ERR_L("Failed to re-configure camera: %d", rc);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002399 }
2400 } else {
2401 ALOGE("%s: Failed to pause streaming: %d", __FUNCTION__, rc);
2402 }
2403
2404 return ret;
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002405}
2406
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01002407status_t Camera3Device::configureStreamsLocked(int operatingMode,
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002408 const CameraMetadata& sessionParams, bool notifyRequestThread) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002409 ATRACE_CALL();
2410 status_t res;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002411
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002412 if (mStatus != STATUS_UNCONFIGURED && mStatus != STATUS_CONFIGURED) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002413 CLOGE("Not idle");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002414 return INVALID_OPERATION;
2415 }
2416
Eino-Ville Talvalae7091aa2017-03-07 15:23:06 -08002417 if (operatingMode < 0) {
2418 CLOGE("Invalid operating mode: %d", operatingMode);
2419 return BAD_VALUE;
2420 }
2421
2422 bool isConstrainedHighSpeed =
2423 static_cast<int>(StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE) ==
2424 operatingMode;
2425
2426 if (mOperatingMode != operatingMode) {
2427 mNeedConfig = true;
2428 mIsConstrainedHighSpeedConfiguration = isConstrainedHighSpeed;
2429 mOperatingMode = operatingMode;
2430 }
2431
Shuzhen Wang0cf01cb2019-09-05 13:33:06 -07002432 // In case called from configureStreams, abort queued input buffers not belonging to
2433 // any pending requests.
2434 if (mInputStream != NULL && notifyRequestThread) {
2435 while (true) {
2436 camera3_stream_buffer_t inputBuffer;
2437 status_t res = mInputStream->getInputBuffer(&inputBuffer,
2438 /*respectHalLimit*/ false);
2439 if (res != OK) {
2440 // Exhausted acquiring all input buffers.
2441 break;
2442 }
2443
2444 inputBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
2445 res = mInputStream->returnInputBuffer(inputBuffer);
2446 if (res != OK) {
2447 ALOGE("%s: %d: couldn't return input buffer while clearing input queue: "
2448 "%s (%d)", __FUNCTION__, __LINE__, strerror(-res), res);
2449 }
2450 }
2451 }
2452
Eino-Ville Talvalaea26c772013-06-11 16:04:06 -07002453 if (!mNeedConfig) {
2454 ALOGV("%s: Skipping config, no stream changes", __FUNCTION__);
2455 return OK;
2456 }
2457
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002458 // Workaround for device HALv3.2 or older spec bug - zero streams requires
2459 // adding a dummy stream instead.
2460 // TODO: Bug: 17321404 for fixing the HAL spec and removing this workaround.
2461 if (mOutputStreams.size() == 0) {
2462 addDummyStreamLocked();
2463 } else {
2464 tryRemoveDummyStreamLocked();
2465 }
2466
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002467 // Start configuring the streams
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002468 ALOGV("%s: Camera %s: Starting stream configuration", __FUNCTION__, mId.string());
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002469
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002470 mPreparerThread->pause();
2471
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002472 camera3_stream_configuration config;
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -08002473 config.operation_mode = mOperatingMode;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002474 config.num_streams = (mInputStream != NULL) + mOutputStreams.size();
2475
2476 Vector<camera3_stream_t*> streams;
2477 streams.setCapacity(config.num_streams);
Emilian Peev192ee832018-01-31 14:46:47 +00002478 std::vector<uint32_t> bufferSizes(config.num_streams, 0);
Yin-Chia Yehfb6e55b2018-01-25 10:50:26 -08002479
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002480
2481 if (mInputStream != NULL) {
2482 camera3_stream_t *inputStream;
2483 inputStream = mInputStream->startConfiguration();
2484 if (inputStream == NULL) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002485 CLOGE("Can't start input stream configuration");
2486 cancelStreamsConfigurationLocked();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002487 return INVALID_OPERATION;
2488 }
2489 streams.add(inputStream);
2490 }
2491
2492 for (size_t i = 0; i < mOutputStreams.size(); i++) {
Igor Murashkin2fba5842013-04-22 14:03:54 -07002493
2494 // Don't configure bidi streams twice, nor add them twice to the list
2495 if (mOutputStreams[i].get() ==
2496 static_cast<Camera3StreamInterface*>(mInputStream.get())) {
2497
2498 config.num_streams--;
2499 continue;
2500 }
2501
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002502 camera3_stream_t *outputStream;
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002503 outputStream = mOutputStreams[i]->startConfiguration();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002504 if (outputStream == NULL) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002505 CLOGE("Can't start output stream configuration");
2506 cancelStreamsConfigurationLocked();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002507 return INVALID_OPERATION;
2508 }
2509 streams.add(outputStream);
Yin-Chia Yehfb6e55b2018-01-25 10:50:26 -08002510
Shuzhen Wangb7ab1e42019-02-20 15:42:23 -08002511 if (outputStream->format == HAL_PIXEL_FORMAT_BLOB) {
Emilian Peev192ee832018-01-31 14:46:47 +00002512 size_t k = i + ((mInputStream != nullptr) ? 1 : 0); // Input stream if present should
2513 // always occupy the initial entry.
Shuzhen Wangb7ab1e42019-02-20 15:42:23 -08002514 if (outputStream->data_space == HAL_DATASPACE_V0_JFIF) {
2515 bufferSizes[k] = static_cast<uint32_t>(
2516 getJpegBufferSize(outputStream->width, outputStream->height));
2517 } else if (outputStream->data_space ==
2518 static_cast<android_dataspace>(HAL_DATASPACE_JPEG_APP_SEGMENTS)) {
2519 bufferSizes[k] = outputStream->width * outputStream->height;
2520 } else {
2521 ALOGW("%s: Blob dataSpace %d not supported",
2522 __FUNCTION__, outputStream->data_space);
2523 }
Yin-Chia Yehfb6e55b2018-01-25 10:50:26 -08002524 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002525 }
2526
2527 config.streams = streams.editArray();
2528
2529 // Do the HAL configuration; will potentially touch stream
Shuzhen Wang92653952019-05-07 15:11:43 -07002530 // max_buffers, usage, and priv fields, as well as data_space and format
2531 // fields for IMPLEMENTATION_DEFINED formats.
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002532
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01002533 const camera_metadata_t *sessionBuffer = sessionParams.getAndLock();
Emilian Peev192ee832018-01-31 14:46:47 +00002534 res = mInterface->configureStreams(sessionBuffer, &config, bufferSizes);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01002535 sessionParams.unlock(sessionBuffer);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002536
Eino-Ville Talvala17543512014-08-06 14:32:02 -07002537 if (res == BAD_VALUE) {
2538 // HAL rejected this set of streams as unsupported, clean up config
2539 // attempt and return to unconfigured state
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002540 CLOGE("Set of requested inputs/outputs not supported by HAL");
2541 cancelStreamsConfigurationLocked();
Eino-Ville Talvala17543512014-08-06 14:32:02 -07002542 return BAD_VALUE;
2543 } else if (res != OK) {
2544 // Some other kind of error from configure_streams - this is not
2545 // expected
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002546 SET_ERR_L("Unable to configure streams with HAL: %s (%d)",
2547 strerror(-res), res);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002548 return res;
2549 }
2550
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002551 // Finish all stream configuration immediately.
2552 // TODO: Try to relax this later back to lazy completion, which should be
2553 // faster
2554
Igor Murashkin073f8572013-05-02 14:59:28 -07002555 if (mInputStream != NULL && mInputStream->isConfiguring()) {
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002556 bool streamReConfigured = false;
2557 res = mInputStream->finishConfiguration(&streamReConfigured);
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002558 if (res != OK) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002559 CLOGE("Can't finish configuring input stream %d: %s (%d)",
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002560 mInputStream->getId(), strerror(-res), res);
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002561 cancelStreamsConfigurationLocked();
Shuzhen Wang210ba5c2018-07-25 16:47:40 -07002562 if ((res == NO_INIT || res == DEAD_OBJECT) && mInputStream->isAbandoned()) {
2563 return DEAD_OBJECT;
2564 }
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002565 return BAD_VALUE;
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002566 }
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002567 if (streamReConfigured) {
2568 mInterface->onStreamReConfigured(mInputStream->getId());
2569 }
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002570 }
2571
2572 for (size_t i = 0; i < mOutputStreams.size(); i++) {
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002573 sp<Camera3OutputStreamInterface> outputStream = mOutputStreams[i];
Zhijun He5d677d12016-05-29 16:52:39 -07002574 if (outputStream->isConfiguring() && !outputStream->isConsumerConfigurationDeferred()) {
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002575 bool streamReConfigured = false;
2576 res = outputStream->finishConfiguration(&streamReConfigured);
Igor Murashkin073f8572013-05-02 14:59:28 -07002577 if (res != OK) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002578 CLOGE("Can't finish configuring output stream %d: %s (%d)",
Igor Murashkin073f8572013-05-02 14:59:28 -07002579 outputStream->getId(), strerror(-res), res);
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002580 cancelStreamsConfigurationLocked();
Shuzhen Wang210ba5c2018-07-25 16:47:40 -07002581 if ((res == NO_INIT || res == DEAD_OBJECT) && outputStream->isAbandoned()) {
2582 return DEAD_OBJECT;
2583 }
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002584 return BAD_VALUE;
Igor Murashkin073f8572013-05-02 14:59:28 -07002585 }
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002586 if (streamReConfigured) {
2587 mInterface->onStreamReConfigured(outputStream->getId());
2588 }
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002589 }
2590 }
2591
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002592 // Request thread needs to know to avoid using repeat-last-settings protocol
2593 // across configure_streams() calls
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002594 if (notifyRequestThread) {
2595 mRequestThread->configurationComplete(mIsConstrainedHighSpeedConfiguration, sessionParams);
2596 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002597
Zhijun He90f7c372016-08-16 16:19:43 -07002598 char value[PROPERTY_VALUE_MAX];
2599 property_get("camera.fifo.disable", value, "0");
2600 int32_t disableFifo = atoi(value);
2601 if (disableFifo != 1) {
2602 // Boost priority of request thread to SCHED_FIFO.
2603 pid_t requestThreadTid = mRequestThread->getTid();
2604 res = requestPriority(getpid(), requestThreadTid,
Mikhail Naganov83f04272017-02-07 10:45:09 -08002605 kRequestThreadPriority, /*isForApp*/ false, /*asynchronous*/ false);
Zhijun He90f7c372016-08-16 16:19:43 -07002606 if (res != OK) {
2607 ALOGW("Can't set realtime priority for request processing thread: %s (%d)",
2608 strerror(-res), res);
2609 } else {
2610 ALOGD("Set real time priority for request queue thread (tid %d)", requestThreadTid);
2611 }
Eino-Ville Talvalaf99498e2015-09-25 16:52:55 -07002612 }
2613
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002614 // Update device state
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01002615 const camera_metadata_t *newSessionParams = sessionParams.getAndLock();
2616 const camera_metadata_t *currentSessionParams = mSessionParams.getAndLock();
2617 bool updateSessionParams = (newSessionParams != currentSessionParams) ? true : false;
2618 sessionParams.unlock(newSessionParams);
2619 mSessionParams.unlock(currentSessionParams);
2620 if (updateSessionParams) {
2621 mSessionParams = sessionParams;
2622 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002623
Eino-Ville Talvalaea26c772013-06-11 16:04:06 -07002624 mNeedConfig = false;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002625
Ruben Brunk183f0562015-08-12 12:55:02 -07002626 internalUpdateStatusLocked((mDummyStreamId == NO_STREAM) ?
2627 STATUS_CONFIGURED : STATUS_UNCONFIGURED);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002628
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002629 ALOGV("%s: Camera %s: Stream configuration complete", __FUNCTION__, mId.string());
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002630
Zhijun He0a210512014-07-24 13:45:15 -07002631 // tear down the deleted streams after configure streams.
2632 mDeletedStreams.clear();
2633
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002634 auto rc = mPreparerThread->resume();
2635 if (rc != OK) {
2636 SET_ERR_L("%s: Camera %s: Preparer thread failed to resume!", __FUNCTION__, mId.string());
2637 return rc;
2638 }
2639
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07002640 if (mDummyStreamId == NO_STREAM) {
2641 mRequestBufferSM.onStreamsConfigured();
2642 }
2643
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002644 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002645}
2646
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002647status_t Camera3Device::addDummyStreamLocked() {
2648 ATRACE_CALL();
2649 status_t res;
2650
2651 if (mDummyStreamId != NO_STREAM) {
2652 // Should never be adding a second dummy stream when one is already
2653 // active
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002654 SET_ERR_L("%s: Camera %s: A dummy stream already exists!",
2655 __FUNCTION__, mId.string());
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002656 return INVALID_OPERATION;
2657 }
2658
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002659 ALOGV("%s: Camera %s: Adding a dummy stream", __FUNCTION__, mId.string());
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002660
2661 sp<Camera3OutputStreamInterface> dummyStream =
2662 new Camera3DummyStream(mNextStreamId);
2663
2664 res = mOutputStreams.add(mNextStreamId, dummyStream);
2665 if (res < 0) {
2666 SET_ERR_L("Can't add dummy stream to set: %s (%d)", strerror(-res), res);
2667 return res;
2668 }
2669
2670 mDummyStreamId = mNextStreamId;
2671 mNextStreamId++;
2672
2673 return OK;
2674}
2675
2676status_t Camera3Device::tryRemoveDummyStreamLocked() {
2677 ATRACE_CALL();
2678 status_t res;
2679
2680 if (mDummyStreamId == NO_STREAM) return OK;
2681 if (mOutputStreams.size() == 1) return OK;
2682
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002683 ALOGV("%s: Camera %s: Removing the dummy stream", __FUNCTION__, mId.string());
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002684
2685 // Ok, have a dummy stream and there's at least one other output stream,
2686 // so remove the dummy
2687
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002688 sp<Camera3StreamInterface> deletedStream = mOutputStreams.get(mDummyStreamId);
2689 if (deletedStream == nullptr) {
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002690 SET_ERR_L("Dummy stream %d does not appear to exist", mDummyStreamId);
2691 return INVALID_OPERATION;
2692 }
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002693 mOutputStreams.remove(mDummyStreamId);
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002694
2695 // Free up the stream endpoint so that it can be used by some other stream
2696 res = deletedStream->disconnect();
2697 if (res != OK) {
2698 SET_ERR_L("Can't disconnect deleted dummy stream %d", mDummyStreamId);
2699 // fall through since we want to still list the stream as deleted.
2700 }
2701 mDeletedStreams.add(deletedStream);
2702 mDummyStreamId = NO_STREAM;
2703
2704 return res;
2705}
2706
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002707void Camera3Device::setErrorState(const char *fmt, ...) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07002708 ATRACE_CALL();
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002709 Mutex::Autolock l(mLock);
2710 va_list args;
2711 va_start(args, fmt);
2712
2713 setErrorStateLockedV(fmt, args);
2714
2715 va_end(args);
2716}
2717
2718void Camera3Device::setErrorStateV(const char *fmt, va_list args) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07002719 ATRACE_CALL();
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002720 Mutex::Autolock l(mLock);
2721 setErrorStateLockedV(fmt, args);
2722}
2723
2724void Camera3Device::setErrorStateLocked(const char *fmt, ...) {
2725 va_list args;
2726 va_start(args, fmt);
2727
2728 setErrorStateLockedV(fmt, args);
2729
2730 va_end(args);
2731}
2732
2733void Camera3Device::setErrorStateLockedV(const char *fmt, va_list args) {
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002734 // Print out all error messages to log
2735 String8 errorCause = String8::formatV(fmt, args);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002736 ALOGE("Camera %s: %s", mId.string(), errorCause.string());
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002737
2738 // But only do error state transition steps for the first error
Zhijun Heb05eeae2013-06-06 13:51:22 -07002739 if (mStatus == STATUS_ERROR || mStatus == STATUS_UNINITIALIZED) return;
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002740
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002741 mErrorCause = errorCause;
2742
Yin-Chia Yeh3d145ae2017-07-27 12:47:03 -07002743 if (mRequestThread != nullptr) {
2744 mRequestThread->setPaused(true);
2745 }
Ruben Brunk183f0562015-08-12 12:55:02 -07002746 internalUpdateStatusLocked(STATUS_ERROR);
Eino-Ville Talvala17543512014-08-06 14:32:02 -07002747
2748 // Notify upstream about a device error
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07002749 sp<NotificationListener> listener = mListener.promote();
2750 if (listener != NULL) {
2751 listener->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
Eino-Ville Talvala17543512014-08-06 14:32:02 -07002752 CaptureResultExtras());
2753 }
2754
2755 // Save stack trace. View by dumping it later.
2756 CameraTraces::saveTrace();
2757 // TODO: consider adding errorCause and client pid/procname
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002758}
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002759
2760/**
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002761 * In-flight request management
2762 */
2763
Jianing Weicb0652e2014-03-12 18:29:36 -07002764status_t Camera3Device::registerInFlight(uint32_t frameNumber,
Chien-Yu Chend196d612015-06-22 19:49:01 -07002765 int32_t numBuffers, CaptureResultExtras resultExtras, bool hasInput,
Shuzhen Wang5c22c152017-12-31 17:12:25 -08002766 bool hasAppCallback, nsecs_t maxExpectedDuration,
Shuzhen Wang26abaf42018-08-28 15:41:20 -07002767 std::set<String8>& physicalCameraIds, bool isStillCapture,
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08002768 bool isZslCapture, bool rotateAndCropAuto, const std::set<std::string>& cameraIdsWithZoom,
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08002769 const SurfaceMap& outputSurfaces) {
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002770 ATRACE_CALL();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002771 std::lock_guard<std::mutex> l(mInFlightLock);
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002772
2773 ssize_t res;
Chien-Yu Chend196d612015-06-22 19:49:01 -07002774 res = mInFlightMap.add(frameNumber, InFlightRequest(numBuffers, resultExtras, hasInput,
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07002775 hasAppCallback, maxExpectedDuration, physicalCameraIds, isStillCapture, isZslCapture,
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08002776 rotateAndCropAuto, cameraIdsWithZoom, outputSurfaces));
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002777 if (res < 0) return res;
2778
Eino-Ville Talvala24b366e2016-07-21 12:53:07 -07002779 if (mInFlightMap.size() == 1) {
Emilian Peev26d975d2018-07-05 14:52:57 +01002780 // Hold a separate dedicated tracker lock to prevent race with disconnect and also
2781 // avoid a deadlock during reprocess requests.
2782 Mutex::Autolock l(mTrackerLock);
Yin-Chia Yeh38dfde52017-06-27 17:13:33 -07002783 if (mStatusTracker != nullptr) {
2784 mStatusTracker->markComponentActive(mInFlightStatusId);
2785 }
Eino-Ville Talvala24b366e2016-07-21 12:53:07 -07002786 }
2787
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07002788 mExpectedInflightDuration += maxExpectedDuration;
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002789 return OK;
2790}
2791
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002792void Camera3Device::onInflightEntryRemovedLocked(nsecs_t duration) {
Shuzhen Wangcadb3302016-11-04 14:17:56 -07002793 // Indicate idle inFlightMap to the status tracker
2794 if (mInFlightMap.size() == 0) {
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07002795 mRequestBufferSM.onInflightMapEmpty();
Emilian Peev26d975d2018-07-05 14:52:57 +01002796 // Hold a separate dedicated tracker lock to prevent race with disconnect and also
2797 // avoid a deadlock during reprocess requests.
2798 Mutex::Autolock l(mTrackerLock);
Yin-Chia Yeh38dfde52017-06-27 17:13:33 -07002799 if (mStatusTracker != nullptr) {
2800 mStatusTracker->markComponentIdle(mInFlightStatusId, Fence::NO_FENCE);
2801 }
Shuzhen Wangcadb3302016-11-04 14:17:56 -07002802 }
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07002803 mExpectedInflightDuration -= duration;
Shuzhen Wangcadb3302016-11-04 14:17:56 -07002804}
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08002805
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002806void Camera3Device::checkInflightMapLengthLocked() {
Yin-Chia Yeh99fd0972019-06-27 14:22:44 -07002807 // Sanity check - if we have too many in-flight frames with long total inflight duration,
2808 // something has likely gone wrong. This might still be legit only if application send in
2809 // a long burst of long exposure requests.
2810 if (mExpectedInflightDuration > kMinWarnInflightDuration) {
2811 if (!mIsConstrainedHighSpeedConfiguration && mInFlightMap.size() > kInFlightWarnLimit) {
2812 CLOGW("In-flight list too large: %zu, total inflight duration %" PRIu64,
2813 mInFlightMap.size(), mExpectedInflightDuration);
2814 } else if (mIsConstrainedHighSpeedConfiguration && mInFlightMap.size() >
2815 kInFlightWarnLimitHighSpeed) {
2816 CLOGW("In-flight list too large for high speed configuration: %zu,"
2817 "total inflight duration %" PRIu64,
2818 mInFlightMap.size(), mExpectedInflightDuration);
2819 }
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08002820 }
2821}
2822
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002823void Camera3Device::onInflightMapFlushedLocked() {
2824 mExpectedInflightDuration = 0;
2825}
2826
2827void Camera3Device::removeInFlightMapEntryLocked(int idx) {
2828 ATRACE_CALL();
2829 nsecs_t duration = mInFlightMap.valueAt(idx).maxExpectedDuration;
2830 mInFlightMap.removeItemsAt(idx, 1);
2831
2832 onInflightEntryRemovedLocked(duration);
2833}
2834
2835
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07002836void Camera3Device::flushInflightRequests() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07002837 ATRACE_CALL();
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07002838 sp<NotificationListener> listener;
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07002839 {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002840 std::lock_guard<std::mutex> l(mOutputLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07002841 listener = mListener.promote();
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07002842 }
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002843
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002844 FlushInflightReqStates states {
2845 mId, mInFlightLock, mInFlightMap, mUseHalBufManager,
2846 listener, *this, *mInterface, *this};
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07002847
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002848 camera3::flushInflightRequests(states);
Eino-Ville Talvala17543512014-08-06 14:32:02 -07002849}
2850
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002851CameraMetadata Camera3Device::getLatestRequestLocked() {
Igor Murashkin1e479c02013-09-06 16:55:14 -07002852 ALOGV("%s", __FUNCTION__);
2853
Igor Murashkin1e479c02013-09-06 16:55:14 -07002854 CameraMetadata retVal;
2855
2856 if (mRequestThread != NULL) {
2857 retVal = mRequestThread->getLatestRequest();
2858 }
2859
Igor Murashkin1e479c02013-09-06 16:55:14 -07002860 return retVal;
2861}
2862
Eino-Ville Talvala4d453832016-07-15 11:56:53 -07002863void Camera3Device::monitorMetadata(TagMonitor::eventSource source,
Shuzhen Wangc2cba122018-05-17 18:10:24 -07002864 int64_t frameNumber, nsecs_t timestamp, const CameraMetadata& metadata,
2865 const std::unordered_map<std::string, CameraMetadata>& physicalMetadata) {
2866
2867 mTagMonitor.monitorMetadata(source, frameNumber, timestamp, metadata,
2868 physicalMetadata);
Eino-Ville Talvala4d453832016-07-15 11:56:53 -07002869}
2870
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002871/**
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002872 * HalInterface inner class methods
2873 */
2874
Yifan Hongf79b5542017-04-11 14:44:25 -07002875Camera3Device::HalInterface::HalInterface(
2876 sp<ICameraDeviceSession> &session,
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08002877 std::shared_ptr<RequestMetadataQueue> queue,
Yin-Chia Yehb978c382019-10-30 00:22:37 -07002878 bool useHalBufManager, bool supportOfflineProcessing) :
Yifan Hongf79b5542017-04-11 14:44:25 -07002879 mHidlSession(session),
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08002880 mRequestMetadataQueue(queue),
Emilian Peev4ec17882019-01-24 17:16:58 -08002881 mUseHalBufManager(useHalBufManager),
Yin-Chia Yehb978c382019-10-30 00:22:37 -07002882 mIsReconfigurationQuerySupported(true),
2883 mSupportOfflineProcessing(supportOfflineProcessing) {
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002884 // Check with hardware service manager if we can downcast these interfaces
2885 // Somewhat expensive, so cache the results at startup
Yin-Chia Yehb978c382019-10-30 00:22:37 -07002886 auto castResult_3_6 = device::V3_6::ICameraDeviceSession::castFrom(mHidlSession);
2887 if (castResult_3_6.isOk()) {
2888 mHidlSession_3_6 = castResult_3_6;
2889 }
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07002890 auto castResult_3_5 = device::V3_5::ICameraDeviceSession::castFrom(mHidlSession);
2891 if (castResult_3_5.isOk()) {
2892 mHidlSession_3_5 = castResult_3_5;
2893 }
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002894 auto castResult_3_4 = device::V3_4::ICameraDeviceSession::castFrom(mHidlSession);
2895 if (castResult_3_4.isOk()) {
2896 mHidlSession_3_4 = castResult_3_4;
2897 }
2898 auto castResult_3_3 = device::V3_3::ICameraDeviceSession::castFrom(mHidlSession);
2899 if (castResult_3_3.isOk()) {
2900 mHidlSession_3_3 = castResult_3_3;
2901 }
2902}
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002903
Yin-Chia Yehb978c382019-10-30 00:22:37 -07002904Camera3Device::HalInterface::HalInterface() :
2905 mUseHalBufManager(false),
2906 mSupportOfflineProcessing(false) {}
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002907
2908Camera3Device::HalInterface::HalInterface(const HalInterface& other) :
Yifan Hongf79b5542017-04-11 14:44:25 -07002909 mHidlSession(other.mHidlSession),
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08002910 mRequestMetadataQueue(other.mRequestMetadataQueue),
Yin-Chia Yehb978c382019-10-30 00:22:37 -07002911 mUseHalBufManager(other.mUseHalBufManager),
2912 mSupportOfflineProcessing(other.mSupportOfflineProcessing) {}
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002913
2914bool Camera3Device::HalInterface::valid() {
Emilian Peev31abd0a2017-05-11 18:37:46 +01002915 return (mHidlSession != nullptr);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002916}
2917
2918void Camera3Device::HalInterface::clear() {
Yin-Chia Yehb978c382019-10-30 00:22:37 -07002919 mHidlSession_3_6.clear();
Emilian Peev644a3e12018-11-23 13:52:39 +00002920 mHidlSession_3_5.clear();
Emilian Peev9e740b02018-01-30 18:28:03 +00002921 mHidlSession_3_4.clear();
2922 mHidlSession_3_3.clear();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002923 mHidlSession.clear();
2924}
2925
2926status_t Camera3Device::HalInterface::constructDefaultRequestSettings(
2927 camera3_request_template_t templateId,
2928 /*out*/ camera_metadata_t **requestTemplate) {
2929 ATRACE_NAME("CameraHal::constructDefaultRequestSettings");
2930 if (!valid()) return INVALID_OPERATION;
2931 status_t res = OK;
2932
Emilian Peev31abd0a2017-05-11 18:37:46 +01002933 common::V1_0::Status status;
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002934
2935 auto requestCallback = [&status, &requestTemplate]
Emilian Peev31abd0a2017-05-11 18:37:46 +01002936 (common::V1_0::Status s, const device::V3_2::CameraMetadata& request) {
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002937 status = s;
2938 if (status == common::V1_0::Status::OK) {
2939 const camera_metadata *r =
2940 reinterpret_cast<const camera_metadata_t*>(request.data());
2941 size_t expectedSize = request.size();
2942 int ret = validate_camera_metadata_structure(r, &expectedSize);
2943 if (ret == OK || ret == CAMERA_METADATA_VALIDATION_SHIFTED) {
2944 *requestTemplate = clone_camera_metadata(r);
2945 if (*requestTemplate == nullptr) {
2946 ALOGE("%s: Unable to clone camera metadata received from HAL",
2947 __FUNCTION__);
Emilian Peev31abd0a2017-05-11 18:37:46 +01002948 status = common::V1_0::Status::INTERNAL_ERROR;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002949 }
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002950 } else {
2951 ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
2952 status = common::V1_0::Status::INTERNAL_ERROR;
Emilian Peev31abd0a2017-05-11 18:37:46 +01002953 }
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002954 }
2955 };
2956 hardware::Return<void> err;
Eino-Ville Talvala96441462018-02-06 11:41:55 -08002957 RequestTemplate id;
2958 switch (templateId) {
2959 case CAMERA3_TEMPLATE_PREVIEW:
2960 id = RequestTemplate::PREVIEW;
2961 break;
2962 case CAMERA3_TEMPLATE_STILL_CAPTURE:
2963 id = RequestTemplate::STILL_CAPTURE;
2964 break;
2965 case CAMERA3_TEMPLATE_VIDEO_RECORD:
2966 id = RequestTemplate::VIDEO_RECORD;
2967 break;
2968 case CAMERA3_TEMPLATE_VIDEO_SNAPSHOT:
2969 id = RequestTemplate::VIDEO_SNAPSHOT;
2970 break;
2971 case CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG:
2972 id = RequestTemplate::ZERO_SHUTTER_LAG;
2973 break;
2974 case CAMERA3_TEMPLATE_MANUAL:
2975 id = RequestTemplate::MANUAL;
2976 break;
2977 default:
2978 // Unknown template ID, or this HAL is too old to support it
2979 return BAD_VALUE;
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002980 }
Eino-Ville Talvala96441462018-02-06 11:41:55 -08002981 err = mHidlSession->constructDefaultRequestSettings(id, requestCallback);
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002982
Emilian Peev31abd0a2017-05-11 18:37:46 +01002983 if (!err.isOk()) {
2984 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
2985 res = DEAD_OBJECT;
2986 } else {
2987 res = CameraProviderManager::mapToStatusT(status);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002988 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01002989
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002990 return res;
2991}
2992
Emilian Peev4ec17882019-01-24 17:16:58 -08002993bool Camera3Device::HalInterface::isReconfigurationRequired(CameraMetadata& oldSessionParams,
2994 CameraMetadata& newSessionParams) {
2995 // We do reconfiguration by default;
2996 bool ret = true;
2997 if ((mHidlSession_3_5 != nullptr) && mIsReconfigurationQuerySupported) {
2998 android::hardware::hidl_vec<uint8_t> oldParams, newParams;
2999 camera_metadata_t* oldSessioMeta = const_cast<camera_metadata_t*>(
3000 oldSessionParams.getAndLock());
3001 camera_metadata_t* newSessioMeta = const_cast<camera_metadata_t*>(
3002 newSessionParams.getAndLock());
3003 oldParams.setToExternal(reinterpret_cast<uint8_t*>(oldSessioMeta),
3004 get_camera_metadata_size(oldSessioMeta));
3005 newParams.setToExternal(reinterpret_cast<uint8_t*>(newSessioMeta),
3006 get_camera_metadata_size(newSessioMeta));
3007 hardware::camera::common::V1_0::Status callStatus;
3008 bool required;
3009 auto hidlCb = [&callStatus, &required] (hardware::camera::common::V1_0::Status s,
3010 bool requiredFlag) {
3011 callStatus = s;
3012 required = requiredFlag;
3013 };
3014 auto err = mHidlSession_3_5->isReconfigurationRequired(oldParams, newParams, hidlCb);
3015 oldSessionParams.unlock(oldSessioMeta);
3016 newSessionParams.unlock(newSessioMeta);
3017 if (err.isOk()) {
3018 switch (callStatus) {
3019 case hardware::camera::common::V1_0::Status::OK:
3020 ret = required;
3021 break;
3022 case hardware::camera::common::V1_0::Status::METHOD_NOT_SUPPORTED:
3023 mIsReconfigurationQuerySupported = false;
3024 ret = true;
3025 break;
3026 default:
3027 ALOGV("%s: Reconfiguration query failed: %d", __FUNCTION__, callStatus);
3028 ret = true;
3029 }
3030 } else {
3031 ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, err.description().c_str());
3032 ret = true;
3033 }
3034 }
3035
3036 return ret;
3037}
3038
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01003039status_t Camera3Device::HalInterface::configureStreams(const camera_metadata_t *sessionParams,
Emilian Peev192ee832018-01-31 14:46:47 +00003040 camera3_stream_configuration *config, const std::vector<uint32_t>& bufferSizes) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003041 ATRACE_NAME("CameraHal::configureStreams");
3042 if (!valid()) return INVALID_OPERATION;
3043 status_t res = OK;
3044
Emilian Peev31abd0a2017-05-11 18:37:46 +01003045 // Convert stream config to HIDL
3046 std::set<int> activeStreams;
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003047 device::V3_2::StreamConfiguration requestedConfiguration3_2;
3048 device::V3_4::StreamConfiguration requestedConfiguration3_4;
3049 requestedConfiguration3_2.streams.resize(config->num_streams);
3050 requestedConfiguration3_4.streams.resize(config->num_streams);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003051 for (size_t i = 0; i < config->num_streams; i++) {
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003052 device::V3_2::Stream &dst3_2 = requestedConfiguration3_2.streams[i];
3053 device::V3_4::Stream &dst3_4 = requestedConfiguration3_4.streams[i];
Emilian Peev31abd0a2017-05-11 18:37:46 +01003054 camera3_stream_t *src = config->streams[i];
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003055
Emilian Peev31abd0a2017-05-11 18:37:46 +01003056 Camera3Stream* cam3stream = Camera3Stream::cast(src);
3057 cam3stream->setBufferFreedListener(this);
3058 int streamId = cam3stream->getId();
3059 StreamType streamType;
3060 switch (src->stream_type) {
3061 case CAMERA3_STREAM_OUTPUT:
3062 streamType = StreamType::OUTPUT;
3063 break;
3064 case CAMERA3_STREAM_INPUT:
3065 streamType = StreamType::INPUT;
3066 break;
3067 default:
3068 ALOGE("%s: Stream %d: Unsupported stream type %d",
3069 __FUNCTION__, streamId, config->streams[i]->stream_type);
3070 return BAD_VALUE;
3071 }
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003072 dst3_2.id = streamId;
3073 dst3_2.streamType = streamType;
3074 dst3_2.width = src->width;
3075 dst3_2.height = src->height;
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003076 dst3_2.usage = mapToConsumerUsage(cam3stream->getUsage());
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003077 dst3_2.rotation = mapToStreamRotation((camera3_stream_rotation_t) src->rotation);
Shuzhen Wang92653952019-05-07 15:11:43 -07003078 // For HidlSession version 3.5 or newer, the format and dataSpace sent
3079 // to HAL are original, not the overriden ones.
3080 if (mHidlSession_3_5 != nullptr) {
3081 dst3_2.format = mapToPixelFormat(cam3stream->isFormatOverridden() ?
3082 cam3stream->getOriginalFormat() : src->format);
3083 dst3_2.dataSpace = mapToHidlDataspace(cam3stream->isDataSpaceOverridden() ?
3084 cam3stream->getOriginalDataSpace() : src->data_space);
3085 } else {
3086 dst3_2.format = mapToPixelFormat(src->format);
3087 dst3_2.dataSpace = mapToHidlDataspace(src->data_space);
3088 }
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003089 dst3_4.v3_2 = dst3_2;
Emilian Peev192ee832018-01-31 14:46:47 +00003090 dst3_4.bufferSize = bufferSizes[i];
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003091 if (src->physical_camera_id != nullptr) {
3092 dst3_4.physicalCameraId = src->physical_camera_id;
3093 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003094
3095 activeStreams.insert(streamId);
3096 // Create Buffer ID map if necessary
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003097 mBufferRecords.tryCreateBufferCache(streamId);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003098 }
3099 // remove BufferIdMap for deleted streams
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003100 mBufferRecords.removeInactiveBufferCaches(activeStreams);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003101
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003102 StreamConfigurationMode operationMode;
Emilian Peev31abd0a2017-05-11 18:37:46 +01003103 res = mapToStreamConfigurationMode(
3104 (camera3_stream_configuration_mode_t) config->operation_mode,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003105 /*out*/ &operationMode);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003106 if (res != OK) {
3107 return res;
3108 }
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003109 requestedConfiguration3_2.operationMode = operationMode;
3110 requestedConfiguration3_4.operationMode = operationMode;
3111 requestedConfiguration3_4.sessionParams.setToExternal(
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01003112 reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams)),
3113 get_camera_metadata_size(sessionParams));
3114
Emilian Peev31abd0a2017-05-11 18:37:46 +01003115 // Invoke configureStreams
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003116 device::V3_3::HalStreamConfiguration finalConfiguration;
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003117 device::V3_4::HalStreamConfiguration finalConfiguration3_4;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003118 device::V3_6::HalStreamConfiguration finalConfiguration3_6;
Emilian Peev31abd0a2017-05-11 18:37:46 +01003119 common::V1_0::Status status;
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003120
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003121 auto configStream34Cb = [&status, &finalConfiguration3_4]
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003122 (common::V1_0::Status s, const device::V3_4::HalStreamConfiguration& halConfiguration) {
3123 finalConfiguration3_4 = halConfiguration;
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01003124 status = s;
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003125 };
3126
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003127 auto configStream36Cb = [&status, &finalConfiguration3_6]
3128 (common::V1_0::Status s, const device::V3_6::HalStreamConfiguration& halConfiguration) {
3129 finalConfiguration3_6 = halConfiguration;
3130 status = s;
3131 };
3132
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003133 auto postprocConfigStream34 = [&finalConfiguration, &finalConfiguration3_4]
3134 (hardware::Return<void>& err) -> status_t {
3135 if (!err.isOk()) {
3136 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3137 return DEAD_OBJECT;
3138 }
3139 finalConfiguration.streams.resize(finalConfiguration3_4.streams.size());
3140 for (size_t i = 0; i < finalConfiguration3_4.streams.size(); i++) {
3141 finalConfiguration.streams[i] = finalConfiguration3_4.streams[i].v3_3;
3142 }
3143 return OK;
3144 };
3145
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003146 auto postprocConfigStream36 = [&finalConfiguration, &finalConfiguration3_6]
3147 (hardware::Return<void>& err) -> status_t {
3148 if (!err.isOk()) {
3149 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3150 return DEAD_OBJECT;
3151 }
3152 finalConfiguration.streams.resize(finalConfiguration3_6.streams.size());
3153 for (size_t i = 0; i < finalConfiguration3_6.streams.size(); i++) {
3154 finalConfiguration.streams[i] = finalConfiguration3_6.streams[i].v3_4.v3_3;
3155 }
3156 return OK;
3157 };
3158
Shuzhen Wang92653952019-05-07 15:11:43 -07003159 // See which version of HAL we have
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003160 if (mHidlSession_3_6 != nullptr) {
3161 ALOGV("%s: v3.6 device found", __FUNCTION__);
3162 device::V3_5::StreamConfiguration requestedConfiguration3_5;
3163 requestedConfiguration3_5.v3_4 = requestedConfiguration3_4;
3164 requestedConfiguration3_5.streamConfigCounter = mNextStreamConfigCounter++;
3165 auto err = mHidlSession_3_6->configureStreams_3_6(
3166 requestedConfiguration3_5, configStream36Cb);
3167 res = postprocConfigStream36(err);
3168 if (res != OK) {
3169 return res;
3170 }
3171 } else if (mHidlSession_3_5 != nullptr) {
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003172 ALOGV("%s: v3.5 device found", __FUNCTION__);
3173 device::V3_5::StreamConfiguration requestedConfiguration3_5;
3174 requestedConfiguration3_5.v3_4 = requestedConfiguration3_4;
3175 requestedConfiguration3_5.streamConfigCounter = mNextStreamConfigCounter++;
3176 auto err = mHidlSession_3_5->configureStreams_3_5(
3177 requestedConfiguration3_5, configStream34Cb);
3178 res = postprocConfigStream34(err);
3179 if (res != OK) {
3180 return res;
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01003181 }
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003182 } else if (mHidlSession_3_4 != nullptr) {
3183 // We do; use v3.4 for the call
3184 ALOGV("%s: v3.4 device found", __FUNCTION__);
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003185 auto err = mHidlSession_3_4->configureStreams_3_4(
3186 requestedConfiguration3_4, configStream34Cb);
3187 res = postprocConfigStream34(err);
3188 if (res != OK) {
3189 return res;
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003190 }
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08003191 } else if (mHidlSession_3_3 != nullptr) {
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003192 // We do; use v3.3 for the call
3193 ALOGV("%s: v3.3 device found", __FUNCTION__);
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08003194 auto err = mHidlSession_3_3->configureStreams_3_3(requestedConfiguration3_2,
Emilian Peev31abd0a2017-05-11 18:37:46 +01003195 [&status, &finalConfiguration]
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003196 (common::V1_0::Status s, const device::V3_3::HalStreamConfiguration& halConfiguration) {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003197 finalConfiguration = halConfiguration;
3198 status = s;
3199 });
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003200 if (!err.isOk()) {
3201 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3202 return DEAD_OBJECT;
3203 }
3204 } else {
3205 // We don't; use v3.2 call and construct a v3.3 HalStreamConfiguration
3206 ALOGV("%s: v3.2 device found", __FUNCTION__);
3207 HalStreamConfiguration finalConfiguration_3_2;
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003208 auto err = mHidlSession->configureStreams(requestedConfiguration3_2,
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003209 [&status, &finalConfiguration_3_2]
3210 (common::V1_0::Status s, const HalStreamConfiguration& halConfiguration) {
3211 finalConfiguration_3_2 = halConfiguration;
3212 status = s;
3213 });
3214 if (!err.isOk()) {
3215 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3216 return DEAD_OBJECT;
3217 }
3218 finalConfiguration.streams.resize(finalConfiguration_3_2.streams.size());
3219 for (size_t i = 0; i < finalConfiguration_3_2.streams.size(); i++) {
3220 finalConfiguration.streams[i].v3_2 = finalConfiguration_3_2.streams[i];
3221 finalConfiguration.streams[i].overrideDataSpace =
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003222 requestedConfiguration3_2.streams[i].dataSpace;
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003223 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003224 }
3225
3226 if (status != common::V1_0::Status::OK ) {
3227 return CameraProviderManager::mapToStatusT(status);
3228 }
3229
3230 // And convert output stream configuration from HIDL
3231
3232 for (size_t i = 0; i < config->num_streams; i++) {
3233 camera3_stream_t *dst = config->streams[i];
3234 int streamId = Camera3Stream::cast(dst)->getId();
3235
3236 // Start scan at i, with the assumption that the stream order matches
3237 size_t realIdx = i;
3238 bool found = false;
Eino-Ville Talvala370875f2019-04-12 12:40:27 -07003239 size_t halStreamCount = finalConfiguration.streams.size();
3240 for (size_t idx = 0; idx < halStreamCount; idx++) {
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003241 if (finalConfiguration.streams[realIdx].v3_2.id == streamId) {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003242 found = true;
3243 break;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003244 }
Eino-Ville Talvala370875f2019-04-12 12:40:27 -07003245 realIdx = (realIdx >= halStreamCount - 1) ? 0 : realIdx + 1;
Emilian Peev31abd0a2017-05-11 18:37:46 +01003246 }
3247 if (!found) {
3248 ALOGE("%s: Stream %d not found in stream configuration response from HAL",
3249 __FUNCTION__, streamId);
3250 return INVALID_OPERATION;
3251 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003252 device::V3_3::HalStream &src = finalConfiguration.streams[realIdx];
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003253 device::V3_6::HalStream &src_36 = finalConfiguration3_6.streams[realIdx];
Yin-Chia Yeh77327052017-01-09 18:23:07 -08003254
Emilian Peev710c1422017-08-30 11:19:38 +01003255 Camera3Stream* dstStream = Camera3Stream::cast(dst);
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003256 int overrideFormat = mapToFrameworkFormat(src.v3_2.overrideFormat);
3257 android_dataspace overrideDataSpace = mapToFrameworkDataspace(src.overrideDataSpace);
3258
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003259 if (mHidlSession_3_6 != nullptr) {
3260 dstStream->setOfflineProcessingSupport(src_36.supportOffline);
3261 }
3262
Yin-Chia Yeh90667662019-07-01 15:45:00 -07003263 if (dstStream->getOriginalFormat() != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
Shuzhen Wang92653952019-05-07 15:11:43 -07003264 dstStream->setFormatOverride(false);
3265 dstStream->setDataSpaceOverride(false);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003266 if (dst->format != overrideFormat) {
3267 ALOGE("%s: Stream %d: Format override not allowed for format 0x%x", __FUNCTION__,
3268 streamId, dst->format);
Yin-Chia Yeh77327052017-01-09 18:23:07 -08003269 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003270 if (dst->data_space != overrideDataSpace) {
3271 ALOGE("%s: Stream %d: DataSpace override not allowed for format 0x%x", __FUNCTION__,
3272 streamId, dst->format);
3273 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003274 } else {
Shuzhen Wang92653952019-05-07 15:11:43 -07003275 bool needFormatOverride =
3276 requestedConfiguration3_2.streams[i].format != src.v3_2.overrideFormat;
3277 bool needDataspaceOverride =
3278 requestedConfiguration3_2.streams[i].dataSpace != src.overrideDataSpace;
Emilian Peev31abd0a2017-05-11 18:37:46 +01003279 // Override allowed with IMPLEMENTATION_DEFINED
Shuzhen Wang92653952019-05-07 15:11:43 -07003280 dstStream->setFormatOverride(needFormatOverride);
3281 dstStream->setDataSpaceOverride(needDataspaceOverride);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003282 dst->format = overrideFormat;
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003283 dst->data_space = overrideDataSpace;
Yin-Chia Yeh77327052017-01-09 18:23:07 -08003284 }
3285
Emilian Peev31abd0a2017-05-11 18:37:46 +01003286 if (dst->stream_type == CAMERA3_STREAM_INPUT) {
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003287 if (src.v3_2.producerUsage != 0) {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003288 ALOGE("%s: Stream %d: INPUT streams must have 0 for producer usage",
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003289 __FUNCTION__, streamId);
3290 return INVALID_OPERATION;
3291 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003292 dstStream->setUsage(
3293 mapConsumerToFrameworkUsage(src.v3_2.consumerUsage));
Emilian Peev31abd0a2017-05-11 18:37:46 +01003294 } else {
3295 // OUTPUT
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003296 if (src.v3_2.consumerUsage != 0) {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003297 ALOGE("%s: Stream %d: OUTPUT streams must have 0 for consumer usage",
3298 __FUNCTION__, streamId);
3299 return INVALID_OPERATION;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003300 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003301 dstStream->setUsage(
3302 mapProducerToFrameworkUsage(src.v3_2.producerUsage));
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003303 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003304 dst->max_buffers = src.v3_2.maxBuffers;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003305 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003306
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003307 return res;
3308}
3309
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003310status_t Camera3Device::HalInterface::wrapAsHidlRequest(camera3_capture_request_t* request,
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003311 /*out*/device::V3_2::CaptureRequest* captureRequest,
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003312 /*out*/std::vector<native_handle_t*>* handlesCreated,
3313 /*out*/std::vector<std::pair<int32_t, int32_t>>* inflightBuffers) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003314 ATRACE_CALL();
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003315 if (captureRequest == nullptr || handlesCreated == nullptr || inflightBuffers == nullptr) {
3316 ALOGE("%s: captureRequest (%p), handlesCreated (%p), and inflightBuffers(%p) "
3317 "must not be null", __FUNCTION__, captureRequest, handlesCreated, inflightBuffers);
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003318 return BAD_VALUE;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003319 }
3320
3321 captureRequest->frameNumber = request->frame_number;
Yifan Hongf79b5542017-04-11 14:44:25 -07003322
3323 captureRequest->fmqSettingsSize = 0;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003324
3325 {
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003326 if (request->input_buffer != nullptr) {
3327 int32_t streamId = Camera3Stream::cast(request->input_buffer->stream)->getId();
3328 buffer_handle_t buf = *(request->input_buffer->buffer);
3329 auto pair = getBufferId(buf, streamId);
3330 bool isNewBuffer = pair.first;
3331 uint64_t bufferId = pair.second;
3332 captureRequest->inputBuffer.streamId = streamId;
3333 captureRequest->inputBuffer.bufferId = bufferId;
3334 captureRequest->inputBuffer.buffer = (isNewBuffer) ? buf : nullptr;
3335 captureRequest->inputBuffer.status = BufferStatus::OK;
3336 native_handle_t *acquireFence = nullptr;
3337 if (request->input_buffer->acquire_fence != -1) {
3338 acquireFence = native_handle_create(1,0);
3339 acquireFence->data[0] = request->input_buffer->acquire_fence;
3340 handlesCreated->push_back(acquireFence);
3341 }
3342 captureRequest->inputBuffer.acquireFence = acquireFence;
3343 captureRequest->inputBuffer.releaseFence = nullptr;
3344
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003345 mBufferRecords.pushInflightBuffer(captureRequest->frameNumber, streamId,
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003346 request->input_buffer->buffer);
3347 inflightBuffers->push_back(std::make_pair(captureRequest->frameNumber, streamId));
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003348 } else {
3349 captureRequest->inputBuffer.streamId = -1;
3350 captureRequest->inputBuffer.bufferId = BUFFER_ID_NO_BUFFER;
3351 }
3352
3353 captureRequest->outputBuffers.resize(request->num_output_buffers);
3354 for (size_t i = 0; i < request->num_output_buffers; i++) {
3355 const camera3_stream_buffer_t *src = request->output_buffers + i;
3356 StreamBuffer &dst = captureRequest->outputBuffers[i];
3357 int32_t streamId = Camera3Stream::cast(src->stream)->getId();
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003358 if (src->buffer != nullptr) {
3359 buffer_handle_t buf = *(src->buffer);
3360 auto pair = getBufferId(buf, streamId);
3361 bool isNewBuffer = pair.first;
3362 dst.bufferId = pair.second;
3363 dst.buffer = isNewBuffer ? buf : nullptr;
3364 native_handle_t *acquireFence = nullptr;
3365 if (src->acquire_fence != -1) {
3366 acquireFence = native_handle_create(1,0);
3367 acquireFence->data[0] = src->acquire_fence;
3368 handlesCreated->push_back(acquireFence);
3369 }
3370 dst.acquireFence = acquireFence;
3371 } else if (mUseHalBufManager) {
3372 // HAL buffer management path
3373 dst.bufferId = BUFFER_ID_NO_BUFFER;
3374 dst.buffer = nullptr;
3375 dst.acquireFence = nullptr;
3376 } else {
3377 ALOGE("%s: cannot send a null buffer in capture request!", __FUNCTION__);
3378 return BAD_VALUE;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003379 }
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003380 dst.streamId = streamId;
3381 dst.status = BufferStatus::OK;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003382 dst.releaseFence = nullptr;
3383
Yin-Chia Yeh5f840f82019-03-05 11:59:04 -08003384 // Output buffers are empty when using HAL buffer manager
3385 if (!mUseHalBufManager) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003386 mBufferRecords.pushInflightBuffer(
3387 captureRequest->frameNumber, streamId, src->buffer);
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003388 inflightBuffers->push_back(std::make_pair(captureRequest->frameNumber, streamId));
Yin-Chia Yeh5f840f82019-03-05 11:59:04 -08003389 }
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003390 }
3391 }
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003392 return OK;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003393}
3394
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003395void Camera3Device::HalInterface::cleanupNativeHandles(
3396 std::vector<native_handle_t*> *handles, bool closeFd) {
3397 if (handles == nullptr) {
3398 return;
3399 }
3400 if (closeFd) {
3401 for (auto& handle : *handles) {
3402 native_handle_close(handle);
3403 }
3404 }
3405 for (auto& handle : *handles) {
3406 native_handle_delete(handle);
3407 }
3408 handles->clear();
3409 return;
3410}
3411
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003412status_t Camera3Device::HalInterface::processBatchCaptureRequests(
3413 std::vector<camera3_capture_request_t*>& requests,/*out*/uint32_t* numRequestProcessed) {
3414 ATRACE_NAME("CameraHal::processBatchCaptureRequests");
3415 if (!valid()) return INVALID_OPERATION;
3416
Emilian Peevaebbe412018-01-15 13:53:24 +00003417 sp<device::V3_4::ICameraDeviceSession> hidlSession_3_4;
3418 auto castResult_3_4 = device::V3_4::ICameraDeviceSession::castFrom(mHidlSession);
3419 if (castResult_3_4.isOk()) {
3420 hidlSession_3_4 = castResult_3_4;
3421 }
3422
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003423 hardware::hidl_vec<device::V3_2::CaptureRequest> captureRequests;
Emilian Peevaebbe412018-01-15 13:53:24 +00003424 hardware::hidl_vec<device::V3_4::CaptureRequest> captureRequests_3_4;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003425 size_t batchSize = requests.size();
Emilian Peevaebbe412018-01-15 13:53:24 +00003426 if (hidlSession_3_4 != nullptr) {
3427 captureRequests_3_4.resize(batchSize);
3428 } else {
3429 captureRequests.resize(batchSize);
3430 }
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003431 std::vector<native_handle_t*> handlesCreated;
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003432 std::vector<std::pair<int32_t, int32_t>> inflightBuffers;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003433
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003434 status_t res = OK;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003435 for (size_t i = 0; i < batchSize; i++) {
Emilian Peevaebbe412018-01-15 13:53:24 +00003436 if (hidlSession_3_4 != nullptr) {
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003437 res = wrapAsHidlRequest(requests[i], /*out*/&captureRequests_3_4[i].v3_2,
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003438 /*out*/&handlesCreated, /*out*/&inflightBuffers);
Emilian Peevaebbe412018-01-15 13:53:24 +00003439 } else {
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003440 res = wrapAsHidlRequest(requests[i], /*out*/&captureRequests[i],
3441 /*out*/&handlesCreated, /*out*/&inflightBuffers);
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003442 }
3443 if (res != OK) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003444 mBufferRecords.popInflightBuffers(inflightBuffers);
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003445 cleanupNativeHandles(&handlesCreated);
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003446 return res;
Emilian Peevaebbe412018-01-15 13:53:24 +00003447 }
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003448 }
3449
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003450 std::vector<device::V3_2::BufferCache> cachesToRemove;
3451 {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003452 std::lock_guard<std::mutex> lock(mFreedBuffersLock);
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003453 for (auto& pair : mFreedBuffers) {
3454 // The stream might have been removed since onBufferFreed
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003455 if (mBufferRecords.isStreamCached(pair.first)) {
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003456 cachesToRemove.push_back({pair.first, pair.second});
3457 }
3458 }
3459 mFreedBuffers.clear();
3460 }
3461
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003462 common::V1_0::Status status = common::V1_0::Status::INTERNAL_ERROR;
3463 *numRequestProcessed = 0;
Yifan Hongf79b5542017-04-11 14:44:25 -07003464
3465 // Write metadata to FMQ.
3466 for (size_t i = 0; i < batchSize; i++) {
3467 camera3_capture_request_t* request = requests[i];
Emilian Peevaebbe412018-01-15 13:53:24 +00003468 device::V3_2::CaptureRequest* captureRequest;
3469 if (hidlSession_3_4 != nullptr) {
3470 captureRequest = &captureRequests_3_4[i].v3_2;
3471 } else {
3472 captureRequest = &captureRequests[i];
3473 }
Yifan Hongf79b5542017-04-11 14:44:25 -07003474
3475 if (request->settings != nullptr) {
3476 size_t settingsSize = get_camera_metadata_size(request->settings);
3477 if (mRequestMetadataQueue != nullptr && mRequestMetadataQueue->write(
3478 reinterpret_cast<const uint8_t*>(request->settings), settingsSize)) {
3479 captureRequest->settings.resize(0);
3480 captureRequest->fmqSettingsSize = settingsSize;
3481 } else {
3482 if (mRequestMetadataQueue != nullptr) {
3483 ALOGW("%s: couldn't utilize fmq, fallback to hwbinder", __FUNCTION__);
3484 }
3485 captureRequest->settings.setToExternal(
3486 reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(request->settings)),
3487 get_camera_metadata_size(request->settings));
3488 captureRequest->fmqSettingsSize = 0u;
3489 }
3490 } else {
3491 // A null request settings maps to a size-0 CameraMetadata
3492 captureRequest->settings.resize(0);
3493 captureRequest->fmqSettingsSize = 0u;
3494 }
Emilian Peevaebbe412018-01-15 13:53:24 +00003495
3496 if (hidlSession_3_4 != nullptr) {
3497 captureRequests_3_4[i].physicalCameraSettings.resize(request->num_physcam_settings);
3498 for (size_t j = 0; j < request->num_physcam_settings; j++) {
Emilian Peev00420d22018-02-05 21:33:13 +00003499 if (request->physcam_settings != nullptr) {
3500 size_t settingsSize = get_camera_metadata_size(request->physcam_settings[j]);
3501 if (mRequestMetadataQueue != nullptr && mRequestMetadataQueue->write(
3502 reinterpret_cast<const uint8_t*>(request->physcam_settings[j]),
3503 settingsSize)) {
3504 captureRequests_3_4[i].physicalCameraSettings[j].settings.resize(0);
3505 captureRequests_3_4[i].physicalCameraSettings[j].fmqSettingsSize =
3506 settingsSize;
3507 } else {
3508 if (mRequestMetadataQueue != nullptr) {
3509 ALOGW("%s: couldn't utilize fmq, fallback to hwbinder", __FUNCTION__);
3510 }
3511 captureRequests_3_4[i].physicalCameraSettings[j].settings.setToExternal(
3512 reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(
3513 request->physcam_settings[j])),
3514 get_camera_metadata_size(request->physcam_settings[j]));
3515 captureRequests_3_4[i].physicalCameraSettings[j].fmqSettingsSize = 0u;
Emilian Peevaebbe412018-01-15 13:53:24 +00003516 }
Emilian Peev00420d22018-02-05 21:33:13 +00003517 } else {
Emilian Peevaebbe412018-01-15 13:53:24 +00003518 captureRequests_3_4[i].physicalCameraSettings[j].fmqSettingsSize = 0u;
Emilian Peev00420d22018-02-05 21:33:13 +00003519 captureRequests_3_4[i].physicalCameraSettings[j].settings.resize(0);
Emilian Peevaebbe412018-01-15 13:53:24 +00003520 }
3521 captureRequests_3_4[i].physicalCameraSettings[j].physicalCameraId =
3522 request->physcam_id[j];
3523 }
3524 }
Yifan Hongf79b5542017-04-11 14:44:25 -07003525 }
Emilian Peevaebbe412018-01-15 13:53:24 +00003526
3527 hardware::details::return_status err;
Jayant Chowdharyc8d581e2018-07-16 14:46:23 -07003528 auto resultCallback =
3529 [&status, &numRequestProcessed] (auto s, uint32_t n) {
3530 status = s;
3531 *numRequestProcessed = n;
3532 };
Emilian Peevaebbe412018-01-15 13:53:24 +00003533 if (hidlSession_3_4 != nullptr) {
3534 err = hidlSession_3_4->processCaptureRequest_3_4(captureRequests_3_4, cachesToRemove,
Jayant Chowdharyc8d581e2018-07-16 14:46:23 -07003535 resultCallback);
Emilian Peevaebbe412018-01-15 13:53:24 +00003536 } else {
3537 err = mHidlSession->processCaptureRequest(captureRequests, cachesToRemove,
Jayant Chowdharyc8d581e2018-07-16 14:46:23 -07003538 resultCallback);
Emilian Peevaebbe412018-01-15 13:53:24 +00003539 }
Eino-Ville Talvalac5cbb872017-04-27 12:48:33 -07003540 if (!err.isOk()) {
3541 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003542 status = common::V1_0::Status::CAMERA_DISCONNECTED;
Eino-Ville Talvalac5cbb872017-04-27 12:48:33 -07003543 }
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003544
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003545 if (status == common::V1_0::Status::OK && *numRequestProcessed != batchSize) {
3546 ALOGE("%s: processCaptureRequest returns OK but processed %d/%zu requests",
3547 __FUNCTION__, *numRequestProcessed, batchSize);
3548 status = common::V1_0::Status::INTERNAL_ERROR;
3549 }
3550
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003551 res = CameraProviderManager::mapToStatusT(status);
3552 if (res == OK) {
3553 if (mHidlSession->isRemote()) {
3554 // Only close acquire fence FDs when the HIDL transaction succeeds (so the FDs have been
3555 // sent to camera HAL processes)
3556 cleanupNativeHandles(&handlesCreated, /*closeFd*/true);
3557 } else {
3558 // In passthrough mode the FDs are now owned by HAL
3559 cleanupNativeHandles(&handlesCreated);
3560 }
3561 } else {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003562 mBufferRecords.popInflightBuffers(inflightBuffers);
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003563 cleanupNativeHandles(&handlesCreated);
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003564 }
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003565 return res;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003566}
3567
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003568status_t Camera3Device::HalInterface::flush() {
3569 ATRACE_NAME("CameraHal::flush");
3570 if (!valid()) return INVALID_OPERATION;
3571 status_t res = OK;
3572
Emilian Peev31abd0a2017-05-11 18:37:46 +01003573 auto err = mHidlSession->flush();
3574 if (!err.isOk()) {
3575 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3576 res = DEAD_OBJECT;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003577 } else {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003578 res = CameraProviderManager::mapToStatusT(err);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003579 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003580
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003581 return res;
3582}
3583
Emilian Peev31abd0a2017-05-11 18:37:46 +01003584status_t Camera3Device::HalInterface::dump(int /*fd*/) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003585 ATRACE_NAME("CameraHal::dump");
3586 if (!valid()) return INVALID_OPERATION;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003587
Emilian Peev31abd0a2017-05-11 18:37:46 +01003588 // Handled by CameraProviderManager::dump
3589
3590 return OK;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003591}
3592
3593status_t Camera3Device::HalInterface::close() {
3594 ATRACE_NAME("CameraHal::close()");
3595 if (!valid()) return INVALID_OPERATION;
3596 status_t res = OK;
3597
Emilian Peev31abd0a2017-05-11 18:37:46 +01003598 auto err = mHidlSession->close();
3599 // Interface will be dead shortly anyway, so don't log errors
3600 if (!err.isOk()) {
3601 res = DEAD_OBJECT;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003602 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003603
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003604 return res;
3605}
3606
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003607void Camera3Device::HalInterface::signalPipelineDrain(const std::vector<int>& streamIds) {
3608 ATRACE_NAME("CameraHal::signalPipelineDrain");
3609 if (!valid() || mHidlSession_3_5 == nullptr) {
3610 ALOGE("%s called on invalid camera!", __FUNCTION__);
3611 return;
3612 }
3613
Yin-Chia Yehc300a072019-02-13 14:56:57 -08003614 auto err = mHidlSession_3_5->signalStreamFlush(streamIds, mNextStreamConfigCounter - 1);
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003615 if (!err.isOk()) {
3616 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3617 return;
3618 }
3619}
3620
Yin-Chia Yehb978c382019-10-30 00:22:37 -07003621status_t Camera3Device::HalInterface::switchToOffline(
3622 const std::vector<int32_t>& streamsToKeep,
3623 /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003624 /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
3625 /*out*/camera3::BufferRecords* bufferRecords) {
Yin-Chia Yehb978c382019-10-30 00:22:37 -07003626 ATRACE_NAME("CameraHal::switchToOffline");
3627 if (!valid() || mHidlSession_3_6 == nullptr) {
3628 ALOGE("%s called on invalid camera!", __FUNCTION__);
3629 return INVALID_OPERATION;
3630 }
3631
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003632 if (offlineSessionInfo == nullptr || offlineSession == nullptr || bufferRecords == nullptr) {
3633 ALOGE("%s: output arguments must not be null!", __FUNCTION__);
Yin-Chia Yehb978c382019-10-30 00:22:37 -07003634 return INVALID_OPERATION;
3635 }
3636
3637 common::V1_0::Status status = common::V1_0::Status::INTERNAL_ERROR;
Yin-Chia Yehb978c382019-10-30 00:22:37 -07003638 auto resultCallback =
3639 [&status, &offlineSessionInfo, &offlineSession] (auto s, auto info, auto session) {
3640 status = s;
3641 *offlineSessionInfo = info;
3642 *offlineSession = session;
3643 };
3644 auto err = mHidlSession_3_6->switchToOffline(streamsToKeep, resultCallback);
3645
3646 if (!err.isOk()) {
3647 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3648 return DEAD_OBJECT;
3649 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003650
3651 status_t ret = CameraProviderManager::mapToStatusT(status);
3652 if (ret != OK) {
3653 return ret;
3654 }
3655
3656 // TODO: assert no ongoing requestBuffer/returnBuffer call here
3657 // TODO: update RequestBufferStateMachine to block requestBuffer/returnBuffer once HAL
3658 // returns from switchToOffline.
3659
3660
3661 // Validate buffer caches
3662 std::vector<int32_t> streams;
3663 streams.reserve(offlineSessionInfo->offlineStreams.size());
3664 for (auto offlineStream : offlineSessionInfo->offlineStreams) {
3665 int32_t id = offlineStream.id;
3666 streams.push_back(id);
3667 // Verify buffer caches
3668 std::vector<uint64_t> bufIds(offlineStream.circulatingBufferIds.begin(),
3669 offlineStream.circulatingBufferIds.end());
3670 if (!verifyBufferIds(id, bufIds)) {
3671 ALOGE("%s: stream ID %d buffer cache records mismatch!", __FUNCTION__, id);
3672 return UNKNOWN_ERROR;
3673 }
3674 }
3675
3676 // Move buffer records
3677 bufferRecords->takeBufferCaches(mBufferRecords, streams);
3678 bufferRecords->takeInflightBufferMap(mBufferRecords);
3679 bufferRecords->takeRequestedBufferMap(mBufferRecords);
3680 return ret;
Yin-Chia Yehb978c382019-10-30 00:22:37 -07003681}
3682
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07003683void Camera3Device::HalInterface::getInflightBufferKeys(
3684 std::vector<std::pair<int32_t, int32_t>>* out) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003685 mBufferRecords.getInflightBufferKeys(out);
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07003686 return;
3687}
3688
Yin-Chia Yeh84be5782019-03-01 11:47:02 -08003689void Camera3Device::HalInterface::getInflightRequestBufferKeys(
3690 std::vector<uint64_t>* out) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003691 mBufferRecords.getInflightRequestBufferKeys(out);
Yin-Chia Yeh84be5782019-03-01 11:47:02 -08003692 return;
3693}
3694
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003695bool Camera3Device::HalInterface::verifyBufferIds(
3696 int32_t streamId, std::vector<uint64_t>& bufIds) {
3697 return mBufferRecords.verifyBufferIds(streamId, bufIds);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003698}
3699
3700status_t Camera3Device::HalInterface::popInflightBuffer(
Yin-Chia Yehf4650602017-01-10 13:13:39 -08003701 int32_t frameNumber, int32_t streamId,
3702 /*out*/ buffer_handle_t **buffer) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003703 return mBufferRecords.popInflightBuffer(frameNumber, streamId, buffer);
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003704}
3705
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07003706status_t Camera3Device::HalInterface::pushInflightRequestBuffer(
Yin-Chia Yeh84be5782019-03-01 11:47:02 -08003707 uint64_t bufferId, buffer_handle_t* buf, int32_t streamId) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003708 return mBufferRecords.pushInflightRequestBuffer(bufferId, buf, streamId);
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07003709}
3710
3711// Find and pop a buffer_handle_t based on bufferId
3712status_t Camera3Device::HalInterface::popInflightRequestBuffer(
Yin-Chia Yeh84be5782019-03-01 11:47:02 -08003713 uint64_t bufferId,
3714 /*out*/ buffer_handle_t** buffer,
3715 /*optional out*/ int32_t* streamId) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003716 return mBufferRecords.popInflightRequestBuffer(bufferId, buffer, streamId);
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07003717}
3718
Yin-Chia Yeh77327052017-01-09 18:23:07 -08003719std::pair<bool, uint64_t> Camera3Device::HalInterface::getBufferId(
3720 const buffer_handle_t& buf, int streamId) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003721 return mBufferRecords.getBufferId(buf, streamId);
Yin-Chia Yeh77327052017-01-09 18:23:07 -08003722}
3723
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003724void Camera3Device::HalInterface::onBufferFreed(
3725 int streamId, const native_handle_t* handle) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003726 uint32_t bufferId = mBufferRecords.removeOneBufferCache(streamId, handle);
3727 std::lock_guard<std::mutex> lock(mFreedBuffersLock);
3728 if (bufferId != BUFFER_ID_NO_BUFFER) {
3729 mFreedBuffers.push_back(std::make_pair(streamId, bufferId));
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003730 }
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003731}
3732
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07003733void Camera3Device::HalInterface::onStreamReConfigured(int streamId) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003734 std::vector<uint64_t> bufIds = mBufferRecords.clearBufferCaches(streamId);
3735 std::lock_guard<std::mutex> lock(mFreedBuffersLock);
3736 for (auto bufferId : bufIds) {
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07003737 mFreedBuffers.push_back(std::make_pair(streamId, bufferId));
3738 }
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07003739}
3740
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003741/**
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003742 * RequestThread inner class methods
3743 */
3744
3745Camera3Device::RequestThread::RequestThread(wp<Camera3Device> parent,
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07003746 sp<StatusTracker> statusTracker,
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07003747 sp<HalInterface> interface, const Vector<int32_t>& sessionParamKeys,
3748 bool useHalBufManager) :
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07003749 Thread(/*canCallJava*/false),
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003750 mParent(parent),
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07003751 mStatusTracker(statusTracker),
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003752 mInterface(interface),
Eino-Ville Talvala77c1a352016-06-13 12:32:43 -07003753 mListener(nullptr),
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07003754 mId(getId(parent)),
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003755 mReconfigured(false),
3756 mDoPause(false),
3757 mPaused(true),
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003758 mNotifyPipelineDrain(false),
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003759 mFrameNumber(0),
Jianing Weicb0652e2014-03-12 18:29:36 -07003760 mLatestRequestId(NAME_NOT_FOUND),
Yin-Chia Yehc00a25c2014-08-21 14:27:44 -07003761 mCurrentAfTriggerId(0),
3762 mCurrentPreCaptureTriggerId(0),
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08003763 mRotateAndCropOverride(ANDROID_SCALER_ROTATE_AND_CROP_NONE),
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003764 mRepeatingLastFrameNumber(
3765 hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES),
Shuzhen Wang686f6442017-06-20 16:16:04 -07003766 mPrepareVideoStream(false),
Emilian Peeva14b4dd2018-05-15 11:00:31 +01003767 mConstrainedMode(false),
Emilian Peevac3ce6c2017-12-12 15:27:02 +00003768 mRequestLatency(kRequestLatencyBinSize),
3769 mSessionParamKeys(sessionParamKeys),
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07003770 mLatestSessionParams(sessionParamKeys.size()),
3771 mUseHalBufManager(useHalBufManager) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07003772 mStatusId = statusTracker->addComponent();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003773}
3774
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003775Camera3Device::RequestThread::~RequestThread() {}
3776
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07003777void Camera3Device::RequestThread::setNotificationListener(
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07003778 wp<NotificationListener> listener) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003779 ATRACE_CALL();
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003780 Mutex::Autolock l(mRequestLock);
3781 mListener = listener;
3782}
3783
Emilian Peevac3ce6c2017-12-12 15:27:02 +00003784void Camera3Device::RequestThread::configurationComplete(bool isConstrainedHighSpeed,
3785 const CameraMetadata& sessionParams) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003786 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003787 Mutex::Autolock l(mRequestLock);
3788 mReconfigured = true;
Emilian Peevac3ce6c2017-12-12 15:27:02 +00003789 mLatestSessionParams = sessionParams;
Chien-Yu Chenc66969b2016-05-19 16:37:51 -07003790 // Prepare video stream for high speed recording.
3791 mPrepareVideoStream = isConstrainedHighSpeed;
Emilian Peeva14b4dd2018-05-15 11:00:31 +01003792 mConstrainedMode = isConstrainedHighSpeed;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003793}
3794
Jianing Wei90e59c92014-03-12 18:29:36 -07003795status_t Camera3Device::RequestThread::queueRequestList(
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003796 List<sp<CaptureRequest> > &requests,
3797 /*out*/
3798 int64_t *lastFrameNumber) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003799 ATRACE_CALL();
Jianing Wei90e59c92014-03-12 18:29:36 -07003800 Mutex::Autolock l(mRequestLock);
3801 for (List<sp<CaptureRequest> >::iterator it = requests.begin(); it != requests.end();
3802 ++it) {
3803 mRequestQueue.push_back(*it);
3804 }
3805
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003806 if (lastFrameNumber != NULL) {
3807 *lastFrameNumber = mFrameNumber + mRequestQueue.size() - 1;
3808 ALOGV("%s: requestId %d, mFrameNumber %" PRId32 ", lastFrameNumber %" PRId64 ".",
3809 __FUNCTION__, (*(requests.begin()))->mResultExtras.requestId, mFrameNumber,
3810 *lastFrameNumber);
3811 }
Jianing Weicb0652e2014-03-12 18:29:36 -07003812
Jianing Wei90e59c92014-03-12 18:29:36 -07003813 unpauseForNewRequests();
3814
3815 return OK;
3816}
3817
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003818
3819status_t Camera3Device::RequestThread::queueTrigger(
3820 RequestTrigger trigger[],
3821 size_t count) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003822 ATRACE_CALL();
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003823 Mutex::Autolock l(mTriggerMutex);
3824 status_t ret;
3825
3826 for (size_t i = 0; i < count; ++i) {
3827 ret = queueTriggerLocked(trigger[i]);
3828
3829 if (ret != OK) {
3830 return ret;
3831 }
3832 }
3833
3834 return OK;
3835}
3836
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003837const String8& Camera3Device::RequestThread::getId(const wp<Camera3Device> &device) {
3838 static String8 deadId("<DeadDevice>");
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07003839 sp<Camera3Device> d = device.promote();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003840 if (d != nullptr) return d->mId;
3841 return deadId;
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07003842}
3843
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003844status_t Camera3Device::RequestThread::queueTriggerLocked(
3845 RequestTrigger trigger) {
3846
3847 uint32_t tag = trigger.metadataTag;
3848 ssize_t index = mTriggerMap.indexOfKey(tag);
3849
3850 switch (trigger.getTagType()) {
3851 case TYPE_BYTE:
3852 // fall-through
3853 case TYPE_INT32:
3854 break;
3855 default:
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07003856 ALOGE("%s: Type not supported: 0x%x", __FUNCTION__,
3857 trigger.getTagType());
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003858 return INVALID_OPERATION;
3859 }
3860
3861 /**
3862 * Collect only the latest trigger, since we only have 1 field
3863 * in the request settings per trigger tag, and can't send more than 1
3864 * trigger per request.
3865 */
3866 if (index != NAME_NOT_FOUND) {
3867 mTriggerMap.editValueAt(index) = trigger;
3868 } else {
3869 mTriggerMap.add(tag, trigger);
3870 }
3871
3872 return OK;
3873}
3874
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003875status_t Camera3Device::RequestThread::setRepeatingRequests(
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003876 const RequestList &requests,
3877 /*out*/
3878 int64_t *lastFrameNumber) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003879 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003880 Mutex::Autolock l(mRequestLock);
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003881 if (lastFrameNumber != NULL) {
3882 *lastFrameNumber = mRepeatingLastFrameNumber;
3883 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003884 mRepeatingRequests.clear();
3885 mRepeatingRequests.insert(mRepeatingRequests.begin(),
3886 requests.begin(), requests.end());
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07003887
3888 unpauseForNewRequests();
3889
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003890 mRepeatingLastFrameNumber = hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003891 return OK;
3892}
3893
Chih-Hung Hsieh8b0b9712016-08-09 14:25:53 -07003894bool Camera3Device::RequestThread::isRepeatingRequestLocked(const sp<CaptureRequest>& requestIn) {
Yin-Chia Yeh8684b7f2014-06-13 14:53:05 -07003895 if (mRepeatingRequests.empty()) {
3896 return false;
3897 }
3898 int32_t requestId = requestIn->mResultExtras.requestId;
3899 const RequestList &repeatRequests = mRepeatingRequests;
3900 // All repeating requests are guaranteed to have same id so only check first quest
3901 const sp<CaptureRequest> firstRequest = *repeatRequests.begin();
3902 return (firstRequest->mResultExtras.requestId == requestId);
3903}
3904
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003905status_t Camera3Device::RequestThread::clearRepeatingRequests(/*out*/int64_t *lastFrameNumber) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003906 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003907 Mutex::Autolock l(mRequestLock);
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07003908 return clearRepeatingRequestsLocked(lastFrameNumber);
3909
3910}
3911
3912status_t Camera3Device::RequestThread::clearRepeatingRequestsLocked(/*out*/int64_t *lastFrameNumber) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003913 mRepeatingRequests.clear();
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003914 if (lastFrameNumber != NULL) {
3915 *lastFrameNumber = mRepeatingLastFrameNumber;
3916 }
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003917 mRepeatingLastFrameNumber = hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003918 return OK;
3919}
3920
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003921status_t Camera3Device::RequestThread::clear(
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003922 /*out*/int64_t *lastFrameNumber) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003923 ATRACE_CALL();
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07003924 Mutex::Autolock l(mRequestLock);
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003925 ALOGV("RequestThread::%s:", __FUNCTION__);
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003926
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07003927 mRepeatingRequests.clear();
Yin-Chia Yeh8684b7f2014-06-13 14:53:05 -07003928
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003929 // Send errors for all requests pending in the request queue, including
3930 // pending repeating requests
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07003931 sp<NotificationListener> listener = mListener.promote();
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003932 if (listener != NULL) {
3933 for (RequestList::iterator it = mRequestQueue.begin();
3934 it != mRequestQueue.end(); ++it) {
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07003935 // Abort the input buffers for reprocess requests.
3936 if ((*it)->mInputStream != NULL) {
3937 camera3_stream_buffer_t inputBuffer;
Eino-Ville Talvalaba435252017-06-21 16:07:25 -07003938 status_t res = (*it)->mInputStream->getInputBuffer(&inputBuffer,
3939 /*respectHalLimit*/ false);
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07003940 if (res != OK) {
3941 ALOGW("%s: %d: couldn't get input buffer while clearing the request "
3942 "list: %s (%d)", __FUNCTION__, __LINE__, strerror(-res), res);
3943 } else {
Shuzhen Wang0cf01cb2019-09-05 13:33:06 -07003944 inputBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07003945 res = (*it)->mInputStream->returnInputBuffer(inputBuffer);
3946 if (res != OK) {
3947 ALOGE("%s: %d: couldn't return input buffer while clearing the request "
3948 "list: %s (%d)", __FUNCTION__, __LINE__, strerror(-res), res);
3949 }
3950 }
3951 }
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003952 // Set the frame number this request would have had, if it
3953 // had been submitted; this frame number will not be reused.
3954 // The requestId and burstId fields were set when the request was
3955 // submitted originally (in convertMetadataListToRequestListLocked)
3956 (*it)->mResultExtras.frameNumber = mFrameNumber++;
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003957 listener->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003958 (*it)->mResultExtras);
Yin-Chia Yeh8684b7f2014-06-13 14:53:05 -07003959 }
3960 }
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07003961 mRequestQueue.clear();
Jinguang Dongb26e7a02016-11-14 16:04:02 +08003962
3963 Mutex::Autolock al(mTriggerMutex);
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07003964 mTriggerMap.clear();
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003965 if (lastFrameNumber != NULL) {
3966 *lastFrameNumber = mRepeatingLastFrameNumber;
3967 }
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003968 mRepeatingLastFrameNumber = hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES;
Emilian Peev8dae54c2019-12-02 15:17:17 -08003969 mRequestSignal.signal();
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07003970 return OK;
3971}
3972
Chien-Yu Chen85a64552015-08-28 15:46:12 -07003973status_t Camera3Device::RequestThread::flush() {
3974 ATRACE_CALL();
3975 Mutex::Autolock l(mFlushLock);
3976
Emilian Peev08dd2452017-04-06 16:55:14 +01003977 return mInterface->flush();
Chien-Yu Chen85a64552015-08-28 15:46:12 -07003978}
3979
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003980void Camera3Device::RequestThread::setPaused(bool paused) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003981 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003982 Mutex::Autolock l(mPauseLock);
3983 mDoPause = paused;
3984 mDoPauseSignal.signal();
3985}
3986
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003987status_t Camera3Device::RequestThread::waitUntilRequestProcessed(
3988 int32_t requestId, nsecs_t timeout) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003989 ATRACE_CALL();
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003990 Mutex::Autolock l(mLatestRequestMutex);
3991 status_t res;
3992 while (mLatestRequestId != requestId) {
3993 nsecs_t startTime = systemTime();
3994
3995 res = mLatestRequestSignal.waitRelative(mLatestRequestMutex, timeout);
3996 if (res != OK) return res;
3997
3998 timeout -= (systemTime() - startTime);
3999 }
4000
4001 return OK;
4002}
4003
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004004void Camera3Device::RequestThread::requestExit() {
4005 // Call parent to set up shutdown
4006 Thread::requestExit();
4007 // The exit from any possible waits
4008 mDoPauseSignal.signal();
4009 mRequestSignal.signal();
Shuzhen Wang686f6442017-06-20 16:16:04 -07004010
4011 mRequestLatency.log("ProcessCaptureRequest latency histogram");
4012 mRequestLatency.reset();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004013}
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004014
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07004015void Camera3Device::RequestThread::checkAndStopRepeatingRequest() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004016 ATRACE_CALL();
Yin-Chia Yeh473fad92016-05-23 15:54:41 -07004017 bool surfaceAbandoned = false;
4018 int64_t lastFrameNumber = 0;
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07004019 sp<NotificationListener> listener;
Yin-Chia Yeh473fad92016-05-23 15:54:41 -07004020 {
4021 Mutex::Autolock l(mRequestLock);
4022 // Check all streams needed by repeating requests are still valid. Otherwise, stop
4023 // repeating requests.
4024 for (const auto& request : mRepeatingRequests) {
4025 for (const auto& s : request->mOutputStreams) {
4026 if (s->isAbandoned()) {
4027 surfaceAbandoned = true;
4028 clearRepeatingRequestsLocked(&lastFrameNumber);
4029 break;
4030 }
4031 }
4032 if (surfaceAbandoned) {
4033 break;
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07004034 }
4035 }
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07004036 listener = mListener.promote();
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07004037 }
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07004038
4039 if (listener != NULL && surfaceAbandoned) {
4040 listener->notifyRepeatingRequestError(lastFrameNumber);
Yin-Chia Yeh473fad92016-05-23 15:54:41 -07004041 }
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07004042}
4043
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004044bool Camera3Device::RequestThread::sendRequestsBatch() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004045 ATRACE_CALL();
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004046 status_t res;
4047 size_t batchSize = mNextRequests.size();
4048 std::vector<camera3_capture_request_t*> requests(batchSize);
4049 uint32_t numRequestProcessed = 0;
4050 for (size_t i = 0; i < batchSize; i++) {
4051 requests[i] = &mNextRequests.editItemAt(i).halRequest;
Yin-Chia Yeh885691c2018-05-01 15:54:24 -07004052 ATRACE_ASYNC_BEGIN("frame capture", mNextRequests[i].halRequest.frame_number);
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004053 }
4054
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004055 res = mInterface->processBatchCaptureRequests(requests, &numRequestProcessed);
4056
4057 bool triggerRemoveFailed = false;
4058 NextRequest& triggerFailedRequest = mNextRequests.editItemAt(0);
4059 for (size_t i = 0; i < numRequestProcessed; i++) {
4060 NextRequest& nextRequest = mNextRequests.editItemAt(i);
4061 nextRequest.submitted = true;
4062
Shuzhen Wangc2cba122018-05-17 18:10:24 -07004063 updateNextRequest(nextRequest);
Emilian Peevaebbe412018-01-15 13:53:24 +00004064
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004065 if (!triggerRemoveFailed) {
4066 // Remove any previously queued triggers (after unlock)
4067 status_t removeTriggerRes = removeTriggers(mPrevRequest);
4068 if (removeTriggerRes != OK) {
4069 triggerRemoveFailed = true;
4070 triggerFailedRequest = nextRequest;
4071 }
4072 }
4073 }
4074
4075 if (triggerRemoveFailed) {
4076 SET_ERR("RequestThread: Unable to remove triggers "
4077 "(capture request %d, HAL device: %s (%d)",
4078 triggerFailedRequest.halRequest.frame_number, strerror(-res), res);
4079 cleanUpFailedRequests(/*sendRequestError*/ false);
4080 return false;
4081 }
4082
4083 if (res != OK) {
4084 // Should only get a failure here for malformed requests or device-level
4085 // errors, so consider all errors fatal. Bad metadata failures should
4086 // come through notify.
4087 SET_ERR("RequestThread: Unable to submit capture request %d to HAL device: %s (%d)",
4088 mNextRequests[numRequestProcessed].halRequest.frame_number,
4089 strerror(-res), res);
4090 cleanUpFailedRequests(/*sendRequestError*/ false);
4091 return false;
4092 }
4093 return true;
4094}
4095
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07004096nsecs_t Camera3Device::RequestThread::calculateMaxExpectedDuration(const camera_metadata_t *request) {
4097 nsecs_t maxExpectedDuration = kDefaultExpectedDuration;
4098 camera_metadata_ro_entry_t e = camera_metadata_ro_entry_t();
4099 find_camera_metadata_ro_entry(request,
4100 ANDROID_CONTROL_AE_MODE,
4101 &e);
4102 if (e.count == 0) return maxExpectedDuration;
4103
4104 switch (e.data.u8[0]) {
4105 case ANDROID_CONTROL_AE_MODE_OFF:
4106 find_camera_metadata_ro_entry(request,
4107 ANDROID_SENSOR_EXPOSURE_TIME,
4108 &e);
4109 if (e.count > 0) {
4110 maxExpectedDuration = e.data.i64[0];
4111 }
4112 find_camera_metadata_ro_entry(request,
4113 ANDROID_SENSOR_FRAME_DURATION,
4114 &e);
4115 if (e.count > 0) {
4116 maxExpectedDuration = std::max(e.data.i64[0], maxExpectedDuration);
4117 }
4118 break;
4119 default:
4120 find_camera_metadata_ro_entry(request,
4121 ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
4122 &e);
4123 if (e.count > 1) {
4124 maxExpectedDuration = 1e9 / e.data.u8[0];
4125 }
4126 break;
4127 }
4128
4129 return maxExpectedDuration;
4130}
4131
Emilian Peeva14b4dd2018-05-15 11:00:31 +01004132bool Camera3Device::RequestThread::skipHFRTargetFPSUpdate(int32_t tag,
4133 const camera_metadata_ro_entry_t& newEntry, const camera_metadata_entry_t& currentEntry) {
4134 if (mConstrainedMode && (ANDROID_CONTROL_AE_TARGET_FPS_RANGE == tag) &&
4135 (newEntry.count == currentEntry.count) && (currentEntry.count == 2) &&
4136 (currentEntry.data.i32[1] == newEntry.data.i32[1])) {
4137 return true;
4138 }
4139
4140 return false;
4141}
4142
Shuzhen Wangc2cba122018-05-17 18:10:24 -07004143void Camera3Device::RequestThread::updateNextRequest(NextRequest& nextRequest) {
4144 // Update the latest request sent to HAL
4145 if (nextRequest.halRequest.settings != NULL) { // Don't update if they were unchanged
4146 Mutex::Autolock al(mLatestRequestMutex);
4147
4148 camera_metadata_t* cloned = clone_camera_metadata(nextRequest.halRequest.settings);
4149 mLatestRequest.acquire(cloned);
4150
4151 mLatestPhysicalRequest.clear();
4152 for (uint32_t i = 0; i < nextRequest.halRequest.num_physcam_settings; i++) {
4153 cloned = clone_camera_metadata(nextRequest.halRequest.physcam_settings[i]);
4154 mLatestPhysicalRequest.emplace(nextRequest.halRequest.physcam_id[i],
4155 CameraMetadata(cloned));
4156 }
4157
4158 sp<Camera3Device> parent = mParent.promote();
4159 if (parent != NULL) {
4160 parent->monitorMetadata(TagMonitor::REQUEST,
4161 nextRequest.halRequest.frame_number,
4162 0, mLatestRequest, mLatestPhysicalRequest);
4163 }
4164 }
4165
4166 if (nextRequest.halRequest.settings != NULL) {
4167 nextRequest.captureRequest->mSettingsList.begin()->metadata.unlock(
4168 nextRequest.halRequest.settings);
4169 }
4170
4171 cleanupPhysicalSettings(nextRequest.captureRequest, &nextRequest.halRequest);
4172}
4173
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004174bool Camera3Device::RequestThread::updateSessionParameters(const CameraMetadata& settings) {
4175 ATRACE_CALL();
4176 bool updatesDetected = false;
4177
Emilian Peev4ec17882019-01-24 17:16:58 -08004178 CameraMetadata updatedParams(mLatestSessionParams);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004179 for (auto tag : mSessionParamKeys) {
4180 camera_metadata_ro_entry entry = settings.find(tag);
Emilian Peev4ec17882019-01-24 17:16:58 -08004181 camera_metadata_entry lastEntry = updatedParams.find(tag);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004182
4183 if (entry.count > 0) {
4184 bool isDifferent = false;
4185 if (lastEntry.count > 0) {
4186 // Have a last value, compare to see if changed
4187 if (lastEntry.type == entry.type &&
4188 lastEntry.count == entry.count) {
4189 // Same type and count, compare values
4190 size_t bytesPerValue = camera_metadata_type_size[lastEntry.type];
4191 size_t entryBytes = bytesPerValue * lastEntry.count;
4192 int cmp = memcmp(entry.data.u8, lastEntry.data.u8, entryBytes);
4193 if (cmp != 0) {
4194 isDifferent = true;
4195 }
4196 } else {
4197 // Count or type has changed
4198 isDifferent = true;
4199 }
4200 } else {
4201 // No last entry, so always consider to be different
4202 isDifferent = true;
4203 }
4204
4205 if (isDifferent) {
4206 ALOGV("%s: Session parameter tag id %d changed", __FUNCTION__, tag);
Emilian Peeva14b4dd2018-05-15 11:00:31 +01004207 if (!skipHFRTargetFPSUpdate(tag, entry, lastEntry)) {
4208 updatesDetected = true;
4209 }
Emilian Peev4ec17882019-01-24 17:16:58 -08004210 updatedParams.update(entry);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004211 }
4212 } else if (lastEntry.count > 0) {
4213 // Value has been removed
4214 ALOGV("%s: Session parameter tag id %d removed", __FUNCTION__, tag);
Emilian Peev4ec17882019-01-24 17:16:58 -08004215 updatedParams.erase(tag);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004216 updatesDetected = true;
4217 }
4218 }
4219
Emilian Peev4ec17882019-01-24 17:16:58 -08004220 bool reconfigureRequired;
4221 if (updatesDetected) {
4222 reconfigureRequired = mInterface->isReconfigurationRequired(mLatestSessionParams,
4223 updatedParams);
4224 mLatestSessionParams = updatedParams;
4225 } else {
4226 reconfigureRequired = false;
4227 }
4228
4229 return reconfigureRequired;
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004230}
4231
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004232bool Camera3Device::RequestThread::threadLoop() {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004233 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004234 status_t res;
Jayant Chowdhary37eca242019-11-18 08:55:56 -08004235 // Any function called from threadLoop() must not hold mInterfaceLock since
4236 // it could lead to deadlocks (disconnect() -> hold mInterfaceMutex -> wait for request thread
4237 // to finish -> request thread waits on mInterfaceMutex) http://b/143513518
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004238
4239 // Handle paused state.
4240 if (waitIfPaused()) {
4241 return true;
4242 }
4243
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004244 // Wait for the next batch of requests.
4245 waitForNextRequestBatch();
4246 if (mNextRequests.size() == 0) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004247 return true;
4248 }
4249
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004250 // Get the latest request ID, if any
4251 int latestRequestId;
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004252 camera_metadata_entry_t requestIdEntry = mNextRequests[mNextRequests.size() - 1].
Emilian Peevaebbe412018-01-15 13:53:24 +00004253 captureRequest->mSettingsList.begin()->metadata.find(ANDROID_REQUEST_ID);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004254 if (requestIdEntry.count > 0) {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004255 latestRequestId = requestIdEntry.data.i32[0];
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004256 } else {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004257 ALOGW("%s: Did not have android.request.id set in the request.", __FUNCTION__);
4258 latestRequestId = NAME_NOT_FOUND;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004259 }
4260
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004261 // 'mNextRequests' will at this point contain either a set of HFR batched requests
4262 // or a single request from streaming or burst. In either case the first element
4263 // should contain the latest camera settings that we need to check for any session
4264 // parameter updates.
Emilian Peevaebbe412018-01-15 13:53:24 +00004265 if (updateSessionParameters(mNextRequests[0].captureRequest->mSettingsList.begin()->metadata)) {
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004266 res = OK;
4267
4268 //Input stream buffers are already acquired at this point so an input stream
4269 //will not be able to move to idle state unless we force it.
4270 if (mNextRequests[0].captureRequest->mInputStream != nullptr) {
4271 res = mNextRequests[0].captureRequest->mInputStream->forceToIdle();
4272 if (res != OK) {
4273 ALOGE("%s: Failed to force idle input stream: %d", __FUNCTION__, res);
4274 cleanUpFailedRequests(/*sendRequestError*/ false);
4275 return false;
4276 }
4277 }
4278
4279 if (res == OK) {
4280 sp<StatusTracker> statusTracker = mStatusTracker.promote();
4281 if (statusTracker != 0) {
Eino-Ville Talvala002001b2018-01-23 16:53:50 -08004282 sp<Camera3Device> parent = mParent.promote();
4283 if (parent != nullptr) {
4284 parent->pauseStateNotify(true);
4285 }
4286
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004287 statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);
4288
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004289 if (parent != nullptr) {
4290 mReconfigured |= parent->reconfigureCamera(mLatestSessionParams);
4291 }
4292
4293 statusTracker->markComponentActive(mStatusId);
4294 setPaused(false);
4295 }
4296
4297 if (mNextRequests[0].captureRequest->mInputStream != nullptr) {
4298 mNextRequests[0].captureRequest->mInputStream->restoreConfiguredState();
4299 if (res != OK) {
4300 ALOGE("%s: Failed to restore configured input stream: %d", __FUNCTION__, res);
4301 cleanUpFailedRequests(/*sendRequestError*/ false);
4302 return false;
4303 }
4304 }
4305 }
4306 }
4307
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004308 // Prepare a batch of HAL requests and output buffers.
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004309 res = prepareHalRequests();
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004310 if (res == TIMED_OUT) {
4311 // Not a fatal error if getting output buffers time out.
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004312 cleanUpFailedRequests(/*sendRequestError*/ true);
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07004313 // Check if any stream is abandoned.
4314 checkAndStopRepeatingRequest();
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004315 return true;
4316 } else if (res != OK) {
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004317 cleanUpFailedRequests(/*sendRequestError*/ false);
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07004318 return false;
4319 }
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004320
Zhijun Hecc27e112013-10-03 16:12:43 -07004321 // Inform waitUntilRequestProcessed thread of a new request ID
4322 {
4323 Mutex::Autolock al(mLatestRequestMutex);
4324
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004325 mLatestRequestId = latestRequestId;
Zhijun Hecc27e112013-10-03 16:12:43 -07004326 mLatestRequestSignal.signal();
4327 }
4328
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004329 // Submit a batch of requests to HAL.
4330 // Use flush lock only when submitting multilple requests in a batch.
4331 // TODO: The problem with flush lock is flush() will be blocked by process_capture_request()
4332 // which may take a long time to finish so synchronizing flush() and
4333 // process_capture_request() defeats the purpose of cancelling requests ASAP with flush().
4334 // For now, only synchronize for high speed recording and we should figure something out for
4335 // removing the synchronization.
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004336 bool useFlushLock = mNextRequests.size() > 1;
Eino-Ville Talvala17a61ad2013-06-03 16:53:32 -07004337
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004338 if (useFlushLock) {
4339 mFlushLock.lock();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004340 }
4341
Zhijun Hef0645c12016-08-02 00:58:11 -07004342 ALOGVV("%s: %d: submitting %zu requests in a batch.", __FUNCTION__, __LINE__,
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004343 mNextRequests.size());
Igor Murashkin1e479c02013-09-06 16:55:14 -07004344
Yin-Chia Yehcd333fe2019-02-08 13:45:41 -08004345 sp<Camera3Device> parent = mParent.promote();
4346 if (parent != nullptr) {
4347 parent->mRequestBufferSM.onSubmittingRequest();
4348 }
4349
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004350 bool submitRequestSuccess = false;
Shuzhen Wang686f6442017-06-20 16:16:04 -07004351 nsecs_t tRequestStart = systemTime(SYSTEM_TIME_MONOTONIC);
Yin-Chia Yeh11648852019-05-16 10:42:54 -07004352 submitRequestSuccess = sendRequestsBatch();
4353
Shuzhen Wang686f6442017-06-20 16:16:04 -07004354 nsecs_t tRequestEnd = systemTime(SYSTEM_TIME_MONOTONIC);
4355 mRequestLatency.add(tRequestStart, tRequestEnd);
Igor Murashkin1e479c02013-09-06 16:55:14 -07004356
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004357 if (useFlushLock) {
4358 mFlushLock.unlock();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004359 }
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004360
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004361 // Unset as current request
4362 {
4363 Mutex::Autolock l(mRequestLock);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004364 mNextRequests.clear();
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004365 }
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004366 mRequestSubmittedSignal.signal();
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004367
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004368 return submitRequestSuccess;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004369}
4370
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004371status_t Camera3Device::RequestThread::prepareHalRequests() {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004372 ATRACE_CALL();
4373
Yin-Chia Yehd07b11e2018-06-01 12:50:02 -07004374 bool batchedRequest = mNextRequests[0].captureRequest->mBatchSize > 1;
Shuzhen Wang4a472662017-02-26 23:29:04 -08004375 for (size_t i = 0; i < mNextRequests.size(); i++) {
4376 auto& nextRequest = mNextRequests.editItemAt(i);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004377 sp<CaptureRequest> captureRequest = nextRequest.captureRequest;
4378 camera3_capture_request_t* halRequest = &nextRequest.halRequest;
4379 Vector<camera3_stream_buffer_t>* outputBuffers = &nextRequest.outputBuffers;
4380
4381 // Prepare a request to HAL
4382 halRequest->frame_number = captureRequest->mResultExtras.frameNumber;
4383
4384 // Insert any queued triggers (before metadata is locked)
4385 status_t res = insertTriggers(captureRequest);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004386 if (res < 0) {
4387 SET_ERR("RequestThread: Unable to insert triggers "
4388 "(capture request %d, HAL device: %s (%d)",
4389 halRequest->frame_number, strerror(-res), res);
4390 return INVALID_OPERATION;
4391 }
Eino-Ville Talvala7b8a1fd2018-05-22 15:30:35 -07004392
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004393 int triggerCount = res;
4394 bool triggersMixedIn = (triggerCount > 0 || mPrevTriggers > 0);
4395 mPrevTriggers = triggerCount;
4396
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08004397 bool rotateAndCropChanged = overrideAutoRotateAndCrop(captureRequest);
4398
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004399 // If the request is the same as last, or we had triggers last time
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08004400 bool newRequest =
4401 (mPrevRequest != captureRequest || triggersMixedIn || rotateAndCropChanged) &&
Yin-Chia Yehd07b11e2018-06-01 12:50:02 -07004402 // Request settings are all the same within one batch, so only treat the first
4403 // request in a batch as new
Zhijun He54c36822018-07-18 09:33:39 -07004404 !(batchedRequest && i > 0);
Emilian Peev00420d22018-02-05 21:33:13 +00004405 if (newRequest) {
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08004406 std::set<std::string> cameraIdsWithZoom;
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004407 /**
4408 * HAL workaround:
4409 * Insert a dummy trigger ID if a trigger is set but no trigger ID is
4410 */
4411 res = addDummyTriggerIds(captureRequest);
4412 if (res != OK) {
4413 SET_ERR("RequestThread: Unable to insert dummy trigger IDs "
4414 "(capture request %d, HAL device: %s (%d)",
4415 halRequest->frame_number, strerror(-res), res);
4416 return INVALID_OPERATION;
4417 }
4418
Eino-Ville Talvala7b8a1fd2018-05-22 15:30:35 -07004419 {
4420 // Correct metadata regions for distortion correction if enabled
4421 sp<Camera3Device> parent = mParent.promote();
4422 if (parent != nullptr) {
Shuzhen Wang4f6fa9d2019-03-29 10:40:35 -07004423 List<PhysicalCameraSettings>::iterator it;
4424 for (it = captureRequest->mSettingsList.begin();
4425 it != captureRequest->mSettingsList.end(); it++) {
4426 if (parent->mDistortionMappers.find(it->cameraId) ==
4427 parent->mDistortionMappers.end()) {
4428 continue;
4429 }
4430 res = parent->mDistortionMappers[it->cameraId].correctCaptureRequest(
4431 &(it->metadata));
4432 if (res != OK) {
4433 SET_ERR("RequestThread: Unable to correct capture requests "
4434 "for lens distortion for request %d: %s (%d)",
4435 halRequest->frame_number, strerror(-res), res);
4436 return INVALID_OPERATION;
4437 }
Eino-Ville Talvala7b8a1fd2018-05-22 15:30:35 -07004438 }
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08004439
4440 for (it = captureRequest->mSettingsList.begin();
4441 it != captureRequest->mSettingsList.end(); it++) {
4442 if (parent->mZoomRatioMappers.find(it->cameraId) ==
4443 parent->mZoomRatioMappers.end()) {
4444 continue;
4445 }
4446
4447 camera_metadata_entry_t e = it->metadata.find(ANDROID_CONTROL_ZOOM_RATIO);
4448 if (e.count > 0 && e.data.f[0] != 1.0f) {
4449 cameraIdsWithZoom.insert(it->cameraId);
4450 }
4451
4452 res = parent->mZoomRatioMappers[it->cameraId].updateCaptureRequest(
4453 &(it->metadata));
4454 if (res != OK) {
4455 SET_ERR("RequestThread: Unable to correct capture requests "
4456 "for zoom ratio for request %d: %s (%d)",
4457 halRequest->frame_number, strerror(-res), res);
4458 return INVALID_OPERATION;
4459 }
4460 }
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08004461 if (captureRequest->mRotateAndCropAuto) {
4462 for (it = captureRequest->mSettingsList.begin();
4463 it != captureRequest->mSettingsList.end(); it++) {
4464 auto mapper = parent->mRotateAndCropMappers.find(it->cameraId);
4465 if (mapper != parent->mRotateAndCropMappers.end()) {
4466 res = mapper->second.updateCaptureRequest(&(it->metadata));
4467 if (res != OK) {
4468 SET_ERR("RequestThread: Unable to correct capture requests "
4469 "for rotate-and-crop for request %d: %s (%d)",
4470 halRequest->frame_number, strerror(-res), res);
4471 return INVALID_OPERATION;
4472 }
4473 }
4474 }
4475 }
Eino-Ville Talvala7b8a1fd2018-05-22 15:30:35 -07004476 }
4477 }
4478
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004479 /**
4480 * The request should be presorted so accesses in HAL
4481 * are O(logn). Sidenote, sorting a sorted metadata is nop.
4482 */
Emilian Peevaebbe412018-01-15 13:53:24 +00004483 captureRequest->mSettingsList.begin()->metadata.sort();
4484 halRequest->settings = captureRequest->mSettingsList.begin()->metadata.getAndLock();
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004485 mPrevRequest = captureRequest;
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08004486 mPrevCameraIdsWithZoom = cameraIdsWithZoom;
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004487 ALOGVV("%s: Request settings are NEW", __FUNCTION__);
4488
4489 IF_ALOGV() {
4490 camera_metadata_ro_entry_t e = camera_metadata_ro_entry_t();
4491 find_camera_metadata_ro_entry(
4492 halRequest->settings,
4493 ANDROID_CONTROL_AF_TRIGGER,
4494 &e
4495 );
4496 if (e.count > 0) {
4497 ALOGV("%s: Request (frame num %d) had AF trigger 0x%x",
4498 __FUNCTION__,
4499 halRequest->frame_number,
4500 e.data.u8[0]);
4501 }
4502 }
4503 } else {
4504 // leave request.settings NULL to indicate 'reuse latest given'
4505 ALOGVV("%s: Request settings are REUSED",
4506 __FUNCTION__);
4507 }
4508
Emilian Peevaebbe412018-01-15 13:53:24 +00004509 if (captureRequest->mSettingsList.size() > 1) {
4510 halRequest->num_physcam_settings = captureRequest->mSettingsList.size() - 1;
4511 halRequest->physcam_id = new const char* [halRequest->num_physcam_settings];
Emilian Peev00420d22018-02-05 21:33:13 +00004512 if (newRequest) {
4513 halRequest->physcam_settings =
4514 new const camera_metadata* [halRequest->num_physcam_settings];
4515 } else {
4516 halRequest->physcam_settings = nullptr;
4517 }
Emilian Peevaebbe412018-01-15 13:53:24 +00004518 auto it = ++captureRequest->mSettingsList.begin();
4519 size_t i = 0;
4520 for (; it != captureRequest->mSettingsList.end(); it++, i++) {
4521 halRequest->physcam_id[i] = it->cameraId.c_str();
Emilian Peev00420d22018-02-05 21:33:13 +00004522 if (newRequest) {
4523 it->metadata.sort();
4524 halRequest->physcam_settings[i] = it->metadata.getAndLock();
4525 }
Emilian Peevaebbe412018-01-15 13:53:24 +00004526 }
4527 }
4528
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004529 uint32_t totalNumBuffers = 0;
4530
4531 // Fill in buffers
4532 if (captureRequest->mInputStream != NULL) {
4533 halRequest->input_buffer = &captureRequest->mInputBuffer;
4534 totalNumBuffers += 1;
4535 } else {
4536 halRequest->input_buffer = NULL;
4537 }
4538
4539 outputBuffers->insertAt(camera3_stream_buffer_t(), 0,
4540 captureRequest->mOutputStreams.size());
4541 halRequest->output_buffers = outputBuffers->array();
Shuzhen Wang5c22c152017-12-31 17:12:25 -08004542 std::set<String8> requestedPhysicalCameras;
Yin-Chia Yehb3a80b12018-09-04 12:13:05 -07004543
4544 sp<Camera3Device> parent = mParent.promote();
4545 if (parent == NULL) {
4546 // Should not happen, and nowhere to send errors to, so just log it
4547 CLOGE("RequestThread: Parent is gone");
4548 return INVALID_OPERATION;
4549 }
4550 nsecs_t waitDuration = kBaseGetBufferWait + parent->getExpectedInFlightDuration();
4551
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004552 SurfaceMap uniqueSurfaceIdMap;
Shuzhen Wang4a472662017-02-26 23:29:04 -08004553 for (size_t j = 0; j < captureRequest->mOutputStreams.size(); j++) {
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004554 sp<Camera3OutputStreamInterface> outputStream =
4555 captureRequest->mOutputStreams.editItemAt(j);
4556 int streamId = outputStream->getId();
Chien-Yu Chenc66969b2016-05-19 16:37:51 -07004557
4558 // Prepare video buffers for high speed recording on the first video request.
4559 if (mPrepareVideoStream && outputStream->isVideoStream()) {
4560 // Only try to prepare video stream on the first video request.
4561 mPrepareVideoStream = false;
4562
Shuzhen Wangb3a0fb52018-09-13 17:24:08 -07004563 res = outputStream->startPrepare(Camera3StreamInterface::ALLOCATE_PIPELINE_MAX,
4564 false /*blockRequest*/);
Chien-Yu Chenc66969b2016-05-19 16:37:51 -07004565 while (res == NOT_ENOUGH_DATA) {
4566 res = outputStream->prepareNextBuffer();
4567 }
4568 if (res != OK) {
4569 ALOGW("%s: Preparing video buffers for high speed failed: %s (%d)",
4570 __FUNCTION__, strerror(-res), res);
4571 outputStream->cancelPrepare();
4572 }
4573 }
4574
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004575 std::vector<size_t> uniqueSurfaceIds;
4576 res = outputStream->getUniqueSurfaceIds(
4577 captureRequest->mOutputSurfaces[streamId],
4578 &uniqueSurfaceIds);
4579 // INVALID_OPERATION is normal output for streams not supporting surfaceIds
4580 if (res != OK && res != INVALID_OPERATION) {
4581 ALOGE("%s: failed to query stream %d unique surface IDs",
4582 __FUNCTION__, streamId);
4583 return res;
4584 }
4585 if (res == OK) {
4586 uniqueSurfaceIdMap.insert({streamId, std::move(uniqueSurfaceIds)});
4587 }
4588
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07004589 if (mUseHalBufManager) {
Yin-Chia Yeh110342b2018-11-19 11:47:46 -08004590 if (outputStream->isAbandoned()) {
Yin-Chia Yeha1b56c82019-03-27 15:50:39 -07004591 ALOGV("%s: stream %d is abandoned, skipping request", __FUNCTION__, streamId);
Yin-Chia Yeh110342b2018-11-19 11:47:46 -08004592 return TIMED_OUT;
4593 }
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07004594 // HAL will request buffer through requestStreamBuffer API
4595 camera3_stream_buffer_t& buffer = outputBuffers->editItemAt(j);
4596 buffer.stream = outputStream->asHalStream();
4597 buffer.buffer = nullptr;
4598 buffer.status = CAMERA3_BUFFER_STATUS_OK;
4599 buffer.acquire_fence = -1;
4600 buffer.release_fence = -1;
4601 } else {
4602 res = outputStream->getBuffer(&outputBuffers->editItemAt(j),
4603 waitDuration,
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004604 captureRequest->mOutputSurfaces[streamId]);
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07004605 if (res != OK) {
4606 // Can't get output buffer from gralloc queue - this could be due to
4607 // abandoned queue or other consumer misbehavior, so not a fatal
4608 // error
Yin-Chia Yeha1b56c82019-03-27 15:50:39 -07004609 ALOGV("RequestThread: Can't get output buffer, skipping request:"
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07004610 " %s (%d)", strerror(-res), res);
4611
4612 return TIMED_OUT;
4613 }
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004614 }
Shuzhen Wang68ac7ad2019-01-30 14:03:28 -08004615
4616 {
4617 sp<Camera3Device> parent = mParent.promote();
4618 if (parent != nullptr) {
4619 const String8& streamCameraId = outputStream->getPhysicalCameraId();
4620 for (const auto& settings : captureRequest->mSettingsList) {
4621 if ((streamCameraId.isEmpty() &&
4622 parent->getId() == settings.cameraId.c_str()) ||
4623 streamCameraId == settings.cameraId.c_str()) {
4624 outputStream->fireBufferRequestForFrameNumber(
4625 captureRequest->mResultExtras.frameNumber,
4626 settings.metadata);
4627 }
4628 }
4629 }
4630 }
Shuzhen Wang0129d522016-10-30 22:43:41 -07004631
Shuzhen Wang5c22c152017-12-31 17:12:25 -08004632 String8 physicalCameraId = outputStream->getPhysicalCameraId();
4633
4634 if (!physicalCameraId.isEmpty()) {
4635 // Physical stream isn't supported for input request.
4636 if (halRequest->input_buffer) {
4637 CLOGE("Physical stream is not supported for input request");
4638 return INVALID_OPERATION;
4639 }
4640 requestedPhysicalCameras.insert(physicalCameraId);
4641 }
4642 halRequest->num_output_buffers++;
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004643 }
4644 totalNumBuffers += halRequest->num_output_buffers;
4645
4646 // Log request in the in-flight queue
Shuzhen Wang4a472662017-02-26 23:29:04 -08004647 // If this request list is for constrained high speed recording (not
4648 // preview), and the current request is not the last one in the batch,
4649 // do not send callback to the app.
4650 bool hasCallback = true;
Yin-Chia Yehd07b11e2018-06-01 12:50:02 -07004651 if (batchedRequest && i != mNextRequests.size()-1) {
Shuzhen Wang4a472662017-02-26 23:29:04 -08004652 hasCallback = false;
4653 }
Emilian Peev9dd21f42018-08-03 13:39:29 +01004654 bool isStillCapture = false;
Shuzhen Wang26abaf42018-08-28 15:41:20 -07004655 bool isZslCapture = false;
Emilian Peev9dd21f42018-08-03 13:39:29 +01004656 if (!mNextRequests[0].captureRequest->mSettingsList.begin()->metadata.isEmpty()) {
4657 camera_metadata_ro_entry_t e = camera_metadata_ro_entry_t();
4658 find_camera_metadata_ro_entry(halRequest->settings, ANDROID_CONTROL_CAPTURE_INTENT, &e);
4659 if ((e.count > 0) && (e.data.u8[0] == ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE)) {
4660 isStillCapture = true;
4661 ATRACE_ASYNC_BEGIN("still capture", mNextRequests[i].halRequest.frame_number);
4662 }
Shuzhen Wang26abaf42018-08-28 15:41:20 -07004663
4664 find_camera_metadata_ro_entry(halRequest->settings, ANDROID_CONTROL_ENABLE_ZSL, &e);
4665 if ((e.count > 0) && (e.data.u8[0] == ANDROID_CONTROL_ENABLE_ZSL_TRUE)) {
4666 isZslCapture = true;
4667 }
Emilian Peev9dd21f42018-08-03 13:39:29 +01004668 }
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004669 res = parent->registerInFlight(halRequest->frame_number,
4670 totalNumBuffers, captureRequest->mResultExtras,
4671 /*hasInput*/halRequest->input_buffer != NULL,
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07004672 hasCallback,
Shuzhen Wang5c22c152017-12-31 17:12:25 -08004673 calculateMaxExpectedDuration(halRequest->settings),
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08004674 requestedPhysicalCameras, isStillCapture, isZslCapture,
4675 captureRequest->mRotateAndCropAuto, mPrevCameraIdsWithZoom,
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004676 (mUseHalBufManager) ? uniqueSurfaceIdMap :
4677 SurfaceMap{});
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004678 ALOGVV("%s: registered in flight requestId = %" PRId32 ", frameNumber = %" PRId64
4679 ", burstId = %" PRId32 ".",
4680 __FUNCTION__,
4681 captureRequest->mResultExtras.requestId, captureRequest->mResultExtras.frameNumber,
4682 captureRequest->mResultExtras.burstId);
4683 if (res != OK) {
4684 SET_ERR("RequestThread: Unable to register new in-flight request:"
4685 " %s (%d)", strerror(-res), res);
4686 return INVALID_OPERATION;
4687 }
4688 }
4689
4690 return OK;
4691}
4692
Igor Murashkin1e479c02013-09-06 16:55:14 -07004693CameraMetadata Camera3Device::RequestThread::getLatestRequest() const {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004694 ATRACE_CALL();
Igor Murashkin1e479c02013-09-06 16:55:14 -07004695 Mutex::Autolock al(mLatestRequestMutex);
4696
4697 ALOGV("RequestThread::%s", __FUNCTION__);
4698
4699 return mLatestRequest;
4700}
4701
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07004702bool Camera3Device::RequestThread::isStreamPending(
4703 sp<Camera3StreamInterface>& stream) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004704 ATRACE_CALL();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07004705 Mutex::Autolock l(mRequestLock);
4706
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004707 for (const auto& nextRequest : mNextRequests) {
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004708 if (!nextRequest.submitted) {
4709 for (const auto& s : nextRequest.captureRequest->mOutputStreams) {
4710 if (stream == s) return true;
4711 }
4712 if (stream == nextRequest.captureRequest->mInputStream) return true;
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004713 }
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004714 }
4715
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07004716 for (const auto& request : mRequestQueue) {
4717 for (const auto& s : request->mOutputStreams) {
4718 if (stream == s) return true;
4719 }
4720 if (stream == request->mInputStream) return true;
4721 }
4722
4723 for (const auto& request : mRepeatingRequests) {
4724 for (const auto& s : request->mOutputStreams) {
4725 if (stream == s) return true;
4726 }
4727 if (stream == request->mInputStream) return true;
4728 }
4729
4730 return false;
4731}
Jianing Weicb0652e2014-03-12 18:29:36 -07004732
Emilian Peev40ead602017-09-26 15:46:36 +01004733bool Camera3Device::RequestThread::isOutputSurfacePending(int streamId, size_t surfaceId) {
4734 ATRACE_CALL();
4735 Mutex::Autolock l(mRequestLock);
4736
4737 for (const auto& nextRequest : mNextRequests) {
4738 for (const auto& s : nextRequest.captureRequest->mOutputSurfaces) {
4739 if (s.first == streamId) {
4740 const auto &it = std::find(s.second.begin(), s.second.end(), surfaceId);
4741 if (it != s.second.end()) {
4742 return true;
4743 }
4744 }
4745 }
4746 }
4747
4748 for (const auto& request : mRequestQueue) {
4749 for (const auto& s : request->mOutputSurfaces) {
4750 if (s.first == streamId) {
4751 const auto &it = std::find(s.second.begin(), s.second.end(), surfaceId);
4752 if (it != s.second.end()) {
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004753 return true;
Emilian Peev40ead602017-09-26 15:46:36 +01004754 }
4755 }
4756 }
4757 }
4758
4759 for (const auto& request : mRepeatingRequests) {
4760 for (const auto& s : request->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()) {
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004764 return true;
Emilian Peev40ead602017-09-26 15:46:36 +01004765 }
4766 }
4767 }
4768 }
4769
4770 return false;
4771}
4772
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07004773void Camera3Device::RequestThread::signalPipelineDrain(const std::vector<int>& streamIds) {
4774 if (!mUseHalBufManager) {
4775 ALOGE("%s called for camera device not supporting HAL buffer management", __FUNCTION__);
4776 return;
4777 }
4778
4779 Mutex::Autolock pl(mPauseLock);
4780 if (mPaused) {
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07004781 mInterface->signalPipelineDrain(streamIds);
4782 return;
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07004783 }
4784 // If request thread is still busy, wait until paused then notify HAL
4785 mNotifyPipelineDrain = true;
4786 mStreamIdsToBeDrained = streamIds;
4787}
4788
Emilian Peevc0fe54c2020-03-11 14:05:07 -07004789void Camera3Device::RequestThread::clearPreviousRequest() {
4790 Mutex::Autolock l(mRequestLock);
4791 mPrevRequest.clear();
4792}
4793
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004794status_t Camera3Device::RequestThread::switchToOffline(
4795 const std::vector<int32_t>& streamsToKeep,
4796 /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004797 /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
4798 /*out*/camera3::BufferRecords* bufferRecords) {
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004799 Mutex::Autolock l(mRequestLock);
4800 clearRepeatingRequestsLocked(/*lastFrameNumber*/nullptr);
4801
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004802 // Wait until request thread is fully stopped
4803 // TBD: check if request thread is being paused by other APIs (shouldn't be)
4804
4805 // We could also check for mRepeatingRequests.empty(), but the API interface
4806 // is serialized by Camera3Device::mInterfaceLock so no one should be able to submit any
4807 // new requests during the call; hence skip that check.
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004808 bool queueEmpty = mNextRequests.empty() && mRequestQueue.empty();
4809 while (!queueEmpty) {
4810 status_t res = mRequestSubmittedSignal.waitRelative(mRequestLock, kRequestSubmitTimeout);
4811 if (res == TIMED_OUT) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004812 ALOGE("%s: request thread failed to submit one request within timeout!", __FUNCTION__);
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004813 return res;
4814 } else if (res != OK) {
4815 ALOGE("%s: request thread failed to submit a request: %s (%d)!",
4816 __FUNCTION__, strerror(-res), res);
4817 return res;
4818 }
4819 queueEmpty = mNextRequests.empty() && mRequestQueue.empty();
4820 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004821
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004822 return mInterface->switchToOffline(
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004823 streamsToKeep, offlineSessionInfo, offlineSession, bufferRecords);
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004824}
4825
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08004826status_t Camera3Device::RequestThread::setRotateAndCropAutoBehavior(
4827 camera_metadata_enum_android_scaler_rotate_and_crop_t rotateAndCropValue) {
4828 ATRACE_CALL();
4829 Mutex::Autolock l(mTriggerMutex);
4830 if (rotateAndCropValue == ANDROID_SCALER_ROTATE_AND_CROP_AUTO) {
4831 return BAD_VALUE;
4832 }
4833 mRotateAndCropOverride = rotateAndCropValue;
4834 return OK;
4835}
4836
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07004837nsecs_t Camera3Device::getExpectedInFlightDuration() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004838 ATRACE_CALL();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004839 std::lock_guard<std::mutex> l(mInFlightLock);
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07004840 return mExpectedInflightDuration > kMinInflightDuration ?
4841 mExpectedInflightDuration : kMinInflightDuration;
4842}
4843
Emilian Peevaebbe412018-01-15 13:53:24 +00004844void Camera3Device::RequestThread::cleanupPhysicalSettings(sp<CaptureRequest> request,
4845 camera3_capture_request_t *halRequest) {
4846 if ((request == nullptr) || (halRequest == nullptr)) {
4847 ALOGE("%s: Invalid request!", __FUNCTION__);
4848 return;
4849 }
4850
4851 if (halRequest->num_physcam_settings > 0) {
4852 if (halRequest->physcam_id != nullptr) {
4853 delete [] halRequest->physcam_id;
4854 halRequest->physcam_id = nullptr;
4855 }
4856 if (halRequest->physcam_settings != nullptr) {
4857 auto it = ++(request->mSettingsList.begin());
4858 size_t i = 0;
4859 for (; it != request->mSettingsList.end(); it++, i++) {
4860 it->metadata.unlock(halRequest->physcam_settings[i]);
4861 }
4862 delete [] halRequest->physcam_settings;
4863 halRequest->physcam_settings = nullptr;
4864 }
4865 }
4866}
4867
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004868void Camera3Device::RequestThread::cleanUpFailedRequests(bool sendRequestError) {
4869 if (mNextRequests.empty()) {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004870 return;
4871 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004872
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004873 for (auto& nextRequest : mNextRequests) {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004874 // Skip the ones that have been submitted successfully.
4875 if (nextRequest.submitted) {
4876 continue;
4877 }
4878
4879 sp<CaptureRequest> captureRequest = nextRequest.captureRequest;
4880 camera3_capture_request_t* halRequest = &nextRequest.halRequest;
4881 Vector<camera3_stream_buffer_t>* outputBuffers = &nextRequest.outputBuffers;
4882
4883 if (halRequest->settings != NULL) {
Emilian Peevaebbe412018-01-15 13:53:24 +00004884 captureRequest->mSettingsList.begin()->metadata.unlock(halRequest->settings);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004885 }
4886
Emilian Peevaebbe412018-01-15 13:53:24 +00004887 cleanupPhysicalSettings(captureRequest, halRequest);
4888
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004889 if (captureRequest->mInputStream != NULL) {
4890 captureRequest->mInputBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
4891 captureRequest->mInputStream->returnInputBuffer(captureRequest->mInputBuffer);
4892 }
4893
Yin-Chia Yeh21cb47b2019-01-18 15:08:17 -08004894 // No output buffer can be returned when using HAL buffer manager
4895 if (!mUseHalBufManager) {
4896 for (size_t i = 0; i < halRequest->num_output_buffers; i++) {
4897 //Buffers that failed processing could still have
4898 //valid acquire fence.
4899 int acquireFence = (*outputBuffers)[i].acquire_fence;
4900 if (0 <= acquireFence) {
4901 close(acquireFence);
4902 outputBuffers->editItemAt(i).acquire_fence = -1;
4903 }
4904 outputBuffers->editItemAt(i).status = CAMERA3_BUFFER_STATUS_ERROR;
4905 captureRequest->mOutputStreams.editItemAt(i)->returnBuffer((*outputBuffers)[i], 0,
4906 /*timestampIncreasing*/true, std::vector<size_t> (),
4907 captureRequest->mResultExtras.frameNumber);
Emilian Peevc58cf4c2017-05-11 17:23:41 +01004908 }
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004909 }
4910
4911 if (sendRequestError) {
4912 Mutex::Autolock l(mRequestLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07004913 sp<NotificationListener> listener = mListener.promote();
4914 if (listener != NULL) {
4915 listener->notifyError(
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08004916 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004917 captureRequest->mResultExtras);
4918 }
4919 }
Shuzhen Wangcadb3302016-11-04 14:17:56 -07004920
4921 // Remove yet-to-be submitted inflight request from inflightMap
4922 {
4923 sp<Camera3Device> parent = mParent.promote();
4924 if (parent != NULL) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004925 std::lock_guard<std::mutex> l(parent->mInFlightLock);
Shuzhen Wangcadb3302016-11-04 14:17:56 -07004926 ssize_t idx = parent->mInFlightMap.indexOfKey(captureRequest->mResultExtras.frameNumber);
4927 if (idx >= 0) {
4928 ALOGV("%s: Remove inflight request from queue: frameNumber %" PRId64,
4929 __FUNCTION__, captureRequest->mResultExtras.frameNumber);
4930 parent->removeInFlightMapEntryLocked(idx);
4931 }
4932 }
4933 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004934 }
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004935
4936 Mutex::Autolock l(mRequestLock);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004937 mNextRequests.clear();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004938}
4939
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004940void Camera3Device::RequestThread::waitForNextRequestBatch() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004941 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004942 // Optimized a bit for the simple steady-state case (single repeating
4943 // request), to avoid putting that request in the queue temporarily.
4944 Mutex::Autolock l(mRequestLock);
4945
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004946 assert(mNextRequests.empty());
4947
4948 NextRequest nextRequest;
4949 nextRequest.captureRequest = waitForNextRequestLocked();
4950 if (nextRequest.captureRequest == nullptr) {
4951 return;
4952 }
4953
4954 nextRequest.halRequest = camera3_capture_request_t();
4955 nextRequest.submitted = false;
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004956 mNextRequests.add(nextRequest);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004957
4958 // Wait for additional requests
4959 const size_t batchSize = nextRequest.captureRequest->mBatchSize;
4960
4961 for (size_t i = 1; i < batchSize; i++) {
4962 NextRequest additionalRequest;
4963 additionalRequest.captureRequest = waitForNextRequestLocked();
4964 if (additionalRequest.captureRequest == nullptr) {
4965 break;
4966 }
4967
4968 additionalRequest.halRequest = camera3_capture_request_t();
4969 additionalRequest.submitted = false;
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004970 mNextRequests.add(additionalRequest);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004971 }
4972
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004973 if (mNextRequests.size() < batchSize) {
Eino-Ville Talvalad309fb92015-11-25 12:12:45 -08004974 ALOGE("RequestThread: only get %zu out of %zu requests. Skipping requests.",
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004975 mNextRequests.size(), batchSize);
4976 cleanUpFailedRequests(/*sendRequestError*/true);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004977 }
4978
4979 return;
4980}
4981
4982sp<Camera3Device::CaptureRequest>
4983 Camera3Device::RequestThread::waitForNextRequestLocked() {
4984 status_t res;
4985 sp<CaptureRequest> nextRequest;
4986
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004987 while (mRequestQueue.empty()) {
4988 if (!mRepeatingRequests.empty()) {
4989 // Always atomically enqueue all requests in a repeating request
4990 // list. Guarantees a complete in-sequence set of captures to
4991 // application.
4992 const RequestList &requests = mRepeatingRequests;
4993 RequestList::const_iterator firstRequest =
4994 requests.begin();
4995 nextRequest = *firstRequest;
4996 mRequestQueue.insert(mRequestQueue.end(),
4997 ++firstRequest,
4998 requests.end());
4999 // No need to wait any longer
Jianing Weicb0652e2014-03-12 18:29:36 -07005000
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07005001 mRepeatingLastFrameNumber = mFrameNumber + requests.size() - 1;
Jianing Weicb0652e2014-03-12 18:29:36 -07005002
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005003 break;
5004 }
5005
5006 res = mRequestSignal.waitRelative(mRequestLock, kRequestTimeout);
5007
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005008 if ((mRequestQueue.empty() && mRepeatingRequests.empty()) ||
5009 exitPending()) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005010 Mutex::Autolock pl(mPauseLock);
5011 if (mPaused == false) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005012 ALOGV("%s: RequestThread: Going idle", __FUNCTION__);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005013 mPaused = true;
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07005014 if (mNotifyPipelineDrain) {
5015 mInterface->signalPipelineDrain(mStreamIdsToBeDrained);
5016 mNotifyPipelineDrain = false;
5017 mStreamIdsToBeDrained.clear();
5018 }
Yin-Chia Yehc300a072019-02-13 14:56:57 -08005019 // Let the tracker know
5020 sp<StatusTracker> statusTracker = mStatusTracker.promote();
5021 if (statusTracker != 0) {
5022 statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);
5023 }
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005024 sp<Camera3Device> parent = mParent.promote();
5025 if (parent != nullptr) {
5026 parent->mRequestBufferSM.onRequestThreadPaused();
5027 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005028 }
5029 // Stop waiting for now and let thread management happen
5030 return NULL;
5031 }
5032 }
5033
5034 if (nextRequest == NULL) {
5035 // Don't have a repeating request already in hand, so queue
5036 // must have an entry now.
5037 RequestList::iterator firstRequest =
5038 mRequestQueue.begin();
5039 nextRequest = *firstRequest;
5040 mRequestQueue.erase(firstRequest);
Shuzhen Wang9d066012016-09-30 11:30:20 -07005041 if (mRequestQueue.empty() && !nextRequest->mRepeating) {
5042 sp<NotificationListener> listener = mListener.promote();
5043 if (listener != NULL) {
5044 listener->notifyRequestQueueEmpty();
5045 }
5046 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005047 }
5048
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07005049 // In case we've been unpaused by setPaused clearing mDoPause, need to
5050 // update internal pause state (capture/setRepeatingRequest unpause
5051 // directly).
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005052 Mutex::Autolock pl(mPauseLock);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005053 if (mPaused) {
5054 ALOGV("%s: RequestThread: Unpaused", __FUNCTION__);
5055 sp<StatusTracker> statusTracker = mStatusTracker.promote();
5056 if (statusTracker != 0) {
5057 statusTracker->markComponentActive(mStatusId);
5058 }
5059 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005060 mPaused = false;
5061
5062 // Check if we've reconfigured since last time, and reset the preview
5063 // request if so. Can't use 'NULL request == repeat' across configure calls.
5064 if (mReconfigured) {
5065 mPrevRequest.clear();
5066 mReconfigured = false;
5067 }
5068
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07005069 if (nextRequest != NULL) {
5070 nextRequest->mResultExtras.frameNumber = mFrameNumber++;
Yin-Chia Yehc00a25c2014-08-21 14:27:44 -07005071 nextRequest->mResultExtras.afTriggerId = mCurrentAfTriggerId;
5072 nextRequest->mResultExtras.precaptureTriggerId = mCurrentPreCaptureTriggerId;
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07005073
5074 // Since RequestThread::clear() removes buffers from the input stream,
5075 // get the right buffer here before unlocking mRequestLock
5076 if (nextRequest->mInputStream != NULL) {
5077 res = nextRequest->mInputStream->getInputBuffer(&nextRequest->mInputBuffer);
5078 if (res != OK) {
5079 // Can't get input buffer from gralloc queue - this could be due to
5080 // disconnected queue or other producer misbehavior, so not a fatal
5081 // error
5082 ALOGE("%s: Can't get input buffer, skipping request:"
5083 " %s (%d)", __FUNCTION__, strerror(-res), res);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005084
5085 sp<NotificationListener> listener = mListener.promote();
5086 if (listener != NULL) {
5087 listener->notifyError(
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08005088 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07005089 nextRequest->mResultExtras);
5090 }
5091 return NULL;
5092 }
5093 }
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07005094 }
Chien-Yu Chend196d612015-06-22 19:49:01 -07005095
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005096 return nextRequest;
5097}
5098
5099bool Camera3Device::RequestThread::waitIfPaused() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005100 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005101 status_t res;
5102 Mutex::Autolock l(mPauseLock);
5103 while (mDoPause) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005104 if (mPaused == false) {
5105 mPaused = true;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005106 ALOGV("%s: RequestThread: Paused", __FUNCTION__);
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07005107 if (mNotifyPipelineDrain) {
5108 mInterface->signalPipelineDrain(mStreamIdsToBeDrained);
5109 mNotifyPipelineDrain = false;
5110 mStreamIdsToBeDrained.clear();
5111 }
Yin-Chia Yehc300a072019-02-13 14:56:57 -08005112 // Let the tracker know
5113 sp<StatusTracker> statusTracker = mStatusTracker.promote();
5114 if (statusTracker != 0) {
5115 statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);
5116 }
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005117 sp<Camera3Device> parent = mParent.promote();
5118 if (parent != nullptr) {
5119 parent->mRequestBufferSM.onRequestThreadPaused();
5120 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005121 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005122
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005123 res = mDoPauseSignal.waitRelative(mPauseLock, kRequestTimeout);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005124 if (res == TIMED_OUT || exitPending()) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005125 return true;
5126 }
5127 }
5128 // We don't set mPaused to false here, because waitForNextRequest needs
5129 // to further manage the paused state in case of starvation.
5130 return false;
5131}
5132
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07005133void Camera3Device::RequestThread::unpauseForNewRequests() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005134 ATRACE_CALL();
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07005135 // With work to do, mark thread as unpaused.
5136 // If paused by request (setPaused), don't resume, to avoid
5137 // extra signaling/waiting overhead to waitUntilPaused
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005138 mRequestSignal.signal();
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07005139 Mutex::Autolock p(mPauseLock);
5140 if (!mDoPause) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005141 ALOGV("%s: RequestThread: Going active", __FUNCTION__);
5142 if (mPaused) {
5143 sp<StatusTracker> statusTracker = mStatusTracker.promote();
5144 if (statusTracker != 0) {
5145 statusTracker->markComponentActive(mStatusId);
5146 }
5147 }
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07005148 mPaused = false;
5149 }
5150}
5151
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07005152void Camera3Device::RequestThread::setErrorState(const char *fmt, ...) {
5153 sp<Camera3Device> parent = mParent.promote();
5154 if (parent != NULL) {
5155 va_list args;
5156 va_start(args, fmt);
5157
5158 parent->setErrorStateV(fmt, args);
5159
5160 va_end(args);
5161 }
5162}
5163
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005164status_t Camera3Device::RequestThread::insertTriggers(
5165 const sp<CaptureRequest> &request) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005166 ATRACE_CALL();
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005167 Mutex::Autolock al(mTriggerMutex);
5168
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07005169 sp<Camera3Device> parent = mParent.promote();
5170 if (parent == NULL) {
5171 CLOGE("RequestThread: Parent is gone");
5172 return DEAD_OBJECT;
5173 }
5174
Emilian Peevaebbe412018-01-15 13:53:24 +00005175 CameraMetadata &metadata = request->mSettingsList.begin()->metadata;
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005176 size_t count = mTriggerMap.size();
5177
5178 for (size_t i = 0; i < count; ++i) {
5179 RequestTrigger trigger = mTriggerMap.valueAt(i);
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005180 uint32_t tag = trigger.metadataTag;
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07005181
5182 if (tag == ANDROID_CONTROL_AF_TRIGGER_ID || tag == ANDROID_CONTROL_AE_PRECAPTURE_ID) {
5183 bool isAeTrigger = (trigger.metadataTag == ANDROID_CONTROL_AE_PRECAPTURE_ID);
5184 uint32_t triggerId = static_cast<uint32_t>(trigger.entryValue);
Yin-Chia Yehc00a25c2014-08-21 14:27:44 -07005185 if (isAeTrigger) {
5186 request->mResultExtras.precaptureTriggerId = triggerId;
5187 mCurrentPreCaptureTriggerId = triggerId;
5188 } else {
5189 request->mResultExtras.afTriggerId = triggerId;
5190 mCurrentAfTriggerId = triggerId;
5191 }
Emilian Peev7e25e5e2017-04-07 15:48:49 +01005192 continue;
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07005193 }
5194
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005195 camera_metadata_entry entry = metadata.find(tag);
5196
5197 if (entry.count > 0) {
5198 /**
5199 * Already has an entry for this trigger in the request.
5200 * Rewrite it with our requested trigger value.
5201 */
5202 RequestTrigger oldTrigger = trigger;
5203
5204 oldTrigger.entryValue = entry.data.u8[0];
5205
5206 mTriggerReplacedMap.add(tag, oldTrigger);
5207 } else {
5208 /**
5209 * More typical, no trigger entry, so we just add it
5210 */
5211 mTriggerRemovedMap.add(tag, trigger);
5212 }
5213
5214 status_t res;
5215
5216 switch (trigger.getTagType()) {
5217 case TYPE_BYTE: {
5218 uint8_t entryValue = static_cast<uint8_t>(trigger.entryValue);
5219 res = metadata.update(tag,
5220 &entryValue,
5221 /*count*/1);
5222 break;
5223 }
5224 case TYPE_INT32:
5225 res = metadata.update(tag,
5226 &trigger.entryValue,
5227 /*count*/1);
5228 break;
5229 default:
5230 ALOGE("%s: Type not supported: 0x%x",
5231 __FUNCTION__,
5232 trigger.getTagType());
5233 return INVALID_OPERATION;
5234 }
5235
5236 if (res != OK) {
5237 ALOGE("%s: Failed to update request metadata with trigger tag %s"
5238 ", value %d", __FUNCTION__, trigger.getTagName(),
5239 trigger.entryValue);
5240 return res;
5241 }
5242
5243 ALOGV("%s: Mixed in trigger %s, value %d", __FUNCTION__,
5244 trigger.getTagName(),
5245 trigger.entryValue);
5246 }
5247
5248 mTriggerMap.clear();
5249
5250 return count;
5251}
5252
5253status_t Camera3Device::RequestThread::removeTriggers(
5254 const sp<CaptureRequest> &request) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005255 ATRACE_CALL();
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005256 Mutex::Autolock al(mTriggerMutex);
5257
Emilian Peevaebbe412018-01-15 13:53:24 +00005258 CameraMetadata &metadata = request->mSettingsList.begin()->metadata;
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005259
5260 /**
5261 * Replace all old entries with their old values.
5262 */
5263 for (size_t i = 0; i < mTriggerReplacedMap.size(); ++i) {
5264 RequestTrigger trigger = mTriggerReplacedMap.valueAt(i);
5265
5266 status_t res;
5267
5268 uint32_t tag = trigger.metadataTag;
5269 switch (trigger.getTagType()) {
5270 case TYPE_BYTE: {
5271 uint8_t entryValue = static_cast<uint8_t>(trigger.entryValue);
5272 res = metadata.update(tag,
5273 &entryValue,
5274 /*count*/1);
5275 break;
5276 }
5277 case TYPE_INT32:
5278 res = metadata.update(tag,
5279 &trigger.entryValue,
5280 /*count*/1);
5281 break;
5282 default:
5283 ALOGE("%s: Type not supported: 0x%x",
5284 __FUNCTION__,
5285 trigger.getTagType());
5286 return INVALID_OPERATION;
5287 }
5288
5289 if (res != OK) {
5290 ALOGE("%s: Failed to restore request metadata with trigger tag %s"
5291 ", trigger value %d", __FUNCTION__,
5292 trigger.getTagName(), trigger.entryValue);
5293 return res;
5294 }
5295 }
5296 mTriggerReplacedMap.clear();
5297
5298 /**
5299 * Remove all new entries.
5300 */
5301 for (size_t i = 0; i < mTriggerRemovedMap.size(); ++i) {
5302 RequestTrigger trigger = mTriggerRemovedMap.valueAt(i);
5303 status_t res = metadata.erase(trigger.metadataTag);
5304
5305 if (res != OK) {
5306 ALOGE("%s: Failed to erase metadata with trigger tag %s"
5307 ", trigger value %d", __FUNCTION__,
5308 trigger.getTagName(), trigger.entryValue);
5309 return res;
5310 }
5311 }
5312 mTriggerRemovedMap.clear();
5313
5314 return OK;
5315}
5316
Eino-Ville Talvala2f876f92013-09-13 11:39:24 -07005317status_t Camera3Device::RequestThread::addDummyTriggerIds(
5318 const sp<CaptureRequest> &request) {
Eino-Ville Talvalad309fb92015-11-25 12:12:45 -08005319 // Trigger ID 0 had special meaning in the HAL2 spec, so avoid it here
Eino-Ville Talvala2f876f92013-09-13 11:39:24 -07005320 static const int32_t dummyTriggerId = 1;
5321 status_t res;
5322
Emilian Peevaebbe412018-01-15 13:53:24 +00005323 CameraMetadata &metadata = request->mSettingsList.begin()->metadata;
Eino-Ville Talvala2f876f92013-09-13 11:39:24 -07005324
5325 // If AF trigger is active, insert a dummy AF trigger ID if none already
5326 // exists
5327 camera_metadata_entry afTrigger = metadata.find(ANDROID_CONTROL_AF_TRIGGER);
5328 camera_metadata_entry afId = metadata.find(ANDROID_CONTROL_AF_TRIGGER_ID);
5329 if (afTrigger.count > 0 &&
5330 afTrigger.data.u8[0] != ANDROID_CONTROL_AF_TRIGGER_IDLE &&
5331 afId.count == 0) {
5332 res = metadata.update(ANDROID_CONTROL_AF_TRIGGER_ID, &dummyTriggerId, 1);
5333 if (res != OK) return res;
5334 }
5335
5336 // If AE precapture trigger is active, insert a dummy precapture trigger ID
5337 // if none already exists
5338 camera_metadata_entry pcTrigger =
5339 metadata.find(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER);
5340 camera_metadata_entry pcId = metadata.find(ANDROID_CONTROL_AE_PRECAPTURE_ID);
5341 if (pcTrigger.count > 0 &&
5342 pcTrigger.data.u8[0] != ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE &&
5343 pcId.count == 0) {
5344 res = metadata.update(ANDROID_CONTROL_AE_PRECAPTURE_ID,
5345 &dummyTriggerId, 1);
5346 if (res != OK) return res;
5347 }
5348
5349 return OK;
5350}
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005351
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08005352bool Camera3Device::RequestThread::overrideAutoRotateAndCrop(
5353 const sp<CaptureRequest> &request) {
5354 ATRACE_CALL();
5355
5356 if (request->mRotateAndCropAuto) {
5357 Mutex::Autolock l(mTriggerMutex);
5358 CameraMetadata &metadata = request->mSettingsList.begin()->metadata;
5359
5360 auto rotateAndCropEntry = metadata.find(ANDROID_SCALER_ROTATE_AND_CROP);
5361 if (rotateAndCropEntry.count > 0) {
5362 if (rotateAndCropEntry.data.u8[0] == mRotateAndCropOverride) {
5363 return false;
5364 } else {
5365 rotateAndCropEntry.data.u8[0] = mRotateAndCropOverride;
5366 return true;
5367 }
5368 } else {
5369 uint8_t rotateAndCrop_u8 = mRotateAndCropOverride;
5370 metadata.update(ANDROID_SCALER_ROTATE_AND_CROP,
5371 &rotateAndCrop_u8, 1);
5372 return true;
5373 }
5374 }
5375 return false;
5376}
5377
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005378/**
5379 * PreparerThread inner class methods
5380 */
5381
5382Camera3Device::PreparerThread::PreparerThread() :
Eino-Ville Talvala77c1a352016-06-13 12:32:43 -07005383 Thread(/*canCallJava*/false), mListener(nullptr),
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005384 mActive(false), mCancelNow(false), mCurrentMaxCount(0), mCurrentPrepareComplete(false) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005385}
5386
5387Camera3Device::PreparerThread::~PreparerThread() {
5388 Thread::requestExitAndWait();
5389 if (mCurrentStream != nullptr) {
5390 mCurrentStream->cancelPrepare();
5391 ATRACE_ASYNC_END("stream prepare", mCurrentStream->getId());
5392 mCurrentStream.clear();
5393 }
5394 clear();
5395}
5396
Ruben Brunkc78ac262015-08-13 17:58:46 -07005397status_t Camera3Device::PreparerThread::prepare(int maxCount, sp<Camera3StreamInterface>& stream) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005398 ATRACE_CALL();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005399 status_t res;
5400
5401 Mutex::Autolock l(mLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005402 sp<NotificationListener> listener = mListener.promote();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005403
Shuzhen Wangb3a0fb52018-09-13 17:24:08 -07005404 res = stream->startPrepare(maxCount, true /*blockRequest*/);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005405 if (res == OK) {
5406 // No preparation needed, fire listener right off
5407 ALOGV("%s: Stream %d already prepared", __FUNCTION__, stream->getId());
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005408 if (listener != NULL) {
5409 listener->notifyPrepared(stream->getId());
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005410 }
5411 return OK;
5412 } else if (res != NOT_ENOUGH_DATA) {
5413 return res;
5414 }
5415
5416 // Need to prepare, start up thread if necessary
5417 if (!mActive) {
5418 // mRunning will change to false before the thread fully shuts down, so wait to be sure it
5419 // isn't running
5420 Thread::requestExitAndWait();
5421 res = Thread::run("C3PrepThread", PRIORITY_BACKGROUND);
5422 if (res != OK) {
5423 ALOGE("%s: Unable to start preparer stream: %d (%s)", __FUNCTION__, res, strerror(-res));
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005424 if (listener != NULL) {
5425 listener->notifyPrepared(stream->getId());
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005426 }
5427 return res;
5428 }
5429 mCancelNow = false;
5430 mActive = true;
5431 ALOGV("%s: Preparer stream started", __FUNCTION__);
5432 }
5433
5434 // queue up the work
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005435 mPendingStreams.emplace(maxCount, stream);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005436 ALOGV("%s: Stream %d queued for preparing", __FUNCTION__, stream->getId());
5437
5438 return OK;
5439}
5440
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005441void Camera3Device::PreparerThread::pause() {
5442 ATRACE_CALL();
5443
5444 Mutex::Autolock l(mLock);
5445
5446 std::unordered_map<int, sp<camera3::Camera3StreamInterface> > pendingStreams;
5447 pendingStreams.insert(mPendingStreams.begin(), mPendingStreams.end());
5448 sp<camera3::Camera3StreamInterface> currentStream = mCurrentStream;
5449 int currentMaxCount = mCurrentMaxCount;
5450 mPendingStreams.clear();
5451 mCancelNow = true;
5452 while (mActive) {
5453 auto res = mThreadActiveSignal.waitRelative(mLock, kActiveTimeout);
5454 if (res == TIMED_OUT) {
5455 ALOGE("%s: Timed out waiting on prepare thread!", __FUNCTION__);
5456 return;
5457 } else if (res != OK) {
5458 ALOGE("%s: Encountered an error: %d waiting on prepare thread!", __FUNCTION__, res);
5459 return;
5460 }
5461 }
5462
5463 //Check whether the prepare thread was able to complete the current
5464 //stream. In case work is still pending emplace it along with the rest
5465 //of the streams in the pending list.
5466 if (currentStream != nullptr) {
5467 if (!mCurrentPrepareComplete) {
5468 pendingStreams.emplace(currentMaxCount, currentStream);
5469 }
5470 }
5471
5472 mPendingStreams.insert(pendingStreams.begin(), pendingStreams.end());
5473 for (const auto& it : mPendingStreams) {
5474 it.second->cancelPrepare();
5475 }
5476}
5477
5478status_t Camera3Device::PreparerThread::resume() {
5479 ATRACE_CALL();
5480 status_t res;
5481
5482 Mutex::Autolock l(mLock);
5483 sp<NotificationListener> listener = mListener.promote();
5484
5485 if (mActive) {
5486 ALOGE("%s: Trying to resume an already active prepare thread!", __FUNCTION__);
5487 return NO_INIT;
5488 }
5489
5490 auto it = mPendingStreams.begin();
5491 for (; it != mPendingStreams.end();) {
Shuzhen Wangb3a0fb52018-09-13 17:24:08 -07005492 res = it->second->startPrepare(it->first, true /*blockRequest*/);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005493 if (res == OK) {
5494 if (listener != NULL) {
5495 listener->notifyPrepared(it->second->getId());
5496 }
5497 it = mPendingStreams.erase(it);
5498 } else if (res != NOT_ENOUGH_DATA) {
5499 ALOGE("%s: Unable to start preparer stream: %d (%s)", __FUNCTION__,
5500 res, strerror(-res));
5501 it = mPendingStreams.erase(it);
5502 } else {
5503 it++;
5504 }
5505 }
5506
5507 if (mPendingStreams.empty()) {
5508 return OK;
5509 }
5510
5511 res = Thread::run("C3PrepThread", PRIORITY_BACKGROUND);
5512 if (res != OK) {
5513 ALOGE("%s: Unable to start preparer stream: %d (%s)",
5514 __FUNCTION__, res, strerror(-res));
5515 return res;
5516 }
5517 mCancelNow = false;
5518 mActive = true;
5519 ALOGV("%s: Preparer stream started", __FUNCTION__);
5520
5521 return OK;
5522}
5523
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005524status_t Camera3Device::PreparerThread::clear() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005525 ATRACE_CALL();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005526 Mutex::Autolock l(mLock);
5527
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005528 for (const auto& it : mPendingStreams) {
5529 it.second->cancelPrepare();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005530 }
5531 mPendingStreams.clear();
5532 mCancelNow = true;
5533
5534 return OK;
5535}
5536
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005537void Camera3Device::PreparerThread::setNotificationListener(wp<NotificationListener> listener) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005538 ATRACE_CALL();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005539 Mutex::Autolock l(mLock);
5540 mListener = listener;
5541}
5542
5543bool Camera3Device::PreparerThread::threadLoop() {
5544 status_t res;
5545 {
5546 Mutex::Autolock l(mLock);
5547 if (mCurrentStream == nullptr) {
5548 // End thread if done with work
5549 if (mPendingStreams.empty()) {
5550 ALOGV("%s: Preparer stream out of work", __FUNCTION__);
5551 // threadLoop _must not_ re-acquire mLock after it sets mActive to false; would
5552 // cause deadlock with prepare()'s requestExitAndWait triggered by !mActive.
5553 mActive = false;
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005554 mThreadActiveSignal.signal();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005555 return false;
5556 }
5557
5558 // Get next stream to prepare
5559 auto it = mPendingStreams.begin();
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005560 mCurrentStream = it->second;
5561 mCurrentMaxCount = it->first;
5562 mCurrentPrepareComplete = false;
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005563 mPendingStreams.erase(it);
5564 ATRACE_ASYNC_BEGIN("stream prepare", mCurrentStream->getId());
5565 ALOGV("%s: Preparing stream %d", __FUNCTION__, mCurrentStream->getId());
5566 } else if (mCancelNow) {
5567 mCurrentStream->cancelPrepare();
5568 ATRACE_ASYNC_END("stream prepare", mCurrentStream->getId());
5569 ALOGV("%s: Cancelling stream %d prepare", __FUNCTION__, mCurrentStream->getId());
5570 mCurrentStream.clear();
5571 mCancelNow = false;
5572 return true;
5573 }
5574 }
5575
5576 res = mCurrentStream->prepareNextBuffer();
5577 if (res == NOT_ENOUGH_DATA) return true;
5578 if (res != OK) {
5579 // Something bad happened; try to recover by cancelling prepare and
5580 // signalling listener anyway
5581 ALOGE("%s: Stream %d returned error %d (%s) during prepare", __FUNCTION__,
5582 mCurrentStream->getId(), res, strerror(-res));
5583 mCurrentStream->cancelPrepare();
5584 }
5585
5586 // This stream has finished, notify listener
5587 Mutex::Autolock l(mLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005588 sp<NotificationListener> listener = mListener.promote();
5589 if (listener != NULL) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005590 ALOGV("%s: Stream %d prepare done, signaling listener", __FUNCTION__,
5591 mCurrentStream->getId());
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005592 listener->notifyPrepared(mCurrentStream->getId());
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005593 }
5594
5595 ATRACE_ASYNC_END("stream prepare", mCurrentStream->getId());
5596 mCurrentStream.clear();
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005597 mCurrentPrepareComplete = true;
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005598
5599 return true;
5600}
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005601
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005602status_t Camera3Device::RequestBufferStateMachine::initialize(
5603 sp<camera3::StatusTracker> statusTracker) {
5604 if (statusTracker == nullptr) {
5605 ALOGE("%s: statusTracker is null", __FUNCTION__);
5606 return BAD_VALUE;
5607 }
5608
5609 std::lock_guard<std::mutex> lock(mLock);
5610 mStatusTracker = statusTracker;
5611 mRequestBufferStatusId = statusTracker->addComponent();
5612 return OK;
5613}
5614
5615bool Camera3Device::RequestBufferStateMachine::startRequestBuffer() {
5616 std::lock_guard<std::mutex> lock(mLock);
Yin-Chia Yeh8a4ccb02018-11-16 15:43:36 -08005617 if (mStatus == RB_STATUS_READY || mStatus == RB_STATUS_PENDING_STOP) {
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005618 mRequestBufferOngoing = true;
Yin-Chia Yeh8a4ccb02018-11-16 15:43:36 -08005619 notifyTrackerLocked(/*active*/true);
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005620 return true;
5621 }
5622 return false;
5623}
5624
5625void Camera3Device::RequestBufferStateMachine::endRequestBuffer() {
5626 std::lock_guard<std::mutex> lock(mLock);
5627 if (!mRequestBufferOngoing) {
5628 ALOGE("%s called without a successful startRequestBuffer call first!", __FUNCTION__);
5629 return;
5630 }
5631 mRequestBufferOngoing = false;
5632 if (mStatus == RB_STATUS_PENDING_STOP) {
5633 checkSwitchToStopLocked();
5634 }
Yin-Chia Yeh8a4ccb02018-11-16 15:43:36 -08005635 notifyTrackerLocked(/*active*/false);
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005636}
5637
5638void Camera3Device::RequestBufferStateMachine::onStreamsConfigured() {
5639 std::lock_guard<std::mutex> lock(mLock);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005640 mSwitchedToOffline = false;
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005641 mStatus = RB_STATUS_READY;
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005642 return;
5643}
5644
Yin-Chia Yehcd333fe2019-02-08 13:45:41 -08005645void Camera3Device::RequestBufferStateMachine::onSubmittingRequest() {
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005646 std::lock_guard<std::mutex> lock(mLock);
5647 mRequestThreadPaused = false;
Yin-Chia Yehcd333fe2019-02-08 13:45:41 -08005648 // inflight map register actually happens in prepareHalRequest now, but it is close enough
5649 // approximation.
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005650 mInflightMapEmpty = false;
5651 if (mStatus == RB_STATUS_STOPPED) {
5652 mStatus = RB_STATUS_READY;
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005653 }
5654 return;
5655}
5656
5657void Camera3Device::RequestBufferStateMachine::onRequestThreadPaused() {
5658 std::lock_guard<std::mutex> lock(mLock);
5659 mRequestThreadPaused = true;
5660 if (mStatus == RB_STATUS_PENDING_STOP) {
5661 checkSwitchToStopLocked();
5662 }
5663 return;
5664}
5665
5666void Camera3Device::RequestBufferStateMachine::onInflightMapEmpty() {
5667 std::lock_guard<std::mutex> lock(mLock);
5668 mInflightMapEmpty = true;
5669 if (mStatus == RB_STATUS_PENDING_STOP) {
5670 checkSwitchToStopLocked();
5671 }
5672 return;
5673}
5674
5675void Camera3Device::RequestBufferStateMachine::onWaitUntilIdle() {
5676 std::lock_guard<std::mutex> lock(mLock);
5677 if (!checkSwitchToStopLocked()) {
5678 mStatus = RB_STATUS_PENDING_STOP;
5679 }
5680 return;
5681}
5682
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005683bool Camera3Device::RequestBufferStateMachine::onSwitchToOfflineSuccess() {
5684 std::lock_guard<std::mutex> lock(mLock);
5685 if (mRequestBufferOngoing) {
5686 ALOGE("%s: HAL must not be requesting buffer after HAL returns switchToOffline!",
5687 __FUNCTION__);
5688 return false;
5689 }
5690 mSwitchedToOffline = true;
5691 mInflightMapEmpty = true;
5692 mRequestThreadPaused = true;
5693 mStatus = RB_STATUS_STOPPED;
5694 return true;
5695}
5696
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005697void Camera3Device::RequestBufferStateMachine::notifyTrackerLocked(bool active) {
5698 sp<StatusTracker> statusTracker = mStatusTracker.promote();
5699 if (statusTracker != nullptr) {
5700 if (active) {
5701 statusTracker->markComponentActive(mRequestBufferStatusId);
5702 } else {
5703 statusTracker->markComponentIdle(mRequestBufferStatusId, Fence::NO_FENCE);
5704 }
5705 }
5706}
5707
5708bool Camera3Device::RequestBufferStateMachine::checkSwitchToStopLocked() {
5709 if (mInflightMapEmpty && mRequestThreadPaused && !mRequestBufferOngoing) {
5710 mStatus = RB_STATUS_STOPPED;
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005711 return true;
5712 }
5713 return false;
5714}
5715
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005716bool Camera3Device::startRequestBuffer() {
5717 return mRequestBufferSM.startRequestBuffer();
5718}
Shuzhen Wang268a1362018-10-16 16:32:59 -07005719
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005720void Camera3Device::endRequestBuffer() {
5721 mRequestBufferSM.endRequestBuffer();
5722}
Shuzhen Wang268a1362018-10-16 16:32:59 -07005723
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005724nsecs_t Camera3Device::getWaitDuration() {
5725 return kBaseGetBufferWait + getExpectedInFlightDuration();
5726}
Shuzhen Wang268a1362018-10-16 16:32:59 -07005727
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005728void Camera3Device::getInflightBufferKeys(std::vector<std::pair<int32_t, int32_t>>* out) {
5729 mInterface->getInflightBufferKeys(out);
5730}
Shuzhen Wang268a1362018-10-16 16:32:59 -07005731
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005732void Camera3Device::getInflightRequestBufferKeys(std::vector<uint64_t>* out) {
5733 mInterface->getInflightRequestBufferKeys(out);
5734}
Shuzhen Wang268a1362018-10-16 16:32:59 -07005735
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005736std::vector<sp<Camera3StreamInterface>> Camera3Device::getAllStreams() {
5737 std::vector<sp<Camera3StreamInterface>> ret;
5738 bool hasInputStream = mInputStream != nullptr;
5739 ret.reserve(mOutputStreams.size() + mDeletedStreams.size() + ((hasInputStream) ? 1 : 0));
5740 if (hasInputStream) {
5741 ret.push_back(mInputStream);
Shuzhen Wang268a1362018-10-16 16:32:59 -07005742 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005743 for (size_t i = 0; i < mOutputStreams.size(); i++) {
5744 ret.push_back(mOutputStreams[i]);
5745 }
5746 for (size_t i = 0; i < mDeletedStreams.size(); i++) {
5747 ret.push_back(mDeletedStreams[i]);
5748 }
5749 return ret;
Shuzhen Wang268a1362018-10-16 16:32:59 -07005750}
5751
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005752status_t Camera3Device::switchToOffline(
5753 const std::vector<int32_t>& streamsToKeep,
5754 /*out*/ sp<CameraOfflineSessionBase>* session) {
5755 ATRACE_CALL();
5756 if (session == nullptr) {
5757 ALOGE("%s: session must not be null", __FUNCTION__);
5758 return BAD_VALUE;
5759 }
5760
5761 Mutex::Autolock il(mInterfaceLock);
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005762
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005763 bool hasInputStream = mInputStream != nullptr;
5764 int32_t inputStreamId = hasInputStream ? mInputStream->getId() : -1;
5765 bool inputStreamSupportsOffline = hasInputStream ?
5766 mInputStream->getOfflineProcessingSupport() : false;
5767 auto outputStreamIds = mOutputStreams.getStreamIds();
5768 auto streamIds = outputStreamIds;
5769 if (hasInputStream) {
5770 streamIds.push_back(mInputStream->getId());
5771 }
5772
5773 // Check all streams in streamsToKeep supports offline mode
5774 for (auto id : streamsToKeep) {
5775 if (std::find(streamIds.begin(), streamIds.end(), id) == streamIds.end()) {
5776 ALOGE("%s: Unknown stream ID %d", __FUNCTION__, id);
5777 return BAD_VALUE;
5778 } else if (id == inputStreamId) {
5779 if (!inputStreamSupportsOffline) {
5780 ALOGE("%s: input stream %d cannot be switched to offline",
5781 __FUNCTION__, id);
5782 return BAD_VALUE;
5783 }
5784 } else {
5785 sp<camera3::Camera3OutputStreamInterface> stream = mOutputStreams.get(id);
5786 if (!stream->getOfflineProcessingSupport()) {
5787 ALOGE("%s: output stream %d cannot be switched to offline",
5788 __FUNCTION__, id);
5789 return BAD_VALUE;
5790 }
5791 }
5792 }
5793
5794 // TODO: block surface sharing and surface group streams until we can support them
5795
5796 // Stop repeating request, wait until all remaining requests are submitted, then call into
5797 // HAL switchToOffline
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005798 hardware::camera::device::V3_6::CameraOfflineSessionInfo offlineSessionInfo;
5799 sp<hardware::camera::device::V3_6::ICameraOfflineSession> offlineSession;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005800 camera3::BufferRecords bufferRecords;
5801 status_t ret = mRequestThread->switchToOffline(
5802 streamsToKeep, &offlineSessionInfo, &offlineSession, &bufferRecords);
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005803
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005804 if (ret != OK) {
5805 SET_ERR("Switch to offline failed: %s (%d)", strerror(-ret), ret);
5806 return ret;
5807 }
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005808
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005809 bool succ = mRequestBufferSM.onSwitchToOfflineSuccess();
5810 if (!succ) {
5811 SET_ERR("HAL must not be calling requestStreamBuffers call");
5812 // TODO: block ALL callbacks from HAL till app configured new streams?
5813 return UNKNOWN_ERROR;
5814 }
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005815
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005816 // Verify offlineSessionInfo
5817 std::vector<int32_t> offlineStreamIds;
5818 offlineStreamIds.reserve(offlineSessionInfo.offlineStreams.size());
5819 for (auto offlineStream : offlineSessionInfo.offlineStreams) {
5820 // verify stream IDs
5821 int32_t id = offlineStream.id;
5822 if (std::find(streamIds.begin(), streamIds.end(), id) == streamIds.end()) {
5823 SET_ERR("stream ID %d not found!", id);
5824 return UNKNOWN_ERROR;
5825 }
5826
5827 // When not using HAL buf manager, only allow streams requested by app to be preserved
5828 if (!mUseHalBufManager) {
5829 if (std::find(streamsToKeep.begin(), streamsToKeep.end(), id) == streamsToKeep.end()) {
5830 SET_ERR("stream ID %d must not be switched to offline!", id);
5831 return UNKNOWN_ERROR;
5832 }
5833 }
5834
5835 offlineStreamIds.push_back(id);
5836 sp<Camera3StreamInterface> stream = (id == inputStreamId) ?
5837 static_cast<sp<Camera3StreamInterface>>(mInputStream) :
5838 static_cast<sp<Camera3StreamInterface>>(mOutputStreams.get(id));
5839 // Verify number of outstanding buffers
5840 if (stream->getOutstandingBuffersCount() != offlineStream.numOutstandingBuffers) {
5841 SET_ERR("Offline stream %d # of remaining buffer mismatch: (%zu,%d) (service/HAL)",
5842 id, stream->getOutstandingBuffersCount(), offlineStream.numOutstandingBuffers);
5843 return UNKNOWN_ERROR;
5844 }
5845 }
5846
5847 // Verify all streams to be deleted don't have any outstanding buffers
5848 if (hasInputStream && std::find(offlineStreamIds.begin(), offlineStreamIds.end(),
5849 inputStreamId) == offlineStreamIds.end()) {
5850 if (mInputStream->hasOutstandingBuffers()) {
5851 SET_ERR("Input stream %d still has %zu outstanding buffer!",
5852 inputStreamId, mInputStream->getOutstandingBuffersCount());
5853 return UNKNOWN_ERROR;
5854 }
5855 }
5856
5857 for (const auto& outStreamId : outputStreamIds) {
5858 if (std::find(offlineStreamIds.begin(), offlineStreamIds.end(),
5859 outStreamId) == offlineStreamIds.end()) {
5860 auto outStream = mOutputStreams.get(outStreamId);
5861 if (outStream->hasOutstandingBuffers()) {
5862 SET_ERR("Output stream %d still has %zu outstanding buffer!",
5863 outStreamId, outStream->getOutstandingBuffersCount());
5864 return UNKNOWN_ERROR;
5865 }
5866 }
5867 }
5868
5869 InFlightRequestMap offlineReqs;
5870 // Verify inflight requests and their pending buffers
5871 {
5872 std::lock_guard<std::mutex> l(mInFlightLock);
5873 for (auto offlineReq : offlineSessionInfo.offlineRequests) {
5874 int idx = mInFlightMap.indexOfKey(offlineReq.frameNumber);
5875 if (idx == NAME_NOT_FOUND) {
5876 SET_ERR("Offline request frame number %d not found!", offlineReq.frameNumber);
5877 return UNKNOWN_ERROR;
5878 }
5879
5880 const auto& inflightReq = mInFlightMap.valueAt(idx);
5881 // TODO: check specific stream IDs
5882 size_t numBuffersLeft = static_cast<size_t>(inflightReq.numBuffersLeft);
5883 if (numBuffersLeft != offlineReq.pendingStreams.size()) {
5884 SET_ERR("Offline request # of remaining buffer mismatch: (%d,%d) (service/HAL)",
5885 inflightReq.numBuffersLeft, offlineReq.pendingStreams.size());
5886 return UNKNOWN_ERROR;
5887 }
5888 offlineReqs.add(offlineReq.frameNumber, inflightReq);
5889 }
5890 }
5891
5892 // Create Camera3OfflineSession and transfer object ownership
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005893 // (streams, inflight requests, buffer caches)
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005894 camera3::StreamSet offlineStreamSet;
5895 sp<camera3::Camera3Stream> inputStream;
5896 for (auto offlineStream : offlineSessionInfo.offlineStreams) {
5897 int32_t id = offlineStream.id;
5898 if (mInputStream != nullptr && id == mInputStream->getId()) {
5899 inputStream = mInputStream;
5900 } else {
5901 offlineStreamSet.add(id, mOutputStreams.get(id));
5902 }
5903 }
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005904
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005905 // TODO: check if we need to lock before copying states
5906 // though technically no other thread should be talking to Camera3Device at this point
5907 Camera3OfflineStates offlineStates(
5908 mTagMonitor, mVendorTagId, mUseHalBufManager, mNeedFixupMonochromeTags,
5909 mUsePartialResult, mNumPartialResults, mNextResultFrameNumber,
5910 mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
5911 mNextShutterFrameNumber, mNextReprocessShutterFrameNumber,
5912 mNextZslStillShutterFrameNumber, mDeviceInfo, mPhysicalDeviceInfoMap,
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08005913 mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005914
5915 *session = new Camera3OfflineSession(mId, inputStream, offlineStreamSet,
5916 std::move(bufferRecords), offlineReqs, offlineStates, offlineSession);
5917
5918 // Delete all streams that has been transferred to offline session
5919 Mutex::Autolock l(mLock);
5920 for (auto offlineStream : offlineSessionInfo.offlineStreams) {
5921 int32_t id = offlineStream.id;
5922 if (mInputStream != nullptr && id == mInputStream->getId()) {
5923 mInputStream.clear();
5924 } else {
5925 mOutputStreams.remove(id);
5926 }
5927 }
5928
5929 // disconnect all other streams and switch to UNCONFIGURED state
5930 if (mInputStream != nullptr) {
5931 ret = mInputStream->disconnect();
5932 if (ret != OK) {
5933 SET_ERR_L("disconnect input stream failed!");
5934 return UNKNOWN_ERROR;
5935 }
5936 }
5937
5938 for (auto streamId : mOutputStreams.getStreamIds()) {
5939 sp<Camera3StreamInterface> stream = mOutputStreams.get(streamId);
5940 ret = stream->disconnect();
5941 if (ret != OK) {
5942 SET_ERR_L("disconnect output stream %d failed!", streamId);
5943 return UNKNOWN_ERROR;
5944 }
5945 }
5946
5947 mInputStream.clear();
5948 mOutputStreams.clear();
5949 mNeedConfig = true;
5950 internalUpdateStatusLocked(STATUS_UNCONFIGURED);
5951 mOperatingMode = NO_MODE;
5952 mIsConstrainedHighSpeedConfiguration = false;
Emilian Peevc0fe54c2020-03-11 14:05:07 -07005953 mRequestThread->clearPreviousRequest();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005954
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005955 return OK;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005956 // TO be done by CameraDeviceClient/Camera3OfflineSession
5957 // register the offline client to camera service
5958 // Setup result passthing threads etc
5959 // Initialize offline session so HAL can start sending callback to it (result Fmq)
5960 // TODO: check how many onIdle callback will be sent
5961 // Java side to make sure the CameraCaptureSession is properly closed
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005962}
5963
Emilian Peevcc0b7952020-01-07 13:54:47 -08005964void Camera3Device::getOfflineStreamIds(std::vector<int> *offlineStreamIds) {
5965 ATRACE_CALL();
5966
5967 if (offlineStreamIds == nullptr) {
5968 return;
5969 }
5970
5971 Mutex::Autolock il(mInterfaceLock);
5972
5973 auto streamIds = mOutputStreams.getStreamIds();
5974 bool hasInputStream = mInputStream != nullptr;
5975 if (hasInputStream && mInputStream->getOfflineProcessingSupport()) {
5976 offlineStreamIds->push_back(mInputStream->getId());
5977 }
5978
5979 for (const auto & streamId : streamIds) {
5980 sp<camera3::Camera3OutputStreamInterface> stream = mOutputStreams.get(streamId);
5981 // Streams that use the camera buffer manager are currently not supported in
5982 // offline mode
5983 if (stream->getOfflineProcessingSupport() &&
5984 (stream->getStreamSetId() == CAMERA3_STREAM_SET_ID_INVALID)) {
5985 offlineStreamIds->push_back(streamId);
5986 }
5987 }
5988}
5989
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08005990status_t Camera3Device::setRotateAndCropAutoBehavior(
5991 camera_metadata_enum_android_scaler_rotate_and_crop_t rotateAndCropValue) {
5992 ATRACE_CALL();
5993 Mutex::Autolock il(mInterfaceLock);
5994 Mutex::Autolock l(mLock);
5995 if (mRequestThread == nullptr) {
5996 return INVALID_OPERATION;
5997 }
5998 return mRequestThread->setRotateAndCropAutoBehavior(rotateAndCropValue);
5999}
6000
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08006001}; // namespace android