blob: d38bfee02109323874245f7bf43a5e667c1407c7 [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();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700367 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800368
Yin-Chia Yehe1c80632016-08-08 14:48:05 -0700369 ALOGI("%s: E", __FUNCTION__);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800370
Eino-Ville Talvala214a17f2013-06-13 12:20:02 -0700371 status_t res = OK;
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700372 std::vector<wp<Camera3StreamInterface>> streams;
Yin-Chia Yeh598fc602017-07-24 11:37:23 -0700373 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700374 {
375 Mutex::Autolock l(mLock);
376 if (mStatus == STATUS_UNINITIALIZED) return res;
377
378 if (mStatus == STATUS_ACTIVE ||
379 (mStatus == STATUS_ERROR && mRequestThread != NULL)) {
380 res = mRequestThread->clearRepeatingRequests();
Eino-Ville Talvala214a17f2013-06-13 12:20:02 -0700381 if (res != OK) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700382 SET_ERR_L("Can't stop streaming");
Eino-Ville Talvala214a17f2013-06-13 12:20:02 -0700383 // Continue to close device even in case of error
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700384 } else {
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -0700385 res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700386 if (res != OK) {
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -0700387 SET_ERR_L("Timeout waiting for HAL to drain (% " PRIi64 " ns)",
388 maxExpectedDuration);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700389 // Continue to close device even in case of error
390 }
Eino-Ville Talvala214a17f2013-06-13 12:20:02 -0700391 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800392 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800393
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700394 if (mStatus == STATUS_ERROR) {
395 CLOGE("Shutting down in an error state");
Eino-Ville Talvala214a17f2013-06-13 12:20:02 -0700396 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700397
398 if (mStatusTracker != NULL) {
399 mStatusTracker->requestExit();
400 }
401
402 if (mRequestThread != NULL) {
403 mRequestThread->requestExit();
404 }
405
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700406 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 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700413 }
414
415 // Joining done without holding mLock, otherwise deadlocks may ensue
416 // as the threads try to access parent state
417 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.
421 mRequestThread->join();
422 }
423
424 if (mStatusTracker != NULL) {
425 mStatusTracker->join();
426 }
427
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800428 HalInterface* interface;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700429 {
430 Mutex::Autolock l(mLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800431 mRequestThread.clear();
Emilian Peev2843c362018-09-26 08:49:40 +0100432 Mutex::Autolock stLock(mTrackerLock);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700433 mStatusTracker.clear();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800434 interface = mInterface.get();
Eino-Ville Talvalaefff1c42015-08-28 16:27:27 -0700435 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800436
Eino-Ville Talvalaefff1c42015-08-28 16:27:27 -0700437 // Call close without internal mutex held, as the HAL close may need to
438 // wait on assorted callbacks,etc, to complete before it can return.
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800439 interface->close();
Eino-Ville Talvalaefff1c42015-08-28 16:27:27 -0700440
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700441 flushInflightRequests();
442
Eino-Ville Talvalaefff1c42015-08-28 16:27:27 -0700443 {
444 Mutex::Autolock l(mLock);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800445 mInterface->clear();
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700446 mOutputStreams.clear();
447 mInputStream.clear();
Yin-Chia Yeh5090c732017-07-20 16:05:29 -0700448 mDeletedStreams.clear();
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700449 mBufferManager.clear();
Ruben Brunk183f0562015-08-12 12:55:02 -0700450 internalUpdateStatusLocked(STATUS_UNINITIALIZED);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700451 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800452
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700453 for (auto& weakStream : streams) {
454 sp<Camera3StreamInterface> stream = weakStream.promote();
455 if (stream != nullptr) {
456 ALOGE("%s: Stream %d leaked! strong reference (%d)!",
457 __FUNCTION__, stream->getId(), stream->getStrongCount() - 1);
458 }
459 }
460
Yin-Chia Yehe1c80632016-08-08 14:48:05 -0700461 ALOGI("%s: X", __FUNCTION__);
Eino-Ville Talvala214a17f2013-06-13 12:20:02 -0700462 return res;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800463}
464
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700465// For dumping/debugging only -
466// try to acquire a lock a few times, eventually give up to proceed with
467// debug/dump operations
468bool Camera3Device::tryLockSpinRightRound(Mutex& lock) {
469 bool gotLock = false;
470 for (size_t i = 0; i < kDumpLockAttempts; ++i) {
471 if (lock.tryLock() == NO_ERROR) {
472 gotLock = true;
473 break;
474 } else {
475 usleep(kDumpSleepDuration);
476 }
477 }
478 return gotLock;
479}
480
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700481Camera3Device::Size Camera3Device::getMaxJpegResolution() const {
482 int32_t maxJpegWidth = 0, maxJpegHeight = 0;
Emilian Peev08dd2452017-04-06 16:55:14 +0100483 const int STREAM_CONFIGURATION_SIZE = 4;
484 const int STREAM_FORMAT_OFFSET = 0;
485 const int STREAM_WIDTH_OFFSET = 1;
486 const int STREAM_HEIGHT_OFFSET = 2;
487 const int STREAM_IS_INPUT_OFFSET = 3;
488 camera_metadata_ro_entry_t availableStreamConfigs =
489 mDeviceInfo.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
490 if (availableStreamConfigs.count == 0 ||
491 availableStreamConfigs.count % STREAM_CONFIGURATION_SIZE != 0) {
492 return Size(0, 0);
493 }
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700494
Emilian Peev08dd2452017-04-06 16:55:14 +0100495 // Get max jpeg size (area-wise).
496 for (size_t i=0; i < availableStreamConfigs.count; i+= STREAM_CONFIGURATION_SIZE) {
497 int32_t format = availableStreamConfigs.data.i32[i + STREAM_FORMAT_OFFSET];
498 int32_t width = availableStreamConfigs.data.i32[i + STREAM_WIDTH_OFFSET];
499 int32_t height = availableStreamConfigs.data.i32[i + STREAM_HEIGHT_OFFSET];
500 int32_t isInput = availableStreamConfigs.data.i32[i + STREAM_IS_INPUT_OFFSET];
501 if (isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT
502 && format == HAL_PIXEL_FORMAT_BLOB &&
503 (width * height > maxJpegWidth * maxJpegHeight)) {
504 maxJpegWidth = width;
505 maxJpegHeight = height;
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700506 }
507 }
Emilian Peev08dd2452017-04-06 16:55:14 +0100508
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700509 return Size(maxJpegWidth, maxJpegHeight);
510}
511
Shuzhen Wangc28dccc2016-02-11 23:48:46 -0800512nsecs_t Camera3Device::getMonoToBoottimeOffset() {
513 // try three times to get the clock offset, choose the one
514 // with the minimum gap in measurements.
515 const int tries = 3;
516 nsecs_t bestGap, measured;
517 for (int i = 0; i < tries; ++i) {
518 const nsecs_t tmono = systemTime(SYSTEM_TIME_MONOTONIC);
519 const nsecs_t tbase = systemTime(SYSTEM_TIME_BOOTTIME);
520 const nsecs_t tmono2 = systemTime(SYSTEM_TIME_MONOTONIC);
521 const nsecs_t gap = tmono2 - tmono;
522 if (i == 0 || gap < bestGap) {
523 bestGap = gap;
524 measured = tbase - ((tmono + tmono2) >> 1);
525 }
526 }
527 return measured;
528}
529
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800530hardware::graphics::common::V1_0::PixelFormat Camera3Device::mapToPixelFormat(
531 int frameworkFormat) {
532 return (hardware::graphics::common::V1_0::PixelFormat) frameworkFormat;
533}
534
535DataspaceFlags Camera3Device::mapToHidlDataspace(
536 android_dataspace dataSpace) {
537 return dataSpace;
538}
539
Chia-I Wu67a0c0e2017-04-06 13:37:01 -0700540BufferUsageFlags Camera3Device::mapToConsumerUsage(
Emilian Peev050f5dc2017-05-18 14:43:56 +0100541 uint64_t usage) {
Yin-Chia Yeh47cf8e62017-04-04 13:00:03 -0700542 return usage;
543}
544
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800545StreamRotation Camera3Device::mapToStreamRotation(camera3_stream_rotation_t rotation) {
546 switch (rotation) {
547 case CAMERA3_STREAM_ROTATION_0:
548 return StreamRotation::ROTATION_0;
549 case CAMERA3_STREAM_ROTATION_90:
550 return StreamRotation::ROTATION_90;
551 case CAMERA3_STREAM_ROTATION_180:
552 return StreamRotation::ROTATION_180;
553 case CAMERA3_STREAM_ROTATION_270:
554 return StreamRotation::ROTATION_270;
555 }
556 ALOGE("%s: Unknown stream rotation %d", __FUNCTION__, rotation);
557 return StreamRotation::ROTATION_0;
558}
559
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -0800560status_t Camera3Device::mapToStreamConfigurationMode(
561 camera3_stream_configuration_mode_t operationMode, StreamConfigurationMode *mode) {
562 if (mode == nullptr) return BAD_VALUE;
563 if (operationMode < CAMERA3_VENDOR_STREAM_CONFIGURATION_MODE_START) {
564 switch(operationMode) {
565 case CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE:
566 *mode = StreamConfigurationMode::NORMAL_MODE;
567 break;
568 case CAMERA3_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE:
569 *mode = StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE;
570 break;
571 default:
572 ALOGE("%s: Unknown stream configuration mode %d", __FUNCTION__, operationMode);
573 return BAD_VALUE;
574 }
575 } else {
576 *mode = static_cast<StreamConfigurationMode>(operationMode);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800577 }
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -0800578 return OK;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800579}
580
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800581int Camera3Device::mapToFrameworkFormat(
582 hardware::graphics::common::V1_0::PixelFormat pixelFormat) {
583 return static_cast<uint32_t>(pixelFormat);
584}
585
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -0700586android_dataspace Camera3Device::mapToFrameworkDataspace(
587 DataspaceFlags dataSpace) {
588 return static_cast<android_dataspace>(dataSpace);
589}
590
Emilian Peev050f5dc2017-05-18 14:43:56 +0100591uint64_t Camera3Device::mapConsumerToFrameworkUsage(
Chia-I Wu67a0c0e2017-04-06 13:37:01 -0700592 BufferUsageFlags usage) {
Yin-Chia Yeh47cf8e62017-04-04 13:00:03 -0700593 return usage;
594}
595
Emilian Peev050f5dc2017-05-18 14:43:56 +0100596uint64_t Camera3Device::mapProducerToFrameworkUsage(
Chia-I Wu67a0c0e2017-04-06 13:37:01 -0700597 BufferUsageFlags usage) {
Yin-Chia Yeh47cf8e62017-04-04 13:00:03 -0700598 return usage;
599}
600
Zhijun Hef7da0962014-04-24 13:27:56 -0700601ssize_t Camera3Device::getJpegBufferSize(uint32_t width, uint32_t height) const {
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700602 // Get max jpeg size (area-wise).
603 Size maxJpegResolution = getMaxJpegResolution();
604 if (maxJpegResolution.width == 0) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800605 ALOGE("%s: Camera %s: Can't find valid available jpeg sizes in static metadata!",
606 __FUNCTION__, mId.string());
Zhijun Hef7da0962014-04-24 13:27:56 -0700607 return BAD_VALUE;
608 }
609
Zhijun Hef7da0962014-04-24 13:27:56 -0700610 // Get max jpeg buffer size
611 ssize_t maxJpegBufferSize = 0;
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700612 camera_metadata_ro_entry jpegBufMaxSize = mDeviceInfo.find(ANDROID_JPEG_MAX_SIZE);
613 if (jpegBufMaxSize.count == 0) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800614 ALOGE("%s: Camera %s: Can't find maximum JPEG size in static metadata!", __FUNCTION__,
615 mId.string());
Zhijun Hef7da0962014-04-24 13:27:56 -0700616 return BAD_VALUE;
617 }
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700618 maxJpegBufferSize = jpegBufMaxSize.data.i32[0];
Yin-Chia Yeh0c4e56d2015-01-09 15:21:27 -0800619 assert(kMinJpegBufferSize < maxJpegBufferSize);
Zhijun Hef7da0962014-04-24 13:27:56 -0700620
621 // Calculate final jpeg buffer size for the given resolution.
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700622 float scaleFactor = ((float) (width * height)) /
623 (maxJpegResolution.width * maxJpegResolution.height);
Yin-Chia Yeh0c4e56d2015-01-09 15:21:27 -0800624 ssize_t jpegBufferSize = scaleFactor * (maxJpegBufferSize - kMinJpegBufferSize) +
625 kMinJpegBufferSize;
Zhijun Hef7da0962014-04-24 13:27:56 -0700626 if (jpegBufferSize > maxJpegBufferSize) {
627 jpegBufferSize = maxJpegBufferSize;
Zhijun Hef7da0962014-04-24 13:27:56 -0700628 }
629
630 return jpegBufferSize;
631}
632
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -0700633ssize_t Camera3Device::getPointCloudBufferSize() const {
634 const int FLOATS_PER_POINT=4;
635 camera_metadata_ro_entry maxPointCount = mDeviceInfo.find(ANDROID_DEPTH_MAX_DEPTH_SAMPLES);
636 if (maxPointCount.count == 0) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800637 ALOGE("%s: Camera %s: Can't find maximum depth point cloud size in static metadata!",
638 __FUNCTION__, mId.string());
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -0700639 return BAD_VALUE;
640 }
641 ssize_t maxBytesForPointCloud = sizeof(android_depth_points) +
642 maxPointCount.data.i32[0] * sizeof(float) * FLOATS_PER_POINT;
643 return maxBytesForPointCloud;
644}
645
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800646ssize_t Camera3Device::getRawOpaqueBufferSize(int32_t width, int32_t height) const {
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800647 const int PER_CONFIGURATION_SIZE = 3;
648 const int WIDTH_OFFSET = 0;
649 const int HEIGHT_OFFSET = 1;
650 const int SIZE_OFFSET = 2;
651 camera_metadata_ro_entry rawOpaqueSizes =
652 mDeviceInfo.find(ANDROID_SENSOR_OPAQUE_RAW_SIZE);
Aurimas Liutikasbc57b122016-02-16 09:59:16 -0800653 size_t count = rawOpaqueSizes.count;
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800654 if (count == 0 || (count % PER_CONFIGURATION_SIZE)) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800655 ALOGE("%s: Camera %s: bad opaque RAW size static metadata length(%zu)!",
656 __FUNCTION__, mId.string(), count);
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800657 return BAD_VALUE;
658 }
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -0700659
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800660 for (size_t i = 0; i < count; i += PER_CONFIGURATION_SIZE) {
661 if (width == rawOpaqueSizes.data.i32[i + WIDTH_OFFSET] &&
662 height == rawOpaqueSizes.data.i32[i + HEIGHT_OFFSET]) {
663 return rawOpaqueSizes.data.i32[i + SIZE_OFFSET];
664 }
665 }
666
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800667 ALOGE("%s: Camera %s: cannot find size for %dx%d opaque RAW image!",
668 __FUNCTION__, mId.string(), width, height);
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800669 return BAD_VALUE;
670}
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -0700671
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800672status_t Camera3Device::dump(int fd, const Vector<String16> &args) {
673 ATRACE_CALL();
674 (void)args;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700675
676 // Try to lock, but continue in case of failure (to avoid blocking in
677 // deadlocks)
678 bool gotInterfaceLock = tryLockSpinRightRound(mInterfaceLock);
679 bool gotLock = tryLockSpinRightRound(mLock);
680
681 ALOGW_IF(!gotInterfaceLock,
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800682 "Camera %s: %s: Unable to lock interface lock, proceeding anyway",
683 mId.string(), __FUNCTION__);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700684 ALOGW_IF(!gotLock,
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800685 "Camera %s: %s: Unable to lock main lock, proceeding anyway",
686 mId.string(), __FUNCTION__);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700687
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800688 bool dumpTemplates = false;
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700689
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800690 String16 templatesOption("-t");
691 int n = args.size();
692 for (int i = 0; i < n; i++) {
693 if (args[i] == templatesOption) {
694 dumpTemplates = true;
695 }
Emilian Peevbd8c5032018-02-14 23:05:40 +0000696 if (args[i] == TagMonitor::kMonitorOption) {
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700697 if (i + 1 < n) {
698 String8 monitorTags = String8(args[i + 1]);
699 if (monitorTags == "off") {
700 mTagMonitor.disableMonitoring();
701 } else {
702 mTagMonitor.parseTagsToMonitor(monitorTags);
703 }
704 } else {
705 mTagMonitor.disableMonitoring();
706 }
707 }
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800708 }
709
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800710 String8 lines;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800711
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800712 const char *status =
713 mStatus == STATUS_ERROR ? "ERROR" :
714 mStatus == STATUS_UNINITIALIZED ? "UNINITIALIZED" :
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700715 mStatus == STATUS_UNCONFIGURED ? "UNCONFIGURED" :
716 mStatus == STATUS_CONFIGURED ? "CONFIGURED" :
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800717 mStatus == STATUS_ACTIVE ? "ACTIVE" :
718 "Unknown";
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700719
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800720 lines.appendFormat(" Device status: %s\n", status);
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -0700721 if (mStatus == STATUS_ERROR) {
722 lines.appendFormat(" Error cause: %s\n", mErrorCause.string());
723 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800724 lines.appendFormat(" Stream configuration:\n");
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -0800725 const char *mode =
726 mOperatingMode == static_cast<int>(StreamConfigurationMode::NORMAL_MODE) ? "NORMAL" :
727 mOperatingMode == static_cast<int>(
728 StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE) ? "CONSTRAINED_HIGH_SPEED" :
729 "CUSTOM";
730 lines.appendFormat(" Operation mode: %s (%d) \n", mode, mOperatingMode);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800731
732 if (mInputStream != NULL) {
733 write(fd, lines.string(), lines.size());
734 mInputStream->dump(fd, args);
735 } else {
736 lines.appendFormat(" No input stream.\n");
737 write(fd, lines.string(), lines.size());
738 }
739 for (size_t i = 0; i < mOutputStreams.size(); i++) {
740 mOutputStreams[i]->dump(fd,args);
741 }
742
Zhijun He431503c2016-03-07 17:30:16 -0800743 if (mBufferManager != NULL) {
744 lines = String8(" Camera3 Buffer Manager:\n");
745 write(fd, lines.string(), lines.size());
746 mBufferManager->dump(fd, args);
747 }
Zhijun He125684a2015-12-26 15:07:30 -0800748
Eino-Ville Talvala42368d92013-04-09 14:13:50 -0700749 lines = String8(" In-flight requests:\n");
750 if (mInFlightMap.size() == 0) {
751 lines.append(" None\n");
752 } else {
753 for (size_t i = 0; i < mInFlightMap.size(); i++) {
754 InFlightRequest r = mInFlightMap.valueAt(i);
Colin Crosse5729fa2014-03-21 15:04:25 -0700755 lines.appendFormat(" Frame %d | Timestamp: %" PRId64 ", metadata"
Eino-Ville Talvala42368d92013-04-09 14:13:50 -0700756 " arrived: %s, buffers left: %d\n", mInFlightMap.keyAt(i),
Chien-Yu Chen43e69a62014-11-25 16:38:33 -0800757 r.shutterTimestamp, r.haveResultMetadata ? "true" : "false",
Eino-Ville Talvala42368d92013-04-09 14:13:50 -0700758 r.numBuffersLeft);
759 }
760 }
761 write(fd, lines.string(), lines.size());
762
Shuzhen Wang686f6442017-06-20 16:16:04 -0700763 if (mRequestThread != NULL) {
764 mRequestThread->dumpCaptureRequestLatency(fd,
765 " ProcessCaptureRequest latency histogram:");
766 }
767
Igor Murashkin1e479c02013-09-06 16:55:14 -0700768 {
769 lines = String8(" Last request sent:\n");
770 write(fd, lines.string(), lines.size());
771
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700772 CameraMetadata lastRequest = getLatestRequestLocked();
Igor Murashkin1e479c02013-09-06 16:55:14 -0700773 lastRequest.dump(fd, /*verbosity*/2, /*indentation*/6);
774 }
775
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800776 if (dumpTemplates) {
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -0800777 const char *templateNames[CAMERA3_TEMPLATE_COUNT] = {
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800778 "TEMPLATE_PREVIEW",
779 "TEMPLATE_STILL_CAPTURE",
780 "TEMPLATE_VIDEO_RECORD",
781 "TEMPLATE_VIDEO_SNAPSHOT",
782 "TEMPLATE_ZERO_SHUTTER_LAG",
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -0800783 "TEMPLATE_MANUAL",
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800784 };
785
786 for (int i = 1; i < CAMERA3_TEMPLATE_COUNT; i++) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800787 camera_metadata_t *templateRequest = nullptr;
788 mInterface->constructDefaultRequestSettings(
789 (camera3_request_template_t) i, &templateRequest);
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800790 lines = String8::format(" HAL Request %s:\n", templateNames[i-1]);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800791 if (templateRequest == nullptr) {
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800792 lines.append(" Not supported\n");
793 write(fd, lines.string(), lines.size());
794 } else {
795 write(fd, lines.string(), lines.size());
796 dump_indented_camera_metadata(templateRequest,
797 fd, /*verbosity*/2, /*indentation*/8);
798 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800799 free_camera_metadata(templateRequest);
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800800 }
801 }
802
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700803 mTagMonitor.dumpMonitoredMetadata(fd);
804
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800805 if (mInterface->valid()) {
Eino-Ville Talvalad00111e2017-01-31 11:59:12 -0800806 lines = String8(" HAL device dump:\n");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800807 write(fd, lines.string(), lines.size());
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800808 mInterface->dump(fd);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800809 }
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800810
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700811 if (gotLock) mLock.unlock();
812 if (gotInterfaceLock) mInterfaceLock.unlock();
813
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800814 return OK;
815}
816
Shuzhen Wang2e7f58f2018-07-11 14:00:29 -0700817const CameraMetadata& Camera3Device::info(const String8& physicalId) const {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800818 ALOGVV("%s: E", __FUNCTION__);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800819 if (CC_UNLIKELY(mStatus == STATUS_UNINITIALIZED ||
820 mStatus == STATUS_ERROR)) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -0700821 ALOGW("%s: Access to static info %s!", __FUNCTION__,
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800822 mStatus == STATUS_ERROR ?
823 "when in error state" : "before init");
824 }
Shuzhen Wang2e7f58f2018-07-11 14:00:29 -0700825 if (physicalId.isEmpty()) {
826 return mDeviceInfo;
827 } else {
828 std::string id(physicalId.c_str());
829 if (mPhysicalDeviceInfoMap.find(id) != mPhysicalDeviceInfoMap.end()) {
830 return mPhysicalDeviceInfoMap.at(id);
831 } else {
832 ALOGE("%s: Invalid physical camera id %s", __FUNCTION__, physicalId.c_str());
833 return mDeviceInfo;
834 }
835 }
836}
837
838const CameraMetadata& Camera3Device::info() const {
839 String8 emptyId;
840 return info(emptyId);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800841}
842
Jianing Wei90e59c92014-03-12 18:29:36 -0700843status_t Camera3Device::checkStatusOkToCaptureLocked() {
844 switch (mStatus) {
845 case STATUS_ERROR:
846 CLOGE("Device has encountered a serious error");
847 return INVALID_OPERATION;
848 case STATUS_UNINITIALIZED:
849 CLOGE("Device not initialized");
850 return INVALID_OPERATION;
851 case STATUS_UNCONFIGURED:
852 case STATUS_CONFIGURED:
853 case STATUS_ACTIVE:
854 // OK
855 break;
856 default:
857 SET_ERR_L("Unexpected status: %d", mStatus);
858 return INVALID_OPERATION;
859 }
860 return OK;
861}
862
863status_t Camera3Device::convertMetadataListToRequestListLocked(
Emilian Peevaebbe412018-01-15 13:53:24 +0000864 const List<const PhysicalCameraSettingsList> &metadataList,
Shuzhen Wang0129d522016-10-30 22:43:41 -0700865 const std::list<const SurfaceMap> &surfaceMaps,
866 bool repeating,
Shuzhen Wang9d066012016-09-30 11:30:20 -0700867 RequestList *requestList) {
Jianing Wei90e59c92014-03-12 18:29:36 -0700868 if (requestList == NULL) {
869 CLOGE("requestList cannot be NULL.");
870 return BAD_VALUE;
871 }
872
Jianing Weicb0652e2014-03-12 18:29:36 -0700873 int32_t burstId = 0;
Emilian Peevaebbe412018-01-15 13:53:24 +0000874 List<const PhysicalCameraSettingsList>::const_iterator metadataIt = metadataList.begin();
Shuzhen Wang0129d522016-10-30 22:43:41 -0700875 std::list<const SurfaceMap>::const_iterator surfaceMapIt = surfaceMaps.begin();
876 for (; metadataIt != metadataList.end() && surfaceMapIt != surfaceMaps.end();
877 ++metadataIt, ++surfaceMapIt) {
878 sp<CaptureRequest> newRequest = setUpRequestLocked(*metadataIt, *surfaceMapIt);
Jianing Wei90e59c92014-03-12 18:29:36 -0700879 if (newRequest == 0) {
880 CLOGE("Can't create capture request");
881 return BAD_VALUE;
882 }
Jianing Weicb0652e2014-03-12 18:29:36 -0700883
Shuzhen Wang9d066012016-09-30 11:30:20 -0700884 newRequest->mRepeating = repeating;
885
Jianing Weicb0652e2014-03-12 18:29:36 -0700886 // Setup burst Id and request Id
887 newRequest->mResultExtras.burstId = burstId++;
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -0800888 auto requestIdEntry = metadataIt->begin()->metadata.find(ANDROID_REQUEST_ID);
889 if (requestIdEntry.count == 0) {
Jianing Weicb0652e2014-03-12 18:29:36 -0700890 CLOGE("RequestID does not exist in metadata");
891 return BAD_VALUE;
892 }
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -0800893 newRequest->mResultExtras.requestId = requestIdEntry.data.i32[0];
Jianing Weicb0652e2014-03-12 18:29:36 -0700894
Jianing Wei90e59c92014-03-12 18:29:36 -0700895 requestList->push_back(newRequest);
Jianing Wei2d6bb3f2014-04-11 10:00:31 -0700896
897 ALOGV("%s: requestId = %" PRId32, __FUNCTION__, newRequest->mResultExtras.requestId);
Jianing Wei90e59c92014-03-12 18:29:36 -0700898 }
Shuzhen Wang0129d522016-10-30 22:43:41 -0700899 if (metadataIt != metadataList.end() || surfaceMapIt != surfaceMaps.end()) {
900 ALOGE("%s: metadataList and surfaceMaps are not the same size!", __FUNCTION__);
901 return BAD_VALUE;
902 }
Chien-Yu Chen85a64552015-08-28 15:46:12 -0700903
904 // Setup batch size if this is a high speed video recording request.
905 if (mIsConstrainedHighSpeedConfiguration && requestList->size() > 0) {
906 auto firstRequest = requestList->begin();
907 for (auto& outputStream : (*firstRequest)->mOutputStreams) {
908 if (outputStream->isVideoStream()) {
909 (*firstRequest)->mBatchSize = requestList->size();
910 break;
911 }
912 }
913 }
914
Jianing Wei90e59c92014-03-12 18:29:36 -0700915 return OK;
916}
917
Yin-Chia Yeh7e5a2042019-02-06 16:01:06 -0800918status_t Camera3Device::capture(CameraMetadata &request, int64_t* lastFrameNumber) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800919 ATRACE_CALL();
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800920
Emilian Peevaebbe412018-01-15 13:53:24 +0000921 List<const PhysicalCameraSettingsList> requestsList;
Shuzhen Wang0129d522016-10-30 22:43:41 -0700922 std::list<const SurfaceMap> surfaceMaps;
Emilian Peevaebbe412018-01-15 13:53:24 +0000923 convertToRequestList(requestsList, surfaceMaps, request);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700924
Yin-Chia Yeh7e5a2042019-02-06 16:01:06 -0800925 return captureList(requestsList, surfaceMaps, lastFrameNumber);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700926}
927
Emilian Peevaebbe412018-01-15 13:53:24 +0000928void Camera3Device::convertToRequestList(List<const PhysicalCameraSettingsList>& requestsList,
Shuzhen Wang0129d522016-10-30 22:43:41 -0700929 std::list<const SurfaceMap>& surfaceMaps,
930 const CameraMetadata& request) {
Emilian Peevaebbe412018-01-15 13:53:24 +0000931 PhysicalCameraSettingsList requestList;
932 requestList.push_back({std::string(getId().string()), request});
933 requestsList.push_back(requestList);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700934
935 SurfaceMap surfaceMap;
936 camera_metadata_ro_entry streams = request.find(ANDROID_REQUEST_OUTPUT_STREAMS);
937 // With no surface list passed in, stream and surface will have 1-to-1
938 // mapping. So the surface index is 0 for each stream in the surfaceMap.
939 for (size_t i = 0; i < streams.count; i++) {
940 surfaceMap[streams.data.i32[i]].push_back(0);
941 }
942 surfaceMaps.push_back(surfaceMap);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800943}
944
Jianing Wei90e59c92014-03-12 18:29:36 -0700945status_t Camera3Device::submitRequestsHelper(
Emilian Peevaebbe412018-01-15 13:53:24 +0000946 const List<const PhysicalCameraSettingsList> &requests,
Shuzhen Wang0129d522016-10-30 22:43:41 -0700947 const std::list<const SurfaceMap> &surfaceMaps,
948 bool repeating,
Jianing Wei2d6bb3f2014-04-11 10:00:31 -0700949 /*out*/
950 int64_t *lastFrameNumber) {
Jianing Wei90e59c92014-03-12 18:29:36 -0700951 ATRACE_CALL();
952 Mutex::Autolock il(mInterfaceLock);
953 Mutex::Autolock l(mLock);
954
955 status_t res = checkStatusOkToCaptureLocked();
956 if (res != OK) {
957 // error logged by previous call
958 return res;
959 }
960
961 RequestList requestList;
962
Shuzhen Wang0129d522016-10-30 22:43:41 -0700963 res = convertMetadataListToRequestListLocked(requests, surfaceMaps,
964 repeating, /*out*/&requestList);
Jianing Wei90e59c92014-03-12 18:29:36 -0700965 if (res != OK) {
966 // error logged by previous call
967 return res;
968 }
969
970 if (repeating) {
Jianing Wei2d6bb3f2014-04-11 10:00:31 -0700971 res = mRequestThread->setRepeatingRequests(requestList, lastFrameNumber);
Jianing Wei90e59c92014-03-12 18:29:36 -0700972 } else {
Jianing Wei2d6bb3f2014-04-11 10:00:31 -0700973 res = mRequestThread->queueRequestList(requestList, lastFrameNumber);
Jianing Wei90e59c92014-03-12 18:29:36 -0700974 }
975
976 if (res == OK) {
977 waitUntilStateThenRelock(/*active*/true, kActiveTimeout);
978 if (res != OK) {
979 SET_ERR_L("Can't transition to active in %f seconds!",
980 kActiveTimeout/1e9);
981 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800982 ALOGV("Camera %s: Capture request %" PRId32 " enqueued", mId.string(),
Jianing Wei2d6bb3f2014-04-11 10:00:31 -0700983 (*(requestList.begin()))->mResultExtras.requestId);
Jianing Wei90e59c92014-03-12 18:29:36 -0700984 } else {
985 CLOGE("Cannot queue request. Impossible.");
986 return BAD_VALUE;
987 }
988
989 return res;
990}
991
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -0700992hardware::Return<void> Camera3Device::requestStreamBuffers(
993 const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& bufReqs,
994 requestStreamBuffers_cb _hidl_cb) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800995 RequestBufferStates states {
996 mId, mRequestBufferInterfaceLock, mUseHalBufManager, mOutputStreams,
997 *this, *mInterface, *this};
998 camera3::requestStreamBuffers(states, bufReqs, _hidl_cb);
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -0700999 return hardware::Void();
1000}
1001
1002hardware::Return<void> Camera3Device::returnStreamBuffers(
1003 const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer>& buffers) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001004 ReturnBufferStates states {
1005 mId, mUseHalBufManager, mOutputStreams, *mInterface};
1006 camera3::returnStreamBuffers(states, buffers);
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07001007 return hardware::Void();
1008}
1009
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001010hardware::Return<void> Camera3Device::processCaptureResult_3_4(
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001011 const hardware::hidl_vec<
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001012 hardware::camera::device::V3_4::CaptureResult>& results) {
Yin-Chia Yeh657c1872017-07-18 18:09:57 -07001013 // Ideally we should grab mLock, but that can lead to deadlock, and
1014 // it's not super important to get up to date value of mStatus for this
1015 // warning print, hence skipping the lock here
1016 if (mStatus == STATUS_ERROR) {
1017 // Per API contract, HAL should act as closed after device error
1018 // But mStatus can be set to error by framework as well, so just log
1019 // a warning here.
1020 ALOGW("%s: received capture result in error state.", __FUNCTION__);
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07001021 }
Yifan Honga640c5a2017-04-12 16:30:31 -07001022
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001023 sp<NotificationListener> listener;
1024 {
1025 std::lock_guard<std::mutex> l(mOutputLock);
1026 listener = mListener.promote();
1027 }
1028
Yifan Honga640c5a2017-04-12 16:30:31 -07001029 if (mProcessCaptureResultLock.tryLock() != OK) {
1030 // This should never happen; it indicates a wrong client implementation
1031 // that doesn't follow the contract. But, we can be tolerant here.
1032 ALOGE("%s: callback overlapped! waiting 1s...",
1033 __FUNCTION__);
1034 if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
1035 ALOGE("%s: cannot acquire lock in 1s, dropping results",
1036 __FUNCTION__);
1037 // really don't know what to do, so bail out.
1038 return hardware::Void();
1039 }
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001040 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001041 CaptureOutputStates states {
1042 mId,
1043 mInFlightLock, mInFlightMap,
1044 mOutputLock, mResultQueue, mResultSignal,
1045 mNextShutterFrameNumber,
1046 mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
1047 mNextResultFrameNumber,
1048 mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
1049 mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
1050 mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08001051 mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
1052 mTagMonitor, mInputStream, mOutputStreams, listener, *this, *this, *mInterface
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001053 };
1054
Yifan Honga640c5a2017-04-12 16:30:31 -07001055 for (const auto& result : results) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001056 processOneCaptureResultLocked(states, result.v3_2, result.physicalCameraMetadata);
Yifan Honga640c5a2017-04-12 16:30:31 -07001057 }
1058 mProcessCaptureResultLock.unlock();
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001059 return hardware::Void();
1060}
1061
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001062// Only one processCaptureResult should be called at a time, so
1063// the locks won't block. The locks are present here simply to enforce this.
1064hardware::Return<void> Camera3Device::processCaptureResult(
1065 const hardware::hidl_vec<
1066 hardware::camera::device::V3_2::CaptureResult>& results) {
1067 hardware::hidl_vec<hardware::camera::device::V3_4::PhysicalCameraMetadata> noPhysMetadata;
1068
1069 // Ideally we should grab mLock, but that can lead to deadlock, and
1070 // it's not super important to get up to date value of mStatus for this
1071 // warning print, hence skipping the lock here
1072 if (mStatus == STATUS_ERROR) {
1073 // Per API contract, HAL should act as closed after device error
1074 // But mStatus can be set to error by framework as well, so just log
1075 // a warning here.
1076 ALOGW("%s: received capture result in error state.", __FUNCTION__);
1077 }
1078
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001079 sp<NotificationListener> listener;
1080 {
1081 std::lock_guard<std::mutex> l(mOutputLock);
1082 listener = mListener.promote();
1083 }
1084
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001085 if (mProcessCaptureResultLock.tryLock() != OK) {
1086 // This should never happen; it indicates a wrong client implementation
1087 // that doesn't follow the contract. But, we can be tolerant here.
1088 ALOGE("%s: callback overlapped! waiting 1s...",
1089 __FUNCTION__);
1090 if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
1091 ALOGE("%s: cannot acquire lock in 1s, dropping results",
1092 __FUNCTION__);
1093 // really don't know what to do, so bail out.
1094 return hardware::Void();
1095 }
1096 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001097
1098 CaptureOutputStates states {
1099 mId,
1100 mInFlightLock, mInFlightMap,
1101 mOutputLock, mResultQueue, mResultSignal,
1102 mNextShutterFrameNumber,
1103 mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
1104 mNextResultFrameNumber,
1105 mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
1106 mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
1107 mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08001108 mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
1109 mTagMonitor, mInputStream, mOutputStreams, listener, *this, *this, *mInterface
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001110 };
1111
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001112 for (const auto& result : results) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001113 processOneCaptureResultLocked(states, result, noPhysMetadata);
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001114 }
1115 mProcessCaptureResultLock.unlock();
1116 return hardware::Void();
1117}
1118
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001119hardware::Return<void> Camera3Device::notify(
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001120 const hardware::hidl_vec<hardware::camera::device::V3_2::NotifyMsg>& msgs) {
Yin-Chia Yeh657c1872017-07-18 18:09:57 -07001121 // Ideally we should grab mLock, but that can lead to deadlock, and
1122 // it's not super important to get up to date value of mStatus for this
1123 // warning print, hence skipping the lock here
1124 if (mStatus == STATUS_ERROR) {
1125 // Per API contract, HAL should act as closed after device error
1126 // But mStatus can be set to error by framework as well, so just log
1127 // a warning here.
1128 ALOGW("%s: received notify message in error state.", __FUNCTION__);
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07001129 }
Yin-Chia Yeh657c1872017-07-18 18:09:57 -07001130
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001131 sp<NotificationListener> listener;
1132 {
1133 std::lock_guard<std::mutex> l(mOutputLock);
1134 listener = mListener.promote();
1135 }
1136
1137 CaptureOutputStates states {
1138 mId,
1139 mInFlightLock, mInFlightMap,
1140 mOutputLock, mResultQueue, mResultSignal,
1141 mNextShutterFrameNumber,
1142 mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
1143 mNextResultFrameNumber,
1144 mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
1145 mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
1146 mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08001147 mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
1148 mTagMonitor, mInputStream, mOutputStreams, listener, *this, *this, *mInterface
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001149 };
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001150 for (const auto& msg : msgs) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001151 camera3::notify(states, msg);
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001152 }
1153 return hardware::Void();
1154}
1155
Emilian Peevaebbe412018-01-15 13:53:24 +00001156status_t Camera3Device::captureList(const List<const PhysicalCameraSettingsList> &requestsList,
Shuzhen Wang0129d522016-10-30 22:43:41 -07001157 const std::list<const SurfaceMap> &surfaceMaps,
Jianing Weicb0652e2014-03-12 18:29:36 -07001158 int64_t *lastFrameNumber) {
Jianing Wei90e59c92014-03-12 18:29:36 -07001159 ATRACE_CALL();
1160
Emilian Peevaebbe412018-01-15 13:53:24 +00001161 return submitRequestsHelper(requestsList, surfaceMaps, /*repeating*/false, lastFrameNumber);
Jianing Wei90e59c92014-03-12 18:29:36 -07001162}
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001163
Jianing Weicb0652e2014-03-12 18:29:36 -07001164status_t Camera3Device::setStreamingRequest(const CameraMetadata &request,
1165 int64_t* /*lastFrameNumber*/) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001166 ATRACE_CALL();
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001167
Emilian Peevaebbe412018-01-15 13:53:24 +00001168 List<const PhysicalCameraSettingsList> requestsList;
Shuzhen Wang0129d522016-10-30 22:43:41 -07001169 std::list<const SurfaceMap> surfaceMaps;
Emilian Peevaebbe412018-01-15 13:53:24 +00001170 convertToRequestList(requestsList, surfaceMaps, request);
Shuzhen Wang0129d522016-10-30 22:43:41 -07001171
Emilian Peevaebbe412018-01-15 13:53:24 +00001172 return setStreamingRequestList(requestsList, /*surfaceMap*/surfaceMaps,
Shuzhen Wang0129d522016-10-30 22:43:41 -07001173 /*lastFrameNumber*/NULL);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001174}
1175
Emilian Peevaebbe412018-01-15 13:53:24 +00001176status_t Camera3Device::setStreamingRequestList(
1177 const List<const PhysicalCameraSettingsList> &requestsList,
1178 const std::list<const SurfaceMap> &surfaceMaps, int64_t *lastFrameNumber) {
Jianing Wei90e59c92014-03-12 18:29:36 -07001179 ATRACE_CALL();
1180
Emilian Peevaebbe412018-01-15 13:53:24 +00001181 return submitRequestsHelper(requestsList, surfaceMaps, /*repeating*/true, lastFrameNumber);
Jianing Wei90e59c92014-03-12 18:29:36 -07001182}
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001183
1184sp<Camera3Device::CaptureRequest> Camera3Device::setUpRequestLocked(
Emilian Peevaebbe412018-01-15 13:53:24 +00001185 const PhysicalCameraSettingsList &request, const SurfaceMap &surfaceMap) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001186 status_t res;
1187
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001188 if (mStatus == STATUS_UNCONFIGURED || mNeedConfig) {
Eino-Ville Talvalae7091aa2017-03-07 15:23:06 -08001189 // This point should only be reached via API1 (API2 must explicitly call configureStreams)
1190 // so unilaterally select normal operating mode.
Emilian Peevaebbe412018-01-15 13:53:24 +00001191 res = filterParamsAndConfigureLocked(request.begin()->metadata,
1192 CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE);
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07001193 // Stream configuration failed. Client might try other configuraitons.
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001194 if (res != OK) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07001195 CLOGE("Can't set up streams: %s (%d)", strerror(-res), res);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001196 return NULL;
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07001197 } else if (mStatus == STATUS_UNCONFIGURED) {
1198 // Stream configuration successfully configure to empty stream configuration.
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001199 CLOGE("No streams configured");
1200 return NULL;
1201 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001202 }
1203
Shuzhen Wang0129d522016-10-30 22:43:41 -07001204 sp<CaptureRequest> newRequest = createCaptureRequest(request, surfaceMap);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001205 return newRequest;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001206}
1207
Jianing Weicb0652e2014-03-12 18:29:36 -07001208status_t Camera3Device::clearStreamingRequest(int64_t *lastFrameNumber) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001209 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001210 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001211 Mutex::Autolock l(mLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001212
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001213 switch (mStatus) {
1214 case STATUS_ERROR:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001215 CLOGE("Device has encountered a serious error");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001216 return INVALID_OPERATION;
1217 case STATUS_UNINITIALIZED:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001218 CLOGE("Device not initialized");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001219 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001220 case STATUS_UNCONFIGURED:
1221 case STATUS_CONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001222 case STATUS_ACTIVE:
1223 // OK
1224 break;
1225 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001226 SET_ERR_L("Unexpected status: %d", mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001227 return INVALID_OPERATION;
1228 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001229 ALOGV("Camera %s: Clearing repeating request", mId.string());
Jianing Weicb0652e2014-03-12 18:29:36 -07001230
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07001231 return mRequestThread->clearRepeatingRequests(lastFrameNumber);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001232}
1233
1234status_t Camera3Device::waitUntilRequestReceived(int32_t requestId, nsecs_t timeout) {
1235 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001236 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001237
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001238 return mRequestThread->waitUntilRequestProcessed(requestId, timeout);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001239}
1240
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001241status_t Camera3Device::createInputStream(
1242 uint32_t width, uint32_t height, int format, int *id) {
1243 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001244 Mutex::Autolock il(mInterfaceLock);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001245 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001246 Mutex::Autolock l(mLock);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001247 ALOGV("Camera %s: Creating new input stream %d: %d x %d, format %d",
1248 mId.string(), mNextStreamId, width, height, format);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001249
1250 status_t res;
1251 bool wasActive = false;
1252
1253 switch (mStatus) {
1254 case STATUS_ERROR:
1255 ALOGE("%s: Device has encountered a serious error", __FUNCTION__);
1256 return INVALID_OPERATION;
1257 case STATUS_UNINITIALIZED:
1258 ALOGE("%s: Device not initialized", __FUNCTION__);
1259 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001260 case STATUS_UNCONFIGURED:
1261 case STATUS_CONFIGURED:
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001262 // OK
1263 break;
1264 case STATUS_ACTIVE:
1265 ALOGV("%s: Stopping activity to reconfigure streams", __FUNCTION__);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001266 res = internalPauseAndWaitLocked(maxExpectedDuration);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001267 if (res != OK) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001268 SET_ERR_L("Can't pause captures to reconfigure streams!");
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001269 return res;
1270 }
1271 wasActive = true;
1272 break;
1273 default:
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001274 SET_ERR_L("%s: Unexpected status: %d", mStatus);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001275 return INVALID_OPERATION;
1276 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001277 assert(mStatus != STATUS_ACTIVE);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001278
1279 if (mInputStream != 0) {
1280 ALOGE("%s: Cannot create more than 1 input stream", __FUNCTION__);
1281 return INVALID_OPERATION;
1282 }
1283
1284 sp<Camera3InputStream> newStream = new Camera3InputStream(mNextStreamId,
1285 width, height, format);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001286 newStream->setStatusTracker(mStatusTracker);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001287
1288 mInputStream = newStream;
1289
1290 *id = mNextStreamId++;
1291
1292 // Continue captures if active at start
1293 if (wasActive) {
1294 ALOGV("%s: Restarting activity to reconfigure streams", __FUNCTION__);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001295 // Reuse current operating mode and session parameters for new stream config
1296 res = configureStreamsLocked(mOperatingMode, mSessionParams);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001297 if (res != OK) {
1298 ALOGE("%s: Can't reconfigure device for new stream %d: %s (%d)",
1299 __FUNCTION__, mNextStreamId, strerror(-res), res);
1300 return res;
1301 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001302 internalResumeLocked();
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001303 }
1304
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001305 ALOGV("Camera %s: Created input stream", mId.string());
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001306 return OK;
1307}
1308
Eino-Ville Talvala727d1722015-06-09 13:44:19 -07001309status_t Camera3Device::createStream(sp<Surface> consumer,
Shuzhen Wang0129d522016-10-30 22:43:41 -07001310 uint32_t width, uint32_t height, int format,
1311 android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001312 const String8& physicalCameraId,
Emilian Peev40ead602017-09-26 15:46:36 +01001313 std::vector<int> *surfaceIds, int streamSetId, bool isShared, uint64_t consumerUsage) {
Shuzhen Wang0129d522016-10-30 22:43:41 -07001314 ATRACE_CALL();
1315
1316 if (consumer == nullptr) {
1317 ALOGE("%s: consumer must not be null", __FUNCTION__);
1318 return BAD_VALUE;
1319 }
1320
1321 std::vector<sp<Surface>> consumers;
1322 consumers.push_back(consumer);
1323
1324 return createStream(consumers, /*hasDeferredConsumer*/ false, width, height,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001325 format, dataSpace, rotation, id, physicalCameraId, surfaceIds, streamSetId,
1326 isShared, consumerUsage);
Shuzhen Wang0129d522016-10-30 22:43:41 -07001327}
1328
1329status_t Camera3Device::createStream(const std::vector<sp<Surface>>& consumers,
1330 bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
1331 android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001332 const String8& physicalCameraId,
Emilian Peev40ead602017-09-26 15:46:36 +01001333 std::vector<int> *surfaceIds, int streamSetId, bool isShared, uint64_t consumerUsage) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001334 ATRACE_CALL();
Emilian Peev40ead602017-09-26 15:46:36 +01001335
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001336 Mutex::Autolock il(mInterfaceLock);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001337 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001338 Mutex::Autolock l(mLock);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001339 ALOGV("Camera %s: Creating new stream %d: %d x %d, format %d, dataspace %d rotation %d"
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001340 " consumer usage %" PRIu64 ", isShared %d, physicalCameraId %s", mId.string(),
1341 mNextStreamId, width, height, format, dataSpace, rotation, consumerUsage, isShared,
1342 physicalCameraId.string());
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001343
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001344 status_t res;
1345 bool wasActive = false;
1346
1347 switch (mStatus) {
1348 case STATUS_ERROR:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001349 CLOGE("Device has encountered a serious error");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001350 return INVALID_OPERATION;
1351 case STATUS_UNINITIALIZED:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001352 CLOGE("Device not initialized");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001353 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001354 case STATUS_UNCONFIGURED:
1355 case STATUS_CONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001356 // OK
1357 break;
1358 case STATUS_ACTIVE:
1359 ALOGV("%s: Stopping activity to reconfigure streams", __FUNCTION__);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001360 res = internalPauseAndWaitLocked(maxExpectedDuration);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001361 if (res != OK) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001362 SET_ERR_L("Can't pause captures to reconfigure streams!");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001363 return res;
1364 }
1365 wasActive = true;
1366 break;
1367 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001368 SET_ERR_L("Unexpected status: %d", mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001369 return INVALID_OPERATION;
1370 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001371 assert(mStatus != STATUS_ACTIVE);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001372
1373 sp<Camera3OutputStream> newStream;
Zhijun He5d677d12016-05-29 16:52:39 -07001374
Shuzhen Wang0129d522016-10-30 22:43:41 -07001375 if (consumers.size() == 0 && !hasDeferredConsumer) {
1376 ALOGE("%s: Number of consumers cannot be smaller than 1", __FUNCTION__);
1377 return BAD_VALUE;
1378 }
Zhijun He5d677d12016-05-29 16:52:39 -07001379
Shuzhen Wang0129d522016-10-30 22:43:41 -07001380 if (hasDeferredConsumer && format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
Zhijun He5d677d12016-05-29 16:52:39 -07001381 ALOGE("Deferred consumer stream creation only support IMPLEMENTATION_DEFINED format");
1382 return BAD_VALUE;
1383 }
1384
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001385 if (format == HAL_PIXEL_FORMAT_BLOB) {
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -07001386 ssize_t blobBufferSize;
Shuzhen Wang68ac7ad2019-01-30 14:03:28 -08001387 if (dataSpace == HAL_DATASPACE_DEPTH) {
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -07001388 blobBufferSize = getPointCloudBufferSize();
1389 if (blobBufferSize <= 0) {
1390 SET_ERR_L("Invalid point cloud buffer size %zd", blobBufferSize);
1391 return BAD_VALUE;
1392 }
Shuzhen Wang68ac7ad2019-01-30 14:03:28 -08001393 } else if (dataSpace == static_cast<android_dataspace>(HAL_DATASPACE_JPEG_APP_SEGMENTS)) {
1394 blobBufferSize = width * height;
1395 } else {
1396 blobBufferSize = getJpegBufferSize(width, height);
1397 if (blobBufferSize <= 0) {
1398 SET_ERR_L("Invalid jpeg buffer size %zd", blobBufferSize);
1399 return BAD_VALUE;
1400 }
Zhijun Hef7da0962014-04-24 13:27:56 -07001401 }
Shuzhen Wang0129d522016-10-30 22:43:41 -07001402 newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
Shuzhen Wangc28dccc2016-02-11 23:48:46 -08001403 width, height, blobBufferSize, format, dataSpace, rotation,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001404 mTimestampOffset, physicalCameraId, streamSetId);
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -08001405 } else if (format == HAL_PIXEL_FORMAT_RAW_OPAQUE) {
1406 ssize_t rawOpaqueBufferSize = getRawOpaqueBufferSize(width, height);
1407 if (rawOpaqueBufferSize <= 0) {
1408 SET_ERR_L("Invalid RAW opaque buffer size %zd", rawOpaqueBufferSize);
1409 return BAD_VALUE;
1410 }
Shuzhen Wang0129d522016-10-30 22:43:41 -07001411 newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
Shuzhen Wangc28dccc2016-02-11 23:48:46 -08001412 width, height, rawOpaqueBufferSize, format, dataSpace, rotation,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001413 mTimestampOffset, physicalCameraId, streamSetId);
Shuzhen Wang758c2152017-01-10 18:26:18 -08001414 } else if (isShared) {
1415 newStream = new Camera3SharedOutputStream(mNextStreamId, consumers,
1416 width, height, format, consumerUsage, dataSpace, rotation,
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07001417 mTimestampOffset, physicalCameraId, streamSetId,
1418 mUseHalBufManager);
Shuzhen Wang0129d522016-10-30 22:43:41 -07001419 } else if (consumers.size() == 0 && hasDeferredConsumer) {
Zhijun He5d677d12016-05-29 16:52:39 -07001420 newStream = new Camera3OutputStream(mNextStreamId,
1421 width, height, format, consumerUsage, dataSpace, rotation,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001422 mTimestampOffset, physicalCameraId, streamSetId);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001423 } else {
Shuzhen Wang0129d522016-10-30 22:43:41 -07001424 newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
Shuzhen Wangc28dccc2016-02-11 23:48:46 -08001425 width, height, format, dataSpace, rotation,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001426 mTimestampOffset, physicalCameraId, streamSetId);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001427 }
Emilian Peev40ead602017-09-26 15:46:36 +01001428
1429 size_t consumerCount = consumers.size();
1430 for (size_t i = 0; i < consumerCount; i++) {
1431 int id = newStream->getSurfaceId(consumers[i]);
1432 if (id < 0) {
1433 SET_ERR_L("Invalid surface id");
1434 return BAD_VALUE;
1435 }
1436 if (surfaceIds != nullptr) {
1437 surfaceIds->push_back(id);
1438 }
1439 }
1440
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001441 newStream->setStatusTracker(mStatusTracker);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001442
Emilian Peev08dd2452017-04-06 16:55:14 +01001443 newStream->setBufferManager(mBufferManager);
Zhijun He125684a2015-12-26 15:07:30 -08001444
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001445 res = mOutputStreams.add(mNextStreamId, newStream);
1446 if (res < 0) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001447 SET_ERR_L("Can't add new stream to set: %s (%d)", strerror(-res), res);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001448 return res;
1449 }
1450
1451 *id = mNextStreamId++;
Eino-Ville Talvalaea26c772013-06-11 16:04:06 -07001452 mNeedConfig = true;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001453
1454 // Continue captures if active at start
1455 if (wasActive) {
1456 ALOGV("%s: Restarting activity to reconfigure streams", __FUNCTION__);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001457 // Reuse current operating mode and session parameters for new stream config
1458 res = configureStreamsLocked(mOperatingMode, mSessionParams);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001459 if (res != OK) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001460 CLOGE("Can't reconfigure device for new stream %d: %s (%d)",
1461 mNextStreamId, strerror(-res), res);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001462 return res;
1463 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001464 internalResumeLocked();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001465 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001466 ALOGV("Camera %s: Created new stream", mId.string());
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001467 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001468}
1469
Emilian Peev710c1422017-08-30 11:19:38 +01001470status_t Camera3Device::getStreamInfo(int id, StreamInfo *streamInfo) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001471 ATRACE_CALL();
Emilian Peev710c1422017-08-30 11:19:38 +01001472 if (nullptr == streamInfo) {
1473 return BAD_VALUE;
1474 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001475 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001476 Mutex::Autolock l(mLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001477
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001478 switch (mStatus) {
1479 case STATUS_ERROR:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001480 CLOGE("Device has encountered a serious error");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001481 return INVALID_OPERATION;
1482 case STATUS_UNINITIALIZED:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001483 CLOGE("Device not initialized!");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001484 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001485 case STATUS_UNCONFIGURED:
1486 case STATUS_CONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001487 case STATUS_ACTIVE:
1488 // OK
1489 break;
1490 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001491 SET_ERR_L("Unexpected status: %d", mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001492 return INVALID_OPERATION;
1493 }
1494
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001495 sp<Camera3StreamInterface> stream = mOutputStreams.get(id);
1496 if (stream == nullptr) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001497 CLOGE("Stream %d is unknown", id);
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001498 return BAD_VALUE;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001499 }
1500
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001501 streamInfo->width = stream->getWidth();
1502 streamInfo->height = stream->getHeight();
1503 streamInfo->format = stream->getFormat();
1504 streamInfo->dataSpace = stream->getDataSpace();
1505 streamInfo->formatOverridden = stream->isFormatOverridden();
1506 streamInfo->originalFormat = stream->getOriginalFormat();
1507 streamInfo->dataSpaceOverridden = stream->isDataSpaceOverridden();
1508 streamInfo->originalDataSpace = stream->getOriginalDataSpace();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001509 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001510}
1511
1512status_t Camera3Device::setStreamTransform(int id,
1513 int transform) {
1514 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001515 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001516 Mutex::Autolock l(mLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001517
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001518 switch (mStatus) {
1519 case STATUS_ERROR:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001520 CLOGE("Device has encountered a serious error");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001521 return INVALID_OPERATION;
1522 case STATUS_UNINITIALIZED:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001523 CLOGE("Device not initialized");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001524 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001525 case STATUS_UNCONFIGURED:
1526 case STATUS_CONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001527 case STATUS_ACTIVE:
1528 // OK
1529 break;
1530 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001531 SET_ERR_L("Unexpected status: %d", mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001532 return INVALID_OPERATION;
1533 }
1534
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001535 sp<Camera3OutputStreamInterface> stream = mOutputStreams.get(id);
1536 if (stream == nullptr) {
1537 CLOGE("Stream %d does not exist", id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001538 return BAD_VALUE;
1539 }
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001540 return stream->setTransform(transform);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001541}
1542
1543status_t Camera3Device::deleteStream(int id) {
1544 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001545 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001546 Mutex::Autolock l(mLock);
1547 status_t res;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001548
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001549 ALOGV("%s: Camera %s: Deleting stream %d", __FUNCTION__, mId.string(), id);
Igor Murashkine2172be2013-05-28 15:31:39 -07001550
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001551 // CameraDevice semantics require device to already be idle before
1552 // deleteStream is called, unlike for createStream.
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001553 if (mStatus == STATUS_ACTIVE) {
Yin-Chia Yeh693047d2018-03-08 12:14:19 -08001554 ALOGW("%s: Camera %s: Device not idle", __FUNCTION__, mId.string());
Igor Murashkin52827132013-05-13 14:53:44 -07001555 return -EBUSY;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001556 }
1557
Yin-Chia Yeh5090c732017-07-20 16:05:29 -07001558 if (mStatus == STATUS_ERROR) {
1559 ALOGW("%s: Camera %s: deleteStream not allowed in ERROR state",
1560 __FUNCTION__, mId.string());
1561 return -EBUSY;
1562 }
1563
Igor Murashkin2fba5842013-04-22 14:03:54 -07001564 sp<Camera3StreamInterface> deletedStream;
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001565 sp<Camera3StreamInterface> stream = mOutputStreams.get(id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001566 if (mInputStream != NULL && id == mInputStream->getId()) {
1567 deletedStream = mInputStream;
1568 mInputStream.clear();
1569 } else {
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001570 if (stream == nullptr) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001571 CLOGE("Stream %d does not exist", id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001572 return BAD_VALUE;
1573 }
Zhijun He5f446352014-01-22 09:49:33 -08001574 }
1575
1576 // Delete output stream or the output part of a bi-directional stream.
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001577 if (stream != nullptr) {
1578 deletedStream = stream;
1579 mOutputStreams.remove(id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001580 }
1581
1582 // Free up the stream endpoint so that it can be used by some other stream
1583 res = deletedStream->disconnect();
1584 if (res != OK) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001585 SET_ERR_L("Can't disconnect deleted stream %d", id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001586 // fall through since we want to still list the stream as deleted.
1587 }
1588 mDeletedStreams.add(deletedStream);
Eino-Ville Talvalaea26c772013-06-11 16:04:06 -07001589 mNeedConfig = true;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001590
1591 return res;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001592}
1593
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001594status_t Camera3Device::configureStreams(const CameraMetadata& sessionParams, int operatingMode) {
Igor Murashkine2d167e2014-08-19 16:19:59 -07001595 ATRACE_CALL();
1596 ALOGV("%s: E", __FUNCTION__);
1597
1598 Mutex::Autolock il(mInterfaceLock);
1599 Mutex::Autolock l(mLock);
Chien-Yu Chen17338fc2015-06-18 16:30:12 -07001600
Emilian Peev811d2952018-05-25 11:08:40 +01001601 // In case the client doesn't include any session parameter, try a
1602 // speculative configuration using the values from the last cached
1603 // default request.
1604 if (sessionParams.isEmpty() &&
1605 ((mLastTemplateId > 0) && (mLastTemplateId < CAMERA3_TEMPLATE_COUNT)) &&
1606 (!mRequestTemplateCache[mLastTemplateId].isEmpty())) {
1607 ALOGV("%s: Speculative session param configuration with template id: %d", __func__,
1608 mLastTemplateId);
1609 return filterParamsAndConfigureLocked(mRequestTemplateCache[mLastTemplateId],
1610 operatingMode);
1611 }
1612
Emilian Peevac3ce6c2017-12-12 15:27:02 +00001613 return filterParamsAndConfigureLocked(sessionParams, operatingMode);
1614}
1615
1616status_t Camera3Device::filterParamsAndConfigureLocked(const CameraMetadata& sessionParams,
1617 int operatingMode) {
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001618 //Filter out any incoming session parameters
1619 const CameraMetadata params(sessionParams);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001620 camera_metadata_entry_t availableSessionKeys = mDeviceInfo.find(
1621 ANDROID_REQUEST_AVAILABLE_SESSION_KEYS);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00001622 CameraMetadata filteredParams(availableSessionKeys.count);
1623 camera_metadata_t *meta = const_cast<camera_metadata_t *>(
1624 filteredParams.getAndLock());
1625 set_camera_metadata_vendor_id(meta, mVendorTagId);
1626 filteredParams.unlock(meta);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001627 if (availableSessionKeys.count > 0) {
1628 for (size_t i = 0; i < availableSessionKeys.count; i++) {
1629 camera_metadata_ro_entry entry = params.find(
1630 availableSessionKeys.data.i32[i]);
1631 if (entry.count > 0) {
1632 filteredParams.update(entry);
1633 }
1634 }
1635 }
1636
1637 return configureStreamsLocked(operatingMode, filteredParams);
Igor Murashkine2d167e2014-08-19 16:19:59 -07001638}
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001639
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -07001640status_t Camera3Device::getInputBufferProducer(
1641 sp<IGraphicBufferProducer> *producer) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07001642 ATRACE_CALL();
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -07001643 Mutex::Autolock il(mInterfaceLock);
1644 Mutex::Autolock l(mLock);
1645
1646 if (producer == NULL) {
1647 return BAD_VALUE;
1648 } else if (mInputStream == NULL) {
1649 return INVALID_OPERATION;
1650 }
1651
1652 return mInputStream->getInputBufferProducer(producer);
1653}
1654
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001655status_t Camera3Device::createDefaultRequest(int templateId,
1656 CameraMetadata *request) {
1657 ATRACE_CALL();
Alex Rayfe7e0c62013-05-30 00:12:13 -07001658 ALOGV("%s: for template %d", __FUNCTION__, templateId);
Chien-Yu Chen9cd14022016-03-09 12:21:01 -08001659
1660 if (templateId <= 0 || templateId >= CAMERA3_TEMPLATE_COUNT) {
1661 android_errorWriteWithInfoLog(CameraService::SN_EVENT_LOG_ID, "26866110",
Jayant Chowdhary12361932018-08-27 14:46:13 -07001662 CameraThreadState::getCallingUid(), nullptr, 0);
Chien-Yu Chen9cd14022016-03-09 12:21:01 -08001663 return BAD_VALUE;
1664 }
1665
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001666 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001667
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001668 {
1669 Mutex::Autolock l(mLock);
1670 switch (mStatus) {
1671 case STATUS_ERROR:
1672 CLOGE("Device has encountered a serious error");
1673 return INVALID_OPERATION;
1674 case STATUS_UNINITIALIZED:
1675 CLOGE("Device is not initialized!");
1676 return INVALID_OPERATION;
1677 case STATUS_UNCONFIGURED:
1678 case STATUS_CONFIGURED:
1679 case STATUS_ACTIVE:
1680 // OK
1681 break;
1682 default:
1683 SET_ERR_L("Unexpected status: %d", mStatus);
1684 return INVALID_OPERATION;
1685 }
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001686
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001687 if (!mRequestTemplateCache[templateId].isEmpty()) {
1688 *request = mRequestTemplateCache[templateId];
Emilian Peev811d2952018-05-25 11:08:40 +01001689 mLastTemplateId = templateId;
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001690 return OK;
1691 }
Zhijun Hea1530f12014-09-14 12:44:20 -07001692 }
1693
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001694 camera_metadata_t *rawRequest;
1695 status_t res = mInterface->constructDefaultRequestSettings(
1696 (camera3_request_template_t) templateId, &rawRequest);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001697
1698 {
1699 Mutex::Autolock l(mLock);
1700 if (res == BAD_VALUE) {
1701 ALOGI("%s: template %d is not supported on this camera device",
1702 __FUNCTION__, templateId);
1703 return res;
1704 } else if (res != OK) {
1705 CLOGE("Unable to construct request template %d: %s (%d)",
1706 templateId, strerror(-res), res);
1707 return res;
1708 }
1709
1710 set_camera_metadata_vendor_id(rawRequest, mVendorTagId);
1711 mRequestTemplateCache[templateId].acquire(rawRequest);
1712
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08001713 // Override the template request with zoomRatioMapper
1714 res = mZoomRatioMappers[mId.c_str()].initZoomRatioInTemplate(
1715 &mRequestTemplateCache[templateId]);
1716 if (res != OK) {
1717 CLOGE("Failed to update zoom ratio for template %d: %s (%d)",
1718 templateId, strerror(-res), res);
1719 return res;
1720 }
1721
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001722 *request = mRequestTemplateCache[templateId];
Emilian Peev811d2952018-05-25 11:08:40 +01001723 mLastTemplateId = templateId;
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001724 }
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001725 return OK;
1726}
1727
1728status_t Camera3Device::waitUntilDrained() {
1729 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001730 Mutex::Autolock il(mInterfaceLock);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001731 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001732 Mutex::Autolock l(mLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001733
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001734 return waitUntilDrainedLocked(maxExpectedDuration);
Zhijun He69a37482014-03-23 18:44:49 -07001735}
1736
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001737status_t Camera3Device::waitUntilDrainedLocked(nsecs_t maxExpectedDuration) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001738 switch (mStatus) {
1739 case STATUS_UNINITIALIZED:
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001740 case STATUS_UNCONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001741 ALOGV("%s: Already idle", __FUNCTION__);
1742 return OK;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001743 case STATUS_CONFIGURED:
1744 // To avoid race conditions, check with tracker to be sure
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001745 case STATUS_ERROR:
1746 case STATUS_ACTIVE:
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001747 // Need to verify shut down
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001748 break;
1749 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001750 SET_ERR_L("Unexpected status: %d",mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001751 return INVALID_OPERATION;
1752 }
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07001753 ALOGV("%s: Camera %s: Waiting until idle (%" PRIi64 "ns)", __FUNCTION__, mId.string(),
1754 maxExpectedDuration);
1755 status_t res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration);
Eino-Ville Talvala9c8a0912014-09-14 14:52:19 -07001756 if (res != OK) {
1757 SET_ERR_L("Error waiting for HAL to drain: %s (%d)", strerror(-res),
1758 res);
1759 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001760 return res;
1761}
1762
Ruben Brunk183f0562015-08-12 12:55:02 -07001763
1764void Camera3Device::internalUpdateStatusLocked(Status status) {
1765 mStatus = status;
1766 mRecentStatusUpdates.add(mStatus);
1767 mStatusChanged.broadcast();
1768}
1769
Eino-Ville Talvala002001b2018-01-23 16:53:50 -08001770void Camera3Device::pauseStateNotify(bool enable) {
Jayant Chowdhary37eca242019-11-18 08:55:56 -08001771 // We must not hold mInterfaceLock here since this function is called from
1772 // RequestThread::threadLoop and holding mInterfaceLock could lead to
1773 // deadlocks (http://b/143513518)
Eino-Ville Talvala002001b2018-01-23 16:53:50 -08001774 Mutex::Autolock l(mLock);
1775
1776 mPauseStateNotify = enable;
1777}
1778
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001779// Pause to reconfigure
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001780status_t Camera3Device::internalPauseAndWaitLocked(nsecs_t maxExpectedDuration) {
Emilian Peeve86358b2019-02-15 13:51:39 -08001781 if (mRequestThread.get() != nullptr) {
1782 mRequestThread->setPaused(true);
1783 } else {
1784 return NO_INIT;
1785 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001786
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07001787 ALOGV("%s: Camera %s: Internal wait until idle (% " PRIi64 " ns)", __FUNCTION__, mId.string(),
1788 maxExpectedDuration);
1789 status_t res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001790 if (res != OK) {
1791 SET_ERR_L("Can't idle device in %f seconds!",
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07001792 maxExpectedDuration/1e9);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001793 }
1794
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001795 return res;
1796}
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001797
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001798// Resume after internalPauseAndWaitLocked
1799status_t Camera3Device::internalResumeLocked() {
1800 status_t res;
1801
1802 mRequestThread->setPaused(false);
1803
Eino-Ville Talvala002001b2018-01-23 16:53:50 -08001804 ALOGV("%s: Camera %s: Internal wait until active (% " PRIi64 " ns)", __FUNCTION__, mId.string(),
1805 kActiveTimeout);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001806 res = waitUntilStateThenRelock(/*active*/ true, kActiveTimeout);
1807 if (res != OK) {
1808 SET_ERR_L("Can't transition to active in %f seconds!",
1809 kActiveTimeout/1e9);
1810 }
1811 mPauseStateNotify = false;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001812 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001813}
1814
Ruben Brunk183f0562015-08-12 12:55:02 -07001815status_t Camera3Device::waitUntilStateThenRelock(bool active, nsecs_t timeout) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001816 status_t res = OK;
Ruben Brunk183f0562015-08-12 12:55:02 -07001817
1818 size_t startIndex = 0;
1819 if (mStatusWaiters == 0) {
1820 // Clear the list of recent statuses if there are no existing threads waiting on updates to
1821 // this status list
1822 mRecentStatusUpdates.clear();
1823 } else {
1824 // If other threads are waiting on updates to this status list, set the position of the
1825 // first element that this list will check rather than clearing the list.
1826 startIndex = mRecentStatusUpdates.size();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001827 }
1828
Ruben Brunk183f0562015-08-12 12:55:02 -07001829 mStatusWaiters++;
1830
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07001831 if (!active && mUseHalBufManager) {
1832 auto streamIds = mOutputStreams.getStreamIds();
Yin-Chia Yehcd333fe2019-02-08 13:45:41 -08001833 if (mStatus == STATUS_ACTIVE) {
1834 mRequestThread->signalPipelineDrain(streamIds);
1835 }
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07001836 mRequestBufferSM.onWaitUntilIdle();
1837 }
1838
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001839 bool stateSeen = false;
1840 do {
Ruben Brunk183f0562015-08-12 12:55:02 -07001841 if (active == (mStatus == STATUS_ACTIVE)) {
1842 // Desired state is current
1843 break;
1844 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001845
1846 res = mStatusChanged.waitRelative(mLock, timeout);
1847 if (res != OK) break;
1848
Ruben Brunk183f0562015-08-12 12:55:02 -07001849 // This is impossible, but if not, could result in subtle deadlocks and invalid state
1850 // transitions.
1851 LOG_ALWAYS_FATAL_IF(startIndex > mRecentStatusUpdates.size(),
1852 "%s: Skipping status updates in Camera3Device, may result in deadlock.",
1853 __FUNCTION__);
1854
1855 // Encountered desired state since we began waiting
1856 for (size_t i = startIndex; i < mRecentStatusUpdates.size(); i++) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001857 if (active == (mRecentStatusUpdates[i] == STATUS_ACTIVE) ) {
1858 stateSeen = true;
1859 break;
1860 }
1861 }
1862 } while (!stateSeen);
1863
Ruben Brunk183f0562015-08-12 12:55:02 -07001864 mStatusWaiters--;
1865
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001866 return res;
1867}
1868
1869
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07001870status_t Camera3Device::setNotifyCallback(wp<NotificationListener> listener) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001871 ATRACE_CALL();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001872 std::lock_guard<std::mutex> l(mOutputLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001873
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001874 if (listener != NULL && mListener != NULL) {
1875 ALOGW("%s: Replacing old callback listener", __FUNCTION__);
1876 }
1877 mListener = listener;
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07001878 mRequestThread->setNotificationListener(listener);
1879 mPreparerThread->setNotificationListener(listener);
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001880
1881 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001882}
1883
Eino-Ville Talvala46910bd2013-07-18 19:15:17 -07001884bool Camera3Device::willNotify3A() {
1885 return false;
1886}
1887
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001888status_t Camera3Device::waitForNextFrame(nsecs_t timeout) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07001889 ATRACE_CALL();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001890 std::unique_lock<std::mutex> l(mOutputLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001891
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001892 while (mResultQueue.empty()) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001893 auto st = mResultSignal.wait_for(l, std::chrono::nanoseconds(timeout));
1894 if (st == std::cv_status::timeout) {
1895 return TIMED_OUT;
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001896 }
1897 }
1898 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001899}
1900
Jianing Weicb0652e2014-03-12 18:29:36 -07001901status_t Camera3Device::getNextResult(CaptureResult *frame) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001902 ATRACE_CALL();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001903 std::lock_guard<std::mutex> l(mOutputLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001904
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001905 if (mResultQueue.empty()) {
1906 return NOT_ENOUGH_DATA;
1907 }
1908
Jianing Weicb0652e2014-03-12 18:29:36 -07001909 if (frame == NULL) {
1910 ALOGE("%s: argument cannot be NULL", __FUNCTION__);
1911 return BAD_VALUE;
1912 }
1913
1914 CaptureResult &result = *(mResultQueue.begin());
1915 frame->mResultExtras = result.mResultExtras;
1916 frame->mMetadata.acquire(result.mMetadata);
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001917 frame->mPhysicalMetadatas = std::move(result.mPhysicalMetadatas);
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001918 mResultQueue.erase(mResultQueue.begin());
1919
1920 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001921}
1922
1923status_t Camera3Device::triggerAutofocus(uint32_t id) {
1924 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001925 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001926
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001927 ALOGV("%s: Triggering autofocus, id %d", __FUNCTION__, id);
1928 // Mix-in this trigger into the next request and only the next request.
1929 RequestTrigger trigger[] = {
1930 {
1931 ANDROID_CONTROL_AF_TRIGGER,
1932 ANDROID_CONTROL_AF_TRIGGER_START
1933 },
1934 {
1935 ANDROID_CONTROL_AF_TRIGGER_ID,
1936 static_cast<int32_t>(id)
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07001937 }
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001938 };
1939
1940 return mRequestThread->queueTrigger(trigger,
1941 sizeof(trigger)/sizeof(trigger[0]));
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001942}
1943
1944status_t Camera3Device::triggerCancelAutofocus(uint32_t id) {
1945 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001946 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001947
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001948 ALOGV("%s: Triggering cancel autofocus, id %d", __FUNCTION__, id);
1949 // Mix-in this trigger into the next request and only the next request.
1950 RequestTrigger trigger[] = {
1951 {
1952 ANDROID_CONTROL_AF_TRIGGER,
1953 ANDROID_CONTROL_AF_TRIGGER_CANCEL
1954 },
1955 {
1956 ANDROID_CONTROL_AF_TRIGGER_ID,
1957 static_cast<int32_t>(id)
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07001958 }
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001959 };
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001960
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001961 return mRequestThread->queueTrigger(trigger,
1962 sizeof(trigger)/sizeof(trigger[0]));
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001963}
1964
1965status_t Camera3Device::triggerPrecaptureMetering(uint32_t id) {
1966 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001967 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001968
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001969 ALOGV("%s: Triggering precapture metering, id %d", __FUNCTION__, id);
1970 // Mix-in this trigger into the next request and only the next request.
1971 RequestTrigger trigger[] = {
1972 {
1973 ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
1974 ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_START
1975 },
1976 {
1977 ANDROID_CONTROL_AE_PRECAPTURE_ID,
1978 static_cast<int32_t>(id)
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07001979 }
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001980 };
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001981
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001982 return mRequestThread->queueTrigger(trigger,
1983 sizeof(trigger)/sizeof(trigger[0]));
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001984}
1985
Jianing Weicb0652e2014-03-12 18:29:36 -07001986status_t Camera3Device::flush(int64_t *frameNumber) {
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07001987 ATRACE_CALL();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001988 ALOGV("%s: Camera %s: Flushing all requests", __FUNCTION__, mId.string());
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001989 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07001990
Zhijun He7ef20392014-04-21 16:04:17 -07001991 {
1992 Mutex::Autolock l(mLock);
Emilian Peeved2ebe42018-09-25 16:59:09 +01001993
1994 // b/116514106 "disconnect()" can get called twice for the same device. The
1995 // camera device will not be initialized during the second run.
1996 if (mStatus == STATUS_UNINITIALIZED) {
1997 return OK;
1998 }
1999
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07002000 mRequestThread->clear(/*out*/frameNumber);
Zhijun He7ef20392014-04-21 16:04:17 -07002001 }
2002
Emilian Peev08dd2452017-04-06 16:55:14 +01002003 return mRequestThread->flush();
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07002004}
2005
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002006status_t Camera3Device::prepare(int streamId) {
Ruben Brunkc78ac262015-08-13 17:58:46 -07002007 return prepare(camera3::Camera3StreamInterface::ALLOCATE_PIPELINE_MAX, streamId);
2008}
2009
2010status_t Camera3Device::prepare(int maxCount, int streamId) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002011 ATRACE_CALL();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002012 ALOGV("%s: Camera %s: Preparing stream %d", __FUNCTION__, mId.string(), streamId);
Eino-Ville Talvala261394e2015-05-13 14:28:38 -07002013 Mutex::Autolock il(mInterfaceLock);
2014 Mutex::Autolock l(mLock);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002015
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002016 sp<Camera3StreamInterface> stream = mOutputStreams.get(streamId);
2017 if (stream == nullptr) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002018 CLOGE("Stream %d does not exist", streamId);
2019 return BAD_VALUE;
2020 }
2021
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002022 if (stream->isUnpreparable() || stream->hasOutstandingBuffers() ) {
Eino-Ville Talvala261394e2015-05-13 14:28:38 -07002023 CLOGE("Stream %d has already been a request target", streamId);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002024 return BAD_VALUE;
2025 }
2026
2027 if (mRequestThread->isStreamPending(stream)) {
Eino-Ville Talvala261394e2015-05-13 14:28:38 -07002028 CLOGE("Stream %d is already a target in a pending request", streamId);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002029 return BAD_VALUE;
2030 }
2031
Ruben Brunkc78ac262015-08-13 17:58:46 -07002032 return mPreparerThread->prepare(maxCount, stream);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002033}
2034
Eino-Ville Talvalab25e3c82015-07-15 16:04:27 -07002035status_t Camera3Device::tearDown(int streamId) {
2036 ATRACE_CALL();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002037 ALOGV("%s: Camera %s: Tearing down stream %d", __FUNCTION__, mId.string(), streamId);
Eino-Ville Talvalab25e3c82015-07-15 16:04:27 -07002038 Mutex::Autolock il(mInterfaceLock);
2039 Mutex::Autolock l(mLock);
2040
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002041 sp<Camera3StreamInterface> stream = mOutputStreams.get(streamId);
2042 if (stream == nullptr) {
Eino-Ville Talvalab25e3c82015-07-15 16:04:27 -07002043 CLOGE("Stream %d does not exist", streamId);
2044 return BAD_VALUE;
2045 }
2046
Eino-Ville Talvalab25e3c82015-07-15 16:04:27 -07002047 if (stream->hasOutstandingBuffers() || mRequestThread->isStreamPending(stream)) {
2048 CLOGE("Stream %d is a target of a in-progress request", streamId);
2049 return BAD_VALUE;
2050 }
2051
2052 return stream->tearDown();
2053}
2054
Shuzhen Wangb0fdc1e2016-03-20 23:21:39 -07002055status_t Camera3Device::addBufferListenerForStream(int streamId,
2056 wp<Camera3StreamBufferListener> listener) {
2057 ATRACE_CALL();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002058 ALOGV("%s: Camera %s: Adding buffer listener for stream %d", __FUNCTION__, mId.string(), streamId);
Shuzhen Wangb0fdc1e2016-03-20 23:21:39 -07002059 Mutex::Autolock il(mInterfaceLock);
2060 Mutex::Autolock l(mLock);
2061
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002062 sp<Camera3StreamInterface> stream = mOutputStreams.get(streamId);
2063 if (stream == nullptr) {
Shuzhen Wangb0fdc1e2016-03-20 23:21:39 -07002064 CLOGE("Stream %d does not exist", streamId);
2065 return BAD_VALUE;
2066 }
Shuzhen Wangb0fdc1e2016-03-20 23:21:39 -07002067 stream->addBufferListener(listener);
2068
2069 return OK;
2070}
2071
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002072/**
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002073 * Methods called by subclasses
2074 */
2075
2076void Camera3Device::notifyStatus(bool idle) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07002077 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002078 {
2079 // Need mLock to safely update state and synchronize to current
2080 // state of methods in flight.
2081 Mutex::Autolock l(mLock);
2082 // We can get various system-idle notices from the status tracker
2083 // while starting up. Only care about them if we've actually sent
2084 // in some requests recently.
2085 if (mStatus != STATUS_ACTIVE && mStatus != STATUS_CONFIGURED) {
2086 return;
2087 }
Eino-Ville Talvala002001b2018-01-23 16:53:50 -08002088 ALOGV("%s: Camera %s: Now %s, pauseState: %s", __FUNCTION__, mId.string(),
2089 idle ? "idle" : "active", mPauseStateNotify ? "true" : "false");
Ruben Brunk183f0562015-08-12 12:55:02 -07002090 internalUpdateStatusLocked(idle ? STATUS_CONFIGURED : STATUS_ACTIVE);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002091
2092 // Skip notifying listener if we're doing some user-transparent
2093 // state changes
2094 if (mPauseStateNotify) return;
2095 }
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07002096
2097 sp<NotificationListener> listener;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002098 {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002099 std::lock_guard<std::mutex> l(mOutputLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07002100 listener = mListener.promote();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002101 }
2102 if (idle && listener != NULL) {
2103 listener->notifyIdle();
2104 }
2105}
2106
Shuzhen Wang758c2152017-01-10 18:26:18 -08002107status_t Camera3Device::setConsumerSurfaces(int streamId,
Emilian Peev40ead602017-09-26 15:46:36 +01002108 const std::vector<sp<Surface>>& consumers, std::vector<int> *surfaceIds) {
Zhijun He5d677d12016-05-29 16:52:39 -07002109 ATRACE_CALL();
Shuzhen Wang758c2152017-01-10 18:26:18 -08002110 ALOGV("%s: Camera %s: set consumer surface for stream %d",
2111 __FUNCTION__, mId.string(), streamId);
Emilian Peev40ead602017-09-26 15:46:36 +01002112
2113 if (surfaceIds == nullptr) {
2114 return BAD_VALUE;
2115 }
2116
Zhijun He5d677d12016-05-29 16:52:39 -07002117 Mutex::Autolock il(mInterfaceLock);
2118 Mutex::Autolock l(mLock);
2119
Shuzhen Wang758c2152017-01-10 18:26:18 -08002120 if (consumers.size() == 0) {
2121 CLOGE("No consumer is passed!");
Zhijun He5d677d12016-05-29 16:52:39 -07002122 return BAD_VALUE;
2123 }
2124
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002125 sp<Camera3OutputStreamInterface> stream = mOutputStreams.get(streamId);
2126 if (stream == nullptr) {
Zhijun He5d677d12016-05-29 16:52:39 -07002127 CLOGE("Stream %d is unknown", streamId);
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002128 return BAD_VALUE;
Zhijun He5d677d12016-05-29 16:52:39 -07002129 }
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002130
2131 // isConsumerConfigurationDeferred will be off after setConsumers
2132 bool isDeferred = stream->isConsumerConfigurationDeferred();
Shuzhen Wang758c2152017-01-10 18:26:18 -08002133 status_t res = stream->setConsumers(consumers);
Zhijun He5d677d12016-05-29 16:52:39 -07002134 if (res != OK) {
2135 CLOGE("Stream %d set consumer failed (error %d %s) ", streamId, res, strerror(-res));
2136 return res;
2137 }
2138
Emilian Peev40ead602017-09-26 15:46:36 +01002139 for (auto &consumer : consumers) {
2140 int id = stream->getSurfaceId(consumer);
2141 if (id < 0) {
2142 CLOGE("Invalid surface id!");
2143 return BAD_VALUE;
2144 }
2145 surfaceIds->push_back(id);
2146 }
2147
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002148 if (isDeferred) {
Shuzhen Wang0129d522016-10-30 22:43:41 -07002149 if (!stream->isConfiguring()) {
2150 CLOGE("Stream %d was already fully configured.", streamId);
2151 return INVALID_OPERATION;
2152 }
Zhijun He5d677d12016-05-29 16:52:39 -07002153
Shuzhen Wang0129d522016-10-30 22:43:41 -07002154 res = stream->finishConfiguration();
2155 if (res != OK) {
Shuzhen Wang210ba5c2018-07-25 16:47:40 -07002156 // If finishConfiguration fails due to abandoned surface, do not set
2157 // device to error state.
2158 bool isSurfaceAbandoned =
2159 (res == NO_INIT || res == DEAD_OBJECT) && stream->isAbandoned();
2160 if (!isSurfaceAbandoned) {
2161 SET_ERR_L("Can't finish configuring output stream %d: %s (%d)",
2162 stream->getId(), strerror(-res), res);
2163 }
Shuzhen Wang0129d522016-10-30 22:43:41 -07002164 return res;
2165 }
Zhijun He5d677d12016-05-29 16:52:39 -07002166 }
2167
2168 return OK;
2169}
2170
Emilian Peev40ead602017-09-26 15:46:36 +01002171status_t Camera3Device::updateStream(int streamId, const std::vector<sp<Surface>> &newSurfaces,
2172 const std::vector<OutputStreamInfo> &outputInfo,
2173 const std::vector<size_t> &removedSurfaceIds, KeyedVector<sp<Surface>, size_t> *outputMap) {
2174 Mutex::Autolock il(mInterfaceLock);
2175 Mutex::Autolock l(mLock);
2176
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002177 sp<Camera3OutputStreamInterface> stream = mOutputStreams.get(streamId);
2178 if (stream == nullptr) {
Emilian Peev40ead602017-09-26 15:46:36 +01002179 CLOGE("Stream %d is unknown", streamId);
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002180 return BAD_VALUE;
Emilian Peev40ead602017-09-26 15:46:36 +01002181 }
2182
2183 for (const auto &it : removedSurfaceIds) {
2184 if (mRequestThread->isOutputSurfacePending(streamId, it)) {
2185 CLOGE("Shared surface still part of a pending request!");
2186 return -EBUSY;
2187 }
2188 }
2189
Emilian Peev40ead602017-09-26 15:46:36 +01002190 status_t res = stream->updateStream(newSurfaces, outputInfo, removedSurfaceIds, outputMap);
2191 if (res != OK) {
2192 CLOGE("Stream %d failed to update stream (error %d %s) ",
2193 streamId, res, strerror(-res));
2194 if (res == UNKNOWN_ERROR) {
2195 SET_ERR_L("%s: Stream update failed to revert to previous output configuration!",
2196 __FUNCTION__);
2197 }
2198 return res;
2199 }
2200
2201 return res;
2202}
2203
Chien-Yu Chena936ac22017-10-23 15:59:49 -07002204status_t Camera3Device::dropStreamBuffers(bool dropping, int streamId) {
2205 Mutex::Autolock il(mInterfaceLock);
2206 Mutex::Autolock l(mLock);
2207
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002208 sp<Camera3OutputStreamInterface> stream = mOutputStreams.get(streamId);
2209 if (stream == nullptr) {
Chien-Yu Chena936ac22017-10-23 15:59:49 -07002210 ALOGE("%s: Stream %d is not found.", __FUNCTION__, streamId);
2211 return BAD_VALUE;
2212 }
Chien-Yu Chena936ac22017-10-23 15:59:49 -07002213 return stream->dropBuffers(dropping);
2214}
2215
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002216/**
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002217 * Camera3Device private methods
2218 */
2219
2220sp<Camera3Device::CaptureRequest> Camera3Device::createCaptureRequest(
Emilian Peevaebbe412018-01-15 13:53:24 +00002221 const PhysicalCameraSettingsList &request, const SurfaceMap &surfaceMap) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002222 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002223
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08002224 sp<CaptureRequest> newRequest = new CaptureRequest();
Emilian Peevaebbe412018-01-15 13:53:24 +00002225 newRequest->mSettingsList = request;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002226
2227 camera_metadata_entry_t inputStreams =
Emilian Peevaebbe412018-01-15 13:53:24 +00002228 newRequest->mSettingsList.begin()->metadata.find(ANDROID_REQUEST_INPUT_STREAMS);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002229 if (inputStreams.count > 0) {
2230 if (mInputStream == NULL ||
Zhijun Hed1d64672013-09-06 15:00:01 -07002231 mInputStream->getId() != inputStreams.data.i32[0]) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002232 CLOGE("Request references unknown input stream %d",
2233 inputStreams.data.u8[0]);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002234 return NULL;
2235 }
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002236
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002237 if (mInputStream->isConfiguring()) {
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002238 SET_ERR_L("%s: input stream %d is not configured!",
2239 __FUNCTION__, mInputStream->getId());
2240 return NULL;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002241 }
Shuzhen Wangb3a0fb52018-09-13 17:24:08 -07002242 // Check if stream prepare is blocking requests.
2243 if (mInputStream->isBlockedByPrepare()) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002244 CLOGE("Request references an input stream that's being prepared!");
2245 return NULL;
2246 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002247
2248 newRequest->mInputStream = mInputStream;
Emilian Peevaebbe412018-01-15 13:53:24 +00002249 newRequest->mSettingsList.begin()->metadata.erase(ANDROID_REQUEST_INPUT_STREAMS);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002250 }
2251
2252 camera_metadata_entry_t streams =
Emilian Peevaebbe412018-01-15 13:53:24 +00002253 newRequest->mSettingsList.begin()->metadata.find(ANDROID_REQUEST_OUTPUT_STREAMS);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002254 if (streams.count == 0) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002255 CLOGE("Zero output streams specified!");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002256 return NULL;
2257 }
2258
2259 for (size_t i = 0; i < streams.count; i++) {
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002260 sp<Camera3OutputStreamInterface> stream = mOutputStreams.get(streams.data.i32[i]);
2261 if (stream == nullptr) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002262 CLOGE("Request references unknown stream %d",
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002263 streams.data.i32[i]);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002264 return NULL;
2265 }
Zhijun He5d677d12016-05-29 16:52:39 -07002266 // It is illegal to include a deferred consumer output stream into a request
Shuzhen Wang0129d522016-10-30 22:43:41 -07002267 auto iter = surfaceMap.find(streams.data.i32[i]);
2268 if (iter != surfaceMap.end()) {
2269 const std::vector<size_t>& surfaces = iter->second;
2270 for (const auto& surface : surfaces) {
2271 if (stream->isConsumerConfigurationDeferred(surface)) {
2272 CLOGE("Stream %d surface %zu hasn't finished configuration yet "
2273 "due to deferred consumer", stream->getId(), surface);
2274 return NULL;
2275 }
2276 }
Yin-Chia Yeh0b287572018-10-15 12:38:13 -07002277 newRequest->mOutputSurfaces[streams.data.i32[i]] = surfaces;
Zhijun He5d677d12016-05-29 16:52:39 -07002278 }
2279
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002280 if (stream->isConfiguring()) {
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002281 SET_ERR_L("%s: stream %d is not configured!", __FUNCTION__, stream->getId());
2282 return NULL;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002283 }
Shuzhen Wangb3a0fb52018-09-13 17:24:08 -07002284 // Check if stream prepare is blocking requests.
2285 if (stream->isBlockedByPrepare()) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002286 CLOGE("Request references an output stream that's being prepared!");
2287 return NULL;
2288 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002289
2290 newRequest->mOutputStreams.push(stream);
2291 }
Emilian Peevaebbe412018-01-15 13:53:24 +00002292 newRequest->mSettingsList.begin()->metadata.erase(ANDROID_REQUEST_OUTPUT_STREAMS);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07002293 newRequest->mBatchSize = 1;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002294
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08002295 auto rotateAndCropEntry =
2296 newRequest->mSettingsList.begin()->metadata.find(ANDROID_SCALER_ROTATE_AND_CROP);
2297 if (rotateAndCropEntry.count > 0 &&
2298 rotateAndCropEntry.data.u8[0] == ANDROID_SCALER_ROTATE_AND_CROP_AUTO) {
2299 newRequest->mRotateAndCropAuto = true;
2300 } else {
2301 newRequest->mRotateAndCropAuto = false;
2302 }
2303
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002304 return newRequest;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002305}
2306
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002307void Camera3Device::cancelStreamsConfigurationLocked() {
2308 int res = OK;
2309 if (mInputStream != NULL && mInputStream->isConfiguring()) {
2310 res = mInputStream->cancelConfiguration();
2311 if (res != OK) {
2312 CLOGE("Can't cancel configuring input stream %d: %s (%d)",
2313 mInputStream->getId(), strerror(-res), res);
2314 }
2315 }
2316
2317 for (size_t i = 0; i < mOutputStreams.size(); i++) {
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002318 sp<Camera3OutputStreamInterface> outputStream = mOutputStreams[i];
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002319 if (outputStream->isConfiguring()) {
2320 res = outputStream->cancelConfiguration();
2321 if (res != OK) {
2322 CLOGE("Can't cancel configuring output stream %d: %s (%d)",
2323 outputStream->getId(), strerror(-res), res);
2324 }
2325 }
2326 }
2327
2328 // Return state to that at start of call, so that future configures
2329 // properly clean things up
2330 internalUpdateStatusLocked(STATUS_UNCONFIGURED);
2331 mNeedConfig = true;
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002332
2333 res = mPreparerThread->resume();
2334 if (res != OK) {
2335 ALOGE("%s: Camera %s: Preparer thread failed to resume!", __FUNCTION__, mId.string());
2336 }
2337}
2338
2339bool Camera3Device::reconfigureCamera(const CameraMetadata& sessionParams) {
2340 ATRACE_CALL();
2341 bool ret = false;
2342
Jayant Chowdhary37eca242019-11-18 08:55:56 -08002343 // We must not hold mInterfaceLock here since this function is called from
2344 // RequestThread::threadLoop and holding mInterfaceLock could lead to
2345 // deadlocks (http://b/143513518)
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002346 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
2347
2348 Mutex::Autolock l(mLock);
2349 auto rc = internalPauseAndWaitLocked(maxExpectedDuration);
2350 if (rc == NO_ERROR) {
2351 mNeedConfig = true;
2352 rc = configureStreamsLocked(mOperatingMode, sessionParams, /*notifyRequestThread*/ false);
2353 if (rc == NO_ERROR) {
2354 ret = true;
2355 mPauseStateNotify = false;
2356 //Moving to active state while holding 'mLock' is important.
2357 //There could be pending calls to 'create-/deleteStream' which
2358 //will trigger another stream configuration while the already
2359 //present streams end up with outstanding buffers that will
2360 //not get drained.
2361 internalUpdateStatusLocked(STATUS_ACTIVE);
Shuzhen Wang210ba5c2018-07-25 16:47:40 -07002362 } else if (rc == DEAD_OBJECT) {
2363 // DEAD_OBJECT can be returned if either the consumer surface is
2364 // abandoned, or the HAL has died.
2365 // - If the HAL has died, configureStreamsLocked call will set
2366 // device to error state,
2367 // - If surface is abandoned, we should not set device to error
2368 // state.
2369 ALOGE("Failed to re-configure camera due to abandoned surface");
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002370 } else {
Shuzhen Wang210ba5c2018-07-25 16:47:40 -07002371 SET_ERR_L("Failed to re-configure camera: %d", rc);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002372 }
2373 } else {
2374 ALOGE("%s: Failed to pause streaming: %d", __FUNCTION__, rc);
2375 }
2376
2377 return ret;
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002378}
2379
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01002380status_t Camera3Device::configureStreamsLocked(int operatingMode,
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002381 const CameraMetadata& sessionParams, bool notifyRequestThread) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002382 ATRACE_CALL();
2383 status_t res;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002384
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002385 if (mStatus != STATUS_UNCONFIGURED && mStatus != STATUS_CONFIGURED) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002386 CLOGE("Not idle");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002387 return INVALID_OPERATION;
2388 }
2389
Eino-Ville Talvalae7091aa2017-03-07 15:23:06 -08002390 if (operatingMode < 0) {
2391 CLOGE("Invalid operating mode: %d", operatingMode);
2392 return BAD_VALUE;
2393 }
2394
2395 bool isConstrainedHighSpeed =
2396 static_cast<int>(StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE) ==
2397 operatingMode;
2398
2399 if (mOperatingMode != operatingMode) {
2400 mNeedConfig = true;
2401 mIsConstrainedHighSpeedConfiguration = isConstrainedHighSpeed;
2402 mOperatingMode = operatingMode;
2403 }
2404
Shuzhen Wang0cf01cb2019-09-05 13:33:06 -07002405 // In case called from configureStreams, abort queued input buffers not belonging to
2406 // any pending requests.
2407 if (mInputStream != NULL && notifyRequestThread) {
2408 while (true) {
2409 camera3_stream_buffer_t inputBuffer;
2410 status_t res = mInputStream->getInputBuffer(&inputBuffer,
2411 /*respectHalLimit*/ false);
2412 if (res != OK) {
2413 // Exhausted acquiring all input buffers.
2414 break;
2415 }
2416
2417 inputBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
2418 res = mInputStream->returnInputBuffer(inputBuffer);
2419 if (res != OK) {
2420 ALOGE("%s: %d: couldn't return input buffer while clearing input queue: "
2421 "%s (%d)", __FUNCTION__, __LINE__, strerror(-res), res);
2422 }
2423 }
2424 }
2425
Eino-Ville Talvalaea26c772013-06-11 16:04:06 -07002426 if (!mNeedConfig) {
2427 ALOGV("%s: Skipping config, no stream changes", __FUNCTION__);
2428 return OK;
2429 }
2430
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002431 // Workaround for device HALv3.2 or older spec bug - zero streams requires
2432 // adding a dummy stream instead.
2433 // TODO: Bug: 17321404 for fixing the HAL spec and removing this workaround.
2434 if (mOutputStreams.size() == 0) {
2435 addDummyStreamLocked();
2436 } else {
2437 tryRemoveDummyStreamLocked();
2438 }
2439
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002440 // Start configuring the streams
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002441 ALOGV("%s: Camera %s: Starting stream configuration", __FUNCTION__, mId.string());
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002442
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002443 mPreparerThread->pause();
2444
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002445 camera3_stream_configuration config;
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -08002446 config.operation_mode = mOperatingMode;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002447 config.num_streams = (mInputStream != NULL) + mOutputStreams.size();
2448
2449 Vector<camera3_stream_t*> streams;
2450 streams.setCapacity(config.num_streams);
Emilian Peev192ee832018-01-31 14:46:47 +00002451 std::vector<uint32_t> bufferSizes(config.num_streams, 0);
Yin-Chia Yehfb6e55b2018-01-25 10:50:26 -08002452
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002453
2454 if (mInputStream != NULL) {
2455 camera3_stream_t *inputStream;
2456 inputStream = mInputStream->startConfiguration();
2457 if (inputStream == NULL) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002458 CLOGE("Can't start input stream configuration");
2459 cancelStreamsConfigurationLocked();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002460 return INVALID_OPERATION;
2461 }
2462 streams.add(inputStream);
2463 }
2464
2465 for (size_t i = 0; i < mOutputStreams.size(); i++) {
Igor Murashkin2fba5842013-04-22 14:03:54 -07002466
2467 // Don't configure bidi streams twice, nor add them twice to the list
2468 if (mOutputStreams[i].get() ==
2469 static_cast<Camera3StreamInterface*>(mInputStream.get())) {
2470
2471 config.num_streams--;
2472 continue;
2473 }
2474
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002475 camera3_stream_t *outputStream;
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002476 outputStream = mOutputStreams[i]->startConfiguration();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002477 if (outputStream == NULL) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002478 CLOGE("Can't start output stream configuration");
2479 cancelStreamsConfigurationLocked();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002480 return INVALID_OPERATION;
2481 }
2482 streams.add(outputStream);
Yin-Chia Yehfb6e55b2018-01-25 10:50:26 -08002483
Shuzhen Wangb7ab1e42019-02-20 15:42:23 -08002484 if (outputStream->format == HAL_PIXEL_FORMAT_BLOB) {
Emilian Peev192ee832018-01-31 14:46:47 +00002485 size_t k = i + ((mInputStream != nullptr) ? 1 : 0); // Input stream if present should
2486 // always occupy the initial entry.
Shuzhen Wangb7ab1e42019-02-20 15:42:23 -08002487 if (outputStream->data_space == HAL_DATASPACE_V0_JFIF) {
2488 bufferSizes[k] = static_cast<uint32_t>(
2489 getJpegBufferSize(outputStream->width, outputStream->height));
2490 } else if (outputStream->data_space ==
2491 static_cast<android_dataspace>(HAL_DATASPACE_JPEG_APP_SEGMENTS)) {
2492 bufferSizes[k] = outputStream->width * outputStream->height;
2493 } else {
2494 ALOGW("%s: Blob dataSpace %d not supported",
2495 __FUNCTION__, outputStream->data_space);
2496 }
Yin-Chia Yehfb6e55b2018-01-25 10:50:26 -08002497 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002498 }
2499
2500 config.streams = streams.editArray();
2501
2502 // Do the HAL configuration; will potentially touch stream
Shuzhen Wang92653952019-05-07 15:11:43 -07002503 // max_buffers, usage, and priv fields, as well as data_space and format
2504 // fields for IMPLEMENTATION_DEFINED formats.
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002505
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01002506 const camera_metadata_t *sessionBuffer = sessionParams.getAndLock();
Emilian Peev192ee832018-01-31 14:46:47 +00002507 res = mInterface->configureStreams(sessionBuffer, &config, bufferSizes);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01002508 sessionParams.unlock(sessionBuffer);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002509
Eino-Ville Talvala17543512014-08-06 14:32:02 -07002510 if (res == BAD_VALUE) {
2511 // HAL rejected this set of streams as unsupported, clean up config
2512 // attempt and return to unconfigured state
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002513 CLOGE("Set of requested inputs/outputs not supported by HAL");
2514 cancelStreamsConfigurationLocked();
Eino-Ville Talvala17543512014-08-06 14:32:02 -07002515 return BAD_VALUE;
2516 } else if (res != OK) {
2517 // Some other kind of error from configure_streams - this is not
2518 // expected
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002519 SET_ERR_L("Unable to configure streams with HAL: %s (%d)",
2520 strerror(-res), res);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002521 return res;
2522 }
2523
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002524 // Finish all stream configuration immediately.
2525 // TODO: Try to relax this later back to lazy completion, which should be
2526 // faster
2527
Igor Murashkin073f8572013-05-02 14:59:28 -07002528 if (mInputStream != NULL && mInputStream->isConfiguring()) {
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002529 bool streamReConfigured = false;
2530 res = mInputStream->finishConfiguration(&streamReConfigured);
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002531 if (res != OK) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002532 CLOGE("Can't finish configuring input stream %d: %s (%d)",
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002533 mInputStream->getId(), strerror(-res), res);
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002534 cancelStreamsConfigurationLocked();
Shuzhen Wang210ba5c2018-07-25 16:47:40 -07002535 if ((res == NO_INIT || res == DEAD_OBJECT) && mInputStream->isAbandoned()) {
2536 return DEAD_OBJECT;
2537 }
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002538 return BAD_VALUE;
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002539 }
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002540 if (streamReConfigured) {
2541 mInterface->onStreamReConfigured(mInputStream->getId());
2542 }
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002543 }
2544
2545 for (size_t i = 0; i < mOutputStreams.size(); i++) {
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002546 sp<Camera3OutputStreamInterface> outputStream = mOutputStreams[i];
Zhijun He5d677d12016-05-29 16:52:39 -07002547 if (outputStream->isConfiguring() && !outputStream->isConsumerConfigurationDeferred()) {
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002548 bool streamReConfigured = false;
2549 res = outputStream->finishConfiguration(&streamReConfigured);
Igor Murashkin073f8572013-05-02 14:59:28 -07002550 if (res != OK) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002551 CLOGE("Can't finish configuring output stream %d: %s (%d)",
Igor Murashkin073f8572013-05-02 14:59:28 -07002552 outputStream->getId(), strerror(-res), res);
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002553 cancelStreamsConfigurationLocked();
Shuzhen Wang210ba5c2018-07-25 16:47:40 -07002554 if ((res == NO_INIT || res == DEAD_OBJECT) && outputStream->isAbandoned()) {
2555 return DEAD_OBJECT;
2556 }
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002557 return BAD_VALUE;
Igor Murashkin073f8572013-05-02 14:59:28 -07002558 }
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002559 if (streamReConfigured) {
2560 mInterface->onStreamReConfigured(outputStream->getId());
2561 }
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002562 }
2563 }
2564
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002565 // Request thread needs to know to avoid using repeat-last-settings protocol
2566 // across configure_streams() calls
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002567 if (notifyRequestThread) {
2568 mRequestThread->configurationComplete(mIsConstrainedHighSpeedConfiguration, sessionParams);
2569 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002570
Zhijun He90f7c372016-08-16 16:19:43 -07002571 char value[PROPERTY_VALUE_MAX];
2572 property_get("camera.fifo.disable", value, "0");
2573 int32_t disableFifo = atoi(value);
2574 if (disableFifo != 1) {
2575 // Boost priority of request thread to SCHED_FIFO.
2576 pid_t requestThreadTid = mRequestThread->getTid();
2577 res = requestPriority(getpid(), requestThreadTid,
Mikhail Naganov83f04272017-02-07 10:45:09 -08002578 kRequestThreadPriority, /*isForApp*/ false, /*asynchronous*/ false);
Zhijun He90f7c372016-08-16 16:19:43 -07002579 if (res != OK) {
2580 ALOGW("Can't set realtime priority for request processing thread: %s (%d)",
2581 strerror(-res), res);
2582 } else {
2583 ALOGD("Set real time priority for request queue thread (tid %d)", requestThreadTid);
2584 }
Eino-Ville Talvalaf99498e2015-09-25 16:52:55 -07002585 }
2586
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002587 // Update device state
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01002588 const camera_metadata_t *newSessionParams = sessionParams.getAndLock();
2589 const camera_metadata_t *currentSessionParams = mSessionParams.getAndLock();
2590 bool updateSessionParams = (newSessionParams != currentSessionParams) ? true : false;
2591 sessionParams.unlock(newSessionParams);
2592 mSessionParams.unlock(currentSessionParams);
2593 if (updateSessionParams) {
2594 mSessionParams = sessionParams;
2595 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002596
Eino-Ville Talvalaea26c772013-06-11 16:04:06 -07002597 mNeedConfig = false;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002598
Ruben Brunk183f0562015-08-12 12:55:02 -07002599 internalUpdateStatusLocked((mDummyStreamId == NO_STREAM) ?
2600 STATUS_CONFIGURED : STATUS_UNCONFIGURED);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002601
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002602 ALOGV("%s: Camera %s: Stream configuration complete", __FUNCTION__, mId.string());
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002603
Zhijun He0a210512014-07-24 13:45:15 -07002604 // tear down the deleted streams after configure streams.
2605 mDeletedStreams.clear();
2606
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002607 auto rc = mPreparerThread->resume();
2608 if (rc != OK) {
2609 SET_ERR_L("%s: Camera %s: Preparer thread failed to resume!", __FUNCTION__, mId.string());
2610 return rc;
2611 }
2612
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07002613 if (mDummyStreamId == NO_STREAM) {
2614 mRequestBufferSM.onStreamsConfigured();
2615 }
2616
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002617 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002618}
2619
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002620status_t Camera3Device::addDummyStreamLocked() {
2621 ATRACE_CALL();
2622 status_t res;
2623
2624 if (mDummyStreamId != NO_STREAM) {
2625 // Should never be adding a second dummy stream when one is already
2626 // active
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002627 SET_ERR_L("%s: Camera %s: A dummy stream already exists!",
2628 __FUNCTION__, mId.string());
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002629 return INVALID_OPERATION;
2630 }
2631
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002632 ALOGV("%s: Camera %s: Adding a dummy stream", __FUNCTION__, mId.string());
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002633
2634 sp<Camera3OutputStreamInterface> dummyStream =
2635 new Camera3DummyStream(mNextStreamId);
2636
2637 res = mOutputStreams.add(mNextStreamId, dummyStream);
2638 if (res < 0) {
2639 SET_ERR_L("Can't add dummy stream to set: %s (%d)", strerror(-res), res);
2640 return res;
2641 }
2642
2643 mDummyStreamId = mNextStreamId;
2644 mNextStreamId++;
2645
2646 return OK;
2647}
2648
2649status_t Camera3Device::tryRemoveDummyStreamLocked() {
2650 ATRACE_CALL();
2651 status_t res;
2652
2653 if (mDummyStreamId == NO_STREAM) return OK;
2654 if (mOutputStreams.size() == 1) return OK;
2655
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002656 ALOGV("%s: Camera %s: Removing the dummy stream", __FUNCTION__, mId.string());
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002657
2658 // Ok, have a dummy stream and there's at least one other output stream,
2659 // so remove the dummy
2660
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002661 sp<Camera3StreamInterface> deletedStream = mOutputStreams.get(mDummyStreamId);
2662 if (deletedStream == nullptr) {
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002663 SET_ERR_L("Dummy stream %d does not appear to exist", mDummyStreamId);
2664 return INVALID_OPERATION;
2665 }
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002666 mOutputStreams.remove(mDummyStreamId);
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002667
2668 // Free up the stream endpoint so that it can be used by some other stream
2669 res = deletedStream->disconnect();
2670 if (res != OK) {
2671 SET_ERR_L("Can't disconnect deleted dummy stream %d", mDummyStreamId);
2672 // fall through since we want to still list the stream as deleted.
2673 }
2674 mDeletedStreams.add(deletedStream);
2675 mDummyStreamId = NO_STREAM;
2676
2677 return res;
2678}
2679
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002680void Camera3Device::setErrorState(const char *fmt, ...) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07002681 ATRACE_CALL();
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002682 Mutex::Autolock l(mLock);
2683 va_list args;
2684 va_start(args, fmt);
2685
2686 setErrorStateLockedV(fmt, args);
2687
2688 va_end(args);
2689}
2690
2691void Camera3Device::setErrorStateV(const char *fmt, va_list args) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07002692 ATRACE_CALL();
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002693 Mutex::Autolock l(mLock);
2694 setErrorStateLockedV(fmt, args);
2695}
2696
2697void Camera3Device::setErrorStateLocked(const char *fmt, ...) {
2698 va_list args;
2699 va_start(args, fmt);
2700
2701 setErrorStateLockedV(fmt, args);
2702
2703 va_end(args);
2704}
2705
2706void Camera3Device::setErrorStateLockedV(const char *fmt, va_list args) {
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002707 // Print out all error messages to log
2708 String8 errorCause = String8::formatV(fmt, args);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002709 ALOGE("Camera %s: %s", mId.string(), errorCause.string());
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002710
2711 // But only do error state transition steps for the first error
Zhijun Heb05eeae2013-06-06 13:51:22 -07002712 if (mStatus == STATUS_ERROR || mStatus == STATUS_UNINITIALIZED) return;
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002713
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002714 mErrorCause = errorCause;
2715
Yin-Chia Yeh3d145ae2017-07-27 12:47:03 -07002716 if (mRequestThread != nullptr) {
2717 mRequestThread->setPaused(true);
2718 }
Ruben Brunk183f0562015-08-12 12:55:02 -07002719 internalUpdateStatusLocked(STATUS_ERROR);
Eino-Ville Talvala17543512014-08-06 14:32:02 -07002720
2721 // Notify upstream about a device error
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07002722 sp<NotificationListener> listener = mListener.promote();
2723 if (listener != NULL) {
2724 listener->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
Eino-Ville Talvala17543512014-08-06 14:32:02 -07002725 CaptureResultExtras());
2726 }
2727
2728 // Save stack trace. View by dumping it later.
2729 CameraTraces::saveTrace();
2730 // TODO: consider adding errorCause and client pid/procname
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002731}
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002732
2733/**
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002734 * In-flight request management
2735 */
2736
Jianing Weicb0652e2014-03-12 18:29:36 -07002737status_t Camera3Device::registerInFlight(uint32_t frameNumber,
Chien-Yu Chend196d612015-06-22 19:49:01 -07002738 int32_t numBuffers, CaptureResultExtras resultExtras, bool hasInput,
Shuzhen Wang5c22c152017-12-31 17:12:25 -08002739 bool hasAppCallback, nsecs_t maxExpectedDuration,
Shuzhen Wang26abaf42018-08-28 15:41:20 -07002740 std::set<String8>& physicalCameraIds, bool isStillCapture,
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08002741 bool isZslCapture, bool rotateAndCropAuto, const std::set<std::string>& cameraIdsWithZoom,
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08002742 const SurfaceMap& outputSurfaces) {
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002743 ATRACE_CALL();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002744 std::lock_guard<std::mutex> l(mInFlightLock);
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002745
2746 ssize_t res;
Chien-Yu Chend196d612015-06-22 19:49:01 -07002747 res = mInFlightMap.add(frameNumber, InFlightRequest(numBuffers, resultExtras, hasInput,
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07002748 hasAppCallback, maxExpectedDuration, physicalCameraIds, isStillCapture, isZslCapture,
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08002749 rotateAndCropAuto, cameraIdsWithZoom, outputSurfaces));
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002750 if (res < 0) return res;
2751
Eino-Ville Talvala24b366e2016-07-21 12:53:07 -07002752 if (mInFlightMap.size() == 1) {
Emilian Peev26d975d2018-07-05 14:52:57 +01002753 // Hold a separate dedicated tracker lock to prevent race with disconnect and also
2754 // avoid a deadlock during reprocess requests.
2755 Mutex::Autolock l(mTrackerLock);
Yin-Chia Yeh38dfde52017-06-27 17:13:33 -07002756 if (mStatusTracker != nullptr) {
2757 mStatusTracker->markComponentActive(mInFlightStatusId);
2758 }
Eino-Ville Talvala24b366e2016-07-21 12:53:07 -07002759 }
2760
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07002761 mExpectedInflightDuration += maxExpectedDuration;
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002762 return OK;
2763}
2764
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002765void Camera3Device::onInflightEntryRemovedLocked(nsecs_t duration) {
Shuzhen Wangcadb3302016-11-04 14:17:56 -07002766 // Indicate idle inFlightMap to the status tracker
2767 if (mInFlightMap.size() == 0) {
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07002768 mRequestBufferSM.onInflightMapEmpty();
Emilian Peev26d975d2018-07-05 14:52:57 +01002769 // Hold a separate dedicated tracker lock to prevent race with disconnect and also
2770 // avoid a deadlock during reprocess requests.
2771 Mutex::Autolock l(mTrackerLock);
Yin-Chia Yeh38dfde52017-06-27 17:13:33 -07002772 if (mStatusTracker != nullptr) {
2773 mStatusTracker->markComponentIdle(mInFlightStatusId, Fence::NO_FENCE);
2774 }
Shuzhen Wangcadb3302016-11-04 14:17:56 -07002775 }
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07002776 mExpectedInflightDuration -= duration;
Shuzhen Wangcadb3302016-11-04 14:17:56 -07002777}
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08002778
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002779void Camera3Device::checkInflightMapLengthLocked() {
Yin-Chia Yeh99fd0972019-06-27 14:22:44 -07002780 // Sanity check - if we have too many in-flight frames with long total inflight duration,
2781 // something has likely gone wrong. This might still be legit only if application send in
2782 // a long burst of long exposure requests.
2783 if (mExpectedInflightDuration > kMinWarnInflightDuration) {
2784 if (!mIsConstrainedHighSpeedConfiguration && mInFlightMap.size() > kInFlightWarnLimit) {
2785 CLOGW("In-flight list too large: %zu, total inflight duration %" PRIu64,
2786 mInFlightMap.size(), mExpectedInflightDuration);
2787 } else if (mIsConstrainedHighSpeedConfiguration && mInFlightMap.size() >
2788 kInFlightWarnLimitHighSpeed) {
2789 CLOGW("In-flight list too large for high speed configuration: %zu,"
2790 "total inflight duration %" PRIu64,
2791 mInFlightMap.size(), mExpectedInflightDuration);
2792 }
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08002793 }
2794}
2795
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002796void Camera3Device::onInflightMapFlushedLocked() {
2797 mExpectedInflightDuration = 0;
2798}
2799
2800void Camera3Device::removeInFlightMapEntryLocked(int idx) {
2801 ATRACE_CALL();
2802 nsecs_t duration = mInFlightMap.valueAt(idx).maxExpectedDuration;
2803 mInFlightMap.removeItemsAt(idx, 1);
2804
2805 onInflightEntryRemovedLocked(duration);
2806}
2807
2808
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07002809void Camera3Device::flushInflightRequests() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07002810 ATRACE_CALL();
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07002811 sp<NotificationListener> listener;
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07002812 {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002813 std::lock_guard<std::mutex> l(mOutputLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07002814 listener = mListener.promote();
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07002815 }
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002816
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002817 FlushInflightReqStates states {
2818 mId, mInFlightLock, mInFlightMap, mUseHalBufManager,
2819 listener, *this, *mInterface, *this};
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07002820
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002821 camera3::flushInflightRequests(states);
Eino-Ville Talvala17543512014-08-06 14:32:02 -07002822}
2823
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002824CameraMetadata Camera3Device::getLatestRequestLocked() {
Igor Murashkin1e479c02013-09-06 16:55:14 -07002825 ALOGV("%s", __FUNCTION__);
2826
Igor Murashkin1e479c02013-09-06 16:55:14 -07002827 CameraMetadata retVal;
2828
2829 if (mRequestThread != NULL) {
2830 retVal = mRequestThread->getLatestRequest();
2831 }
2832
Igor Murashkin1e479c02013-09-06 16:55:14 -07002833 return retVal;
2834}
2835
Eino-Ville Talvala4d453832016-07-15 11:56:53 -07002836void Camera3Device::monitorMetadata(TagMonitor::eventSource source,
Shuzhen Wangc2cba122018-05-17 18:10:24 -07002837 int64_t frameNumber, nsecs_t timestamp, const CameraMetadata& metadata,
2838 const std::unordered_map<std::string, CameraMetadata>& physicalMetadata) {
2839
2840 mTagMonitor.monitorMetadata(source, frameNumber, timestamp, metadata,
2841 physicalMetadata);
Eino-Ville Talvala4d453832016-07-15 11:56:53 -07002842}
2843
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002844/**
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002845 * HalInterface inner class methods
2846 */
2847
Yifan Hongf79b5542017-04-11 14:44:25 -07002848Camera3Device::HalInterface::HalInterface(
2849 sp<ICameraDeviceSession> &session,
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08002850 std::shared_ptr<RequestMetadataQueue> queue,
Yin-Chia Yehb978c382019-10-30 00:22:37 -07002851 bool useHalBufManager, bool supportOfflineProcessing) :
Yifan Hongf79b5542017-04-11 14:44:25 -07002852 mHidlSession(session),
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08002853 mRequestMetadataQueue(queue),
Emilian Peev4ec17882019-01-24 17:16:58 -08002854 mUseHalBufManager(useHalBufManager),
Yin-Chia Yehb978c382019-10-30 00:22:37 -07002855 mIsReconfigurationQuerySupported(true),
2856 mSupportOfflineProcessing(supportOfflineProcessing) {
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002857 // Check with hardware service manager if we can downcast these interfaces
2858 // Somewhat expensive, so cache the results at startup
Yin-Chia Yehb978c382019-10-30 00:22:37 -07002859 auto castResult_3_6 = device::V3_6::ICameraDeviceSession::castFrom(mHidlSession);
2860 if (castResult_3_6.isOk()) {
2861 mHidlSession_3_6 = castResult_3_6;
2862 }
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07002863 auto castResult_3_5 = device::V3_5::ICameraDeviceSession::castFrom(mHidlSession);
2864 if (castResult_3_5.isOk()) {
2865 mHidlSession_3_5 = castResult_3_5;
2866 }
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002867 auto castResult_3_4 = device::V3_4::ICameraDeviceSession::castFrom(mHidlSession);
2868 if (castResult_3_4.isOk()) {
2869 mHidlSession_3_4 = castResult_3_4;
2870 }
2871 auto castResult_3_3 = device::V3_3::ICameraDeviceSession::castFrom(mHidlSession);
2872 if (castResult_3_3.isOk()) {
2873 mHidlSession_3_3 = castResult_3_3;
2874 }
2875}
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002876
Yin-Chia Yehb978c382019-10-30 00:22:37 -07002877Camera3Device::HalInterface::HalInterface() :
2878 mUseHalBufManager(false),
2879 mSupportOfflineProcessing(false) {}
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002880
2881Camera3Device::HalInterface::HalInterface(const HalInterface& other) :
Yifan Hongf79b5542017-04-11 14:44:25 -07002882 mHidlSession(other.mHidlSession),
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08002883 mRequestMetadataQueue(other.mRequestMetadataQueue),
Yin-Chia Yehb978c382019-10-30 00:22:37 -07002884 mUseHalBufManager(other.mUseHalBufManager),
2885 mSupportOfflineProcessing(other.mSupportOfflineProcessing) {}
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002886
2887bool Camera3Device::HalInterface::valid() {
Emilian Peev31abd0a2017-05-11 18:37:46 +01002888 return (mHidlSession != nullptr);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002889}
2890
2891void Camera3Device::HalInterface::clear() {
Yin-Chia Yehb978c382019-10-30 00:22:37 -07002892 mHidlSession_3_6.clear();
Emilian Peev644a3e12018-11-23 13:52:39 +00002893 mHidlSession_3_5.clear();
Emilian Peev9e740b02018-01-30 18:28:03 +00002894 mHidlSession_3_4.clear();
2895 mHidlSession_3_3.clear();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002896 mHidlSession.clear();
2897}
2898
2899status_t Camera3Device::HalInterface::constructDefaultRequestSettings(
2900 camera3_request_template_t templateId,
2901 /*out*/ camera_metadata_t **requestTemplate) {
2902 ATRACE_NAME("CameraHal::constructDefaultRequestSettings");
2903 if (!valid()) return INVALID_OPERATION;
2904 status_t res = OK;
2905
Emilian Peev31abd0a2017-05-11 18:37:46 +01002906 common::V1_0::Status status;
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002907
2908 auto requestCallback = [&status, &requestTemplate]
Emilian Peev31abd0a2017-05-11 18:37:46 +01002909 (common::V1_0::Status s, const device::V3_2::CameraMetadata& request) {
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002910 status = s;
2911 if (status == common::V1_0::Status::OK) {
2912 const camera_metadata *r =
2913 reinterpret_cast<const camera_metadata_t*>(request.data());
2914 size_t expectedSize = request.size();
2915 int ret = validate_camera_metadata_structure(r, &expectedSize);
2916 if (ret == OK || ret == CAMERA_METADATA_VALIDATION_SHIFTED) {
2917 *requestTemplate = clone_camera_metadata(r);
2918 if (*requestTemplate == nullptr) {
2919 ALOGE("%s: Unable to clone camera metadata received from HAL",
2920 __FUNCTION__);
Emilian Peev31abd0a2017-05-11 18:37:46 +01002921 status = common::V1_0::Status::INTERNAL_ERROR;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002922 }
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002923 } else {
2924 ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
2925 status = common::V1_0::Status::INTERNAL_ERROR;
Emilian Peev31abd0a2017-05-11 18:37:46 +01002926 }
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002927 }
2928 };
2929 hardware::Return<void> err;
Eino-Ville Talvala96441462018-02-06 11:41:55 -08002930 RequestTemplate id;
2931 switch (templateId) {
2932 case CAMERA3_TEMPLATE_PREVIEW:
2933 id = RequestTemplate::PREVIEW;
2934 break;
2935 case CAMERA3_TEMPLATE_STILL_CAPTURE:
2936 id = RequestTemplate::STILL_CAPTURE;
2937 break;
2938 case CAMERA3_TEMPLATE_VIDEO_RECORD:
2939 id = RequestTemplate::VIDEO_RECORD;
2940 break;
2941 case CAMERA3_TEMPLATE_VIDEO_SNAPSHOT:
2942 id = RequestTemplate::VIDEO_SNAPSHOT;
2943 break;
2944 case CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG:
2945 id = RequestTemplate::ZERO_SHUTTER_LAG;
2946 break;
2947 case CAMERA3_TEMPLATE_MANUAL:
2948 id = RequestTemplate::MANUAL;
2949 break;
2950 default:
2951 // Unknown template ID, or this HAL is too old to support it
2952 return BAD_VALUE;
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002953 }
Eino-Ville Talvala96441462018-02-06 11:41:55 -08002954 err = mHidlSession->constructDefaultRequestSettings(id, requestCallback);
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002955
Emilian Peev31abd0a2017-05-11 18:37:46 +01002956 if (!err.isOk()) {
2957 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
2958 res = DEAD_OBJECT;
2959 } else {
2960 res = CameraProviderManager::mapToStatusT(status);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002961 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01002962
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002963 return res;
2964}
2965
Emilian Peev4ec17882019-01-24 17:16:58 -08002966bool Camera3Device::HalInterface::isReconfigurationRequired(CameraMetadata& oldSessionParams,
2967 CameraMetadata& newSessionParams) {
2968 // We do reconfiguration by default;
2969 bool ret = true;
2970 if ((mHidlSession_3_5 != nullptr) && mIsReconfigurationQuerySupported) {
2971 android::hardware::hidl_vec<uint8_t> oldParams, newParams;
2972 camera_metadata_t* oldSessioMeta = const_cast<camera_metadata_t*>(
2973 oldSessionParams.getAndLock());
2974 camera_metadata_t* newSessioMeta = const_cast<camera_metadata_t*>(
2975 newSessionParams.getAndLock());
2976 oldParams.setToExternal(reinterpret_cast<uint8_t*>(oldSessioMeta),
2977 get_camera_metadata_size(oldSessioMeta));
2978 newParams.setToExternal(reinterpret_cast<uint8_t*>(newSessioMeta),
2979 get_camera_metadata_size(newSessioMeta));
2980 hardware::camera::common::V1_0::Status callStatus;
2981 bool required;
2982 auto hidlCb = [&callStatus, &required] (hardware::camera::common::V1_0::Status s,
2983 bool requiredFlag) {
2984 callStatus = s;
2985 required = requiredFlag;
2986 };
2987 auto err = mHidlSession_3_5->isReconfigurationRequired(oldParams, newParams, hidlCb);
2988 oldSessionParams.unlock(oldSessioMeta);
2989 newSessionParams.unlock(newSessioMeta);
2990 if (err.isOk()) {
2991 switch (callStatus) {
2992 case hardware::camera::common::V1_0::Status::OK:
2993 ret = required;
2994 break;
2995 case hardware::camera::common::V1_0::Status::METHOD_NOT_SUPPORTED:
2996 mIsReconfigurationQuerySupported = false;
2997 ret = true;
2998 break;
2999 default:
3000 ALOGV("%s: Reconfiguration query failed: %d", __FUNCTION__, callStatus);
3001 ret = true;
3002 }
3003 } else {
3004 ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, err.description().c_str());
3005 ret = true;
3006 }
3007 }
3008
3009 return ret;
3010}
3011
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01003012status_t Camera3Device::HalInterface::configureStreams(const camera_metadata_t *sessionParams,
Emilian Peev192ee832018-01-31 14:46:47 +00003013 camera3_stream_configuration *config, const std::vector<uint32_t>& bufferSizes) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003014 ATRACE_NAME("CameraHal::configureStreams");
3015 if (!valid()) return INVALID_OPERATION;
3016 status_t res = OK;
3017
Emilian Peev31abd0a2017-05-11 18:37:46 +01003018 // Convert stream config to HIDL
3019 std::set<int> activeStreams;
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003020 device::V3_2::StreamConfiguration requestedConfiguration3_2;
3021 device::V3_4::StreamConfiguration requestedConfiguration3_4;
3022 requestedConfiguration3_2.streams.resize(config->num_streams);
3023 requestedConfiguration3_4.streams.resize(config->num_streams);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003024 for (size_t i = 0; i < config->num_streams; i++) {
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003025 device::V3_2::Stream &dst3_2 = requestedConfiguration3_2.streams[i];
3026 device::V3_4::Stream &dst3_4 = requestedConfiguration3_4.streams[i];
Emilian Peev31abd0a2017-05-11 18:37:46 +01003027 camera3_stream_t *src = config->streams[i];
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003028
Emilian Peev31abd0a2017-05-11 18:37:46 +01003029 Camera3Stream* cam3stream = Camera3Stream::cast(src);
3030 cam3stream->setBufferFreedListener(this);
3031 int streamId = cam3stream->getId();
3032 StreamType streamType;
3033 switch (src->stream_type) {
3034 case CAMERA3_STREAM_OUTPUT:
3035 streamType = StreamType::OUTPUT;
3036 break;
3037 case CAMERA3_STREAM_INPUT:
3038 streamType = StreamType::INPUT;
3039 break;
3040 default:
3041 ALOGE("%s: Stream %d: Unsupported stream type %d",
3042 __FUNCTION__, streamId, config->streams[i]->stream_type);
3043 return BAD_VALUE;
3044 }
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003045 dst3_2.id = streamId;
3046 dst3_2.streamType = streamType;
3047 dst3_2.width = src->width;
3048 dst3_2.height = src->height;
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003049 dst3_2.usage = mapToConsumerUsage(cam3stream->getUsage());
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003050 dst3_2.rotation = mapToStreamRotation((camera3_stream_rotation_t) src->rotation);
Shuzhen Wang92653952019-05-07 15:11:43 -07003051 // For HidlSession version 3.5 or newer, the format and dataSpace sent
3052 // to HAL are original, not the overriden ones.
3053 if (mHidlSession_3_5 != nullptr) {
3054 dst3_2.format = mapToPixelFormat(cam3stream->isFormatOverridden() ?
3055 cam3stream->getOriginalFormat() : src->format);
3056 dst3_2.dataSpace = mapToHidlDataspace(cam3stream->isDataSpaceOverridden() ?
3057 cam3stream->getOriginalDataSpace() : src->data_space);
3058 } else {
3059 dst3_2.format = mapToPixelFormat(src->format);
3060 dst3_2.dataSpace = mapToHidlDataspace(src->data_space);
3061 }
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003062 dst3_4.v3_2 = dst3_2;
Emilian Peev192ee832018-01-31 14:46:47 +00003063 dst3_4.bufferSize = bufferSizes[i];
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003064 if (src->physical_camera_id != nullptr) {
3065 dst3_4.physicalCameraId = src->physical_camera_id;
3066 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003067
3068 activeStreams.insert(streamId);
3069 // Create Buffer ID map if necessary
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003070 mBufferRecords.tryCreateBufferCache(streamId);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003071 }
3072 // remove BufferIdMap for deleted streams
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003073 mBufferRecords.removeInactiveBufferCaches(activeStreams);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003074
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003075 StreamConfigurationMode operationMode;
Emilian Peev31abd0a2017-05-11 18:37:46 +01003076 res = mapToStreamConfigurationMode(
3077 (camera3_stream_configuration_mode_t) config->operation_mode,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003078 /*out*/ &operationMode);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003079 if (res != OK) {
3080 return res;
3081 }
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003082 requestedConfiguration3_2.operationMode = operationMode;
3083 requestedConfiguration3_4.operationMode = operationMode;
3084 requestedConfiguration3_4.sessionParams.setToExternal(
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01003085 reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams)),
3086 get_camera_metadata_size(sessionParams));
3087
Emilian Peev31abd0a2017-05-11 18:37:46 +01003088 // Invoke configureStreams
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003089 device::V3_3::HalStreamConfiguration finalConfiguration;
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003090 device::V3_4::HalStreamConfiguration finalConfiguration3_4;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003091 device::V3_6::HalStreamConfiguration finalConfiguration3_6;
Emilian Peev31abd0a2017-05-11 18:37:46 +01003092 common::V1_0::Status status;
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003093
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003094 auto configStream34Cb = [&status, &finalConfiguration3_4]
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003095 (common::V1_0::Status s, const device::V3_4::HalStreamConfiguration& halConfiguration) {
3096 finalConfiguration3_4 = halConfiguration;
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01003097 status = s;
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003098 };
3099
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003100 auto configStream36Cb = [&status, &finalConfiguration3_6]
3101 (common::V1_0::Status s, const device::V3_6::HalStreamConfiguration& halConfiguration) {
3102 finalConfiguration3_6 = halConfiguration;
3103 status = s;
3104 };
3105
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003106 auto postprocConfigStream34 = [&finalConfiguration, &finalConfiguration3_4]
3107 (hardware::Return<void>& err) -> status_t {
3108 if (!err.isOk()) {
3109 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3110 return DEAD_OBJECT;
3111 }
3112 finalConfiguration.streams.resize(finalConfiguration3_4.streams.size());
3113 for (size_t i = 0; i < finalConfiguration3_4.streams.size(); i++) {
3114 finalConfiguration.streams[i] = finalConfiguration3_4.streams[i].v3_3;
3115 }
3116 return OK;
3117 };
3118
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003119 auto postprocConfigStream36 = [&finalConfiguration, &finalConfiguration3_6]
3120 (hardware::Return<void>& err) -> status_t {
3121 if (!err.isOk()) {
3122 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3123 return DEAD_OBJECT;
3124 }
3125 finalConfiguration.streams.resize(finalConfiguration3_6.streams.size());
3126 for (size_t i = 0; i < finalConfiguration3_6.streams.size(); i++) {
3127 finalConfiguration.streams[i] = finalConfiguration3_6.streams[i].v3_4.v3_3;
3128 }
3129 return OK;
3130 };
3131
Shuzhen Wang92653952019-05-07 15:11:43 -07003132 // See which version of HAL we have
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003133 if (mHidlSession_3_6 != nullptr) {
3134 ALOGV("%s: v3.6 device found", __FUNCTION__);
3135 device::V3_5::StreamConfiguration requestedConfiguration3_5;
3136 requestedConfiguration3_5.v3_4 = requestedConfiguration3_4;
3137 requestedConfiguration3_5.streamConfigCounter = mNextStreamConfigCounter++;
3138 auto err = mHidlSession_3_6->configureStreams_3_6(
3139 requestedConfiguration3_5, configStream36Cb);
3140 res = postprocConfigStream36(err);
3141 if (res != OK) {
3142 return res;
3143 }
3144 } else if (mHidlSession_3_5 != nullptr) {
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003145 ALOGV("%s: v3.5 device found", __FUNCTION__);
3146 device::V3_5::StreamConfiguration requestedConfiguration3_5;
3147 requestedConfiguration3_5.v3_4 = requestedConfiguration3_4;
3148 requestedConfiguration3_5.streamConfigCounter = mNextStreamConfigCounter++;
3149 auto err = mHidlSession_3_5->configureStreams_3_5(
3150 requestedConfiguration3_5, configStream34Cb);
3151 res = postprocConfigStream34(err);
3152 if (res != OK) {
3153 return res;
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01003154 }
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003155 } else if (mHidlSession_3_4 != nullptr) {
3156 // We do; use v3.4 for the call
3157 ALOGV("%s: v3.4 device found", __FUNCTION__);
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003158 auto err = mHidlSession_3_4->configureStreams_3_4(
3159 requestedConfiguration3_4, configStream34Cb);
3160 res = postprocConfigStream34(err);
3161 if (res != OK) {
3162 return res;
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003163 }
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08003164 } else if (mHidlSession_3_3 != nullptr) {
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003165 // We do; use v3.3 for the call
3166 ALOGV("%s: v3.3 device found", __FUNCTION__);
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08003167 auto err = mHidlSession_3_3->configureStreams_3_3(requestedConfiguration3_2,
Emilian Peev31abd0a2017-05-11 18:37:46 +01003168 [&status, &finalConfiguration]
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003169 (common::V1_0::Status s, const device::V3_3::HalStreamConfiguration& halConfiguration) {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003170 finalConfiguration = halConfiguration;
3171 status = s;
3172 });
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003173 if (!err.isOk()) {
3174 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3175 return DEAD_OBJECT;
3176 }
3177 } else {
3178 // We don't; use v3.2 call and construct a v3.3 HalStreamConfiguration
3179 ALOGV("%s: v3.2 device found", __FUNCTION__);
3180 HalStreamConfiguration finalConfiguration_3_2;
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003181 auto err = mHidlSession->configureStreams(requestedConfiguration3_2,
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003182 [&status, &finalConfiguration_3_2]
3183 (common::V1_0::Status s, const HalStreamConfiguration& halConfiguration) {
3184 finalConfiguration_3_2 = halConfiguration;
3185 status = s;
3186 });
3187 if (!err.isOk()) {
3188 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3189 return DEAD_OBJECT;
3190 }
3191 finalConfiguration.streams.resize(finalConfiguration_3_2.streams.size());
3192 for (size_t i = 0; i < finalConfiguration_3_2.streams.size(); i++) {
3193 finalConfiguration.streams[i].v3_2 = finalConfiguration_3_2.streams[i];
3194 finalConfiguration.streams[i].overrideDataSpace =
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003195 requestedConfiguration3_2.streams[i].dataSpace;
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003196 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003197 }
3198
3199 if (status != common::V1_0::Status::OK ) {
3200 return CameraProviderManager::mapToStatusT(status);
3201 }
3202
3203 // And convert output stream configuration from HIDL
3204
3205 for (size_t i = 0; i < config->num_streams; i++) {
3206 camera3_stream_t *dst = config->streams[i];
3207 int streamId = Camera3Stream::cast(dst)->getId();
3208
3209 // Start scan at i, with the assumption that the stream order matches
3210 size_t realIdx = i;
3211 bool found = false;
Eino-Ville Talvala370875f2019-04-12 12:40:27 -07003212 size_t halStreamCount = finalConfiguration.streams.size();
3213 for (size_t idx = 0; idx < halStreamCount; idx++) {
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003214 if (finalConfiguration.streams[realIdx].v3_2.id == streamId) {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003215 found = true;
3216 break;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003217 }
Eino-Ville Talvala370875f2019-04-12 12:40:27 -07003218 realIdx = (realIdx >= halStreamCount - 1) ? 0 : realIdx + 1;
Emilian Peev31abd0a2017-05-11 18:37:46 +01003219 }
3220 if (!found) {
3221 ALOGE("%s: Stream %d not found in stream configuration response from HAL",
3222 __FUNCTION__, streamId);
3223 return INVALID_OPERATION;
3224 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003225 device::V3_3::HalStream &src = finalConfiguration.streams[realIdx];
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003226 device::V3_6::HalStream &src_36 = finalConfiguration3_6.streams[realIdx];
Yin-Chia Yeh77327052017-01-09 18:23:07 -08003227
Emilian Peev710c1422017-08-30 11:19:38 +01003228 Camera3Stream* dstStream = Camera3Stream::cast(dst);
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003229 int overrideFormat = mapToFrameworkFormat(src.v3_2.overrideFormat);
3230 android_dataspace overrideDataSpace = mapToFrameworkDataspace(src.overrideDataSpace);
3231
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003232 if (mHidlSession_3_6 != nullptr) {
3233 dstStream->setOfflineProcessingSupport(src_36.supportOffline);
3234 }
3235
Yin-Chia Yeh90667662019-07-01 15:45:00 -07003236 if (dstStream->getOriginalFormat() != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
Shuzhen Wang92653952019-05-07 15:11:43 -07003237 dstStream->setFormatOverride(false);
3238 dstStream->setDataSpaceOverride(false);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003239 if (dst->format != overrideFormat) {
3240 ALOGE("%s: Stream %d: Format override not allowed for format 0x%x", __FUNCTION__,
3241 streamId, dst->format);
Yin-Chia Yeh77327052017-01-09 18:23:07 -08003242 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003243 if (dst->data_space != overrideDataSpace) {
3244 ALOGE("%s: Stream %d: DataSpace override not allowed for format 0x%x", __FUNCTION__,
3245 streamId, dst->format);
3246 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003247 } else {
Shuzhen Wang92653952019-05-07 15:11:43 -07003248 bool needFormatOverride =
3249 requestedConfiguration3_2.streams[i].format != src.v3_2.overrideFormat;
3250 bool needDataspaceOverride =
3251 requestedConfiguration3_2.streams[i].dataSpace != src.overrideDataSpace;
Emilian Peev31abd0a2017-05-11 18:37:46 +01003252 // Override allowed with IMPLEMENTATION_DEFINED
Shuzhen Wang92653952019-05-07 15:11:43 -07003253 dstStream->setFormatOverride(needFormatOverride);
3254 dstStream->setDataSpaceOverride(needDataspaceOverride);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003255 dst->format = overrideFormat;
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003256 dst->data_space = overrideDataSpace;
Yin-Chia Yeh77327052017-01-09 18:23:07 -08003257 }
3258
Emilian Peev31abd0a2017-05-11 18:37:46 +01003259 if (dst->stream_type == CAMERA3_STREAM_INPUT) {
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003260 if (src.v3_2.producerUsage != 0) {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003261 ALOGE("%s: Stream %d: INPUT streams must have 0 for producer usage",
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003262 __FUNCTION__, streamId);
3263 return INVALID_OPERATION;
3264 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003265 dstStream->setUsage(
3266 mapConsumerToFrameworkUsage(src.v3_2.consumerUsage));
Emilian Peev31abd0a2017-05-11 18:37:46 +01003267 } else {
3268 // OUTPUT
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003269 if (src.v3_2.consumerUsage != 0) {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003270 ALOGE("%s: Stream %d: OUTPUT streams must have 0 for consumer usage",
3271 __FUNCTION__, streamId);
3272 return INVALID_OPERATION;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003273 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003274 dstStream->setUsage(
3275 mapProducerToFrameworkUsage(src.v3_2.producerUsage));
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003276 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003277 dst->max_buffers = src.v3_2.maxBuffers;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003278 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003279
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003280 return res;
3281}
3282
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003283status_t Camera3Device::HalInterface::wrapAsHidlRequest(camera3_capture_request_t* request,
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003284 /*out*/device::V3_2::CaptureRequest* captureRequest,
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003285 /*out*/std::vector<native_handle_t*>* handlesCreated,
3286 /*out*/std::vector<std::pair<int32_t, int32_t>>* inflightBuffers) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003287 ATRACE_CALL();
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003288 if (captureRequest == nullptr || handlesCreated == nullptr || inflightBuffers == nullptr) {
3289 ALOGE("%s: captureRequest (%p), handlesCreated (%p), and inflightBuffers(%p) "
3290 "must not be null", __FUNCTION__, captureRequest, handlesCreated, inflightBuffers);
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003291 return BAD_VALUE;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003292 }
3293
3294 captureRequest->frameNumber = request->frame_number;
Yifan Hongf79b5542017-04-11 14:44:25 -07003295
3296 captureRequest->fmqSettingsSize = 0;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003297
3298 {
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003299 if (request->input_buffer != nullptr) {
3300 int32_t streamId = Camera3Stream::cast(request->input_buffer->stream)->getId();
3301 buffer_handle_t buf = *(request->input_buffer->buffer);
3302 auto pair = getBufferId(buf, streamId);
3303 bool isNewBuffer = pair.first;
3304 uint64_t bufferId = pair.second;
3305 captureRequest->inputBuffer.streamId = streamId;
3306 captureRequest->inputBuffer.bufferId = bufferId;
3307 captureRequest->inputBuffer.buffer = (isNewBuffer) ? buf : nullptr;
3308 captureRequest->inputBuffer.status = BufferStatus::OK;
3309 native_handle_t *acquireFence = nullptr;
3310 if (request->input_buffer->acquire_fence != -1) {
3311 acquireFence = native_handle_create(1,0);
3312 acquireFence->data[0] = request->input_buffer->acquire_fence;
3313 handlesCreated->push_back(acquireFence);
3314 }
3315 captureRequest->inputBuffer.acquireFence = acquireFence;
3316 captureRequest->inputBuffer.releaseFence = nullptr;
3317
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003318 mBufferRecords.pushInflightBuffer(captureRequest->frameNumber, streamId,
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003319 request->input_buffer->buffer);
3320 inflightBuffers->push_back(std::make_pair(captureRequest->frameNumber, streamId));
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003321 } else {
3322 captureRequest->inputBuffer.streamId = -1;
3323 captureRequest->inputBuffer.bufferId = BUFFER_ID_NO_BUFFER;
3324 }
3325
3326 captureRequest->outputBuffers.resize(request->num_output_buffers);
3327 for (size_t i = 0; i < request->num_output_buffers; i++) {
3328 const camera3_stream_buffer_t *src = request->output_buffers + i;
3329 StreamBuffer &dst = captureRequest->outputBuffers[i];
3330 int32_t streamId = Camera3Stream::cast(src->stream)->getId();
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003331 if (src->buffer != nullptr) {
3332 buffer_handle_t buf = *(src->buffer);
3333 auto pair = getBufferId(buf, streamId);
3334 bool isNewBuffer = pair.first;
3335 dst.bufferId = pair.second;
3336 dst.buffer = isNewBuffer ? buf : nullptr;
3337 native_handle_t *acquireFence = nullptr;
3338 if (src->acquire_fence != -1) {
3339 acquireFence = native_handle_create(1,0);
3340 acquireFence->data[0] = src->acquire_fence;
3341 handlesCreated->push_back(acquireFence);
3342 }
3343 dst.acquireFence = acquireFence;
3344 } else if (mUseHalBufManager) {
3345 // HAL buffer management path
3346 dst.bufferId = BUFFER_ID_NO_BUFFER;
3347 dst.buffer = nullptr;
3348 dst.acquireFence = nullptr;
3349 } else {
3350 ALOGE("%s: cannot send a null buffer in capture request!", __FUNCTION__);
3351 return BAD_VALUE;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003352 }
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003353 dst.streamId = streamId;
3354 dst.status = BufferStatus::OK;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003355 dst.releaseFence = nullptr;
3356
Yin-Chia Yeh5f840f82019-03-05 11:59:04 -08003357 // Output buffers are empty when using HAL buffer manager
3358 if (!mUseHalBufManager) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003359 mBufferRecords.pushInflightBuffer(
3360 captureRequest->frameNumber, streamId, src->buffer);
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003361 inflightBuffers->push_back(std::make_pair(captureRequest->frameNumber, streamId));
Yin-Chia Yeh5f840f82019-03-05 11:59:04 -08003362 }
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003363 }
3364 }
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003365 return OK;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003366}
3367
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003368void Camera3Device::HalInterface::cleanupNativeHandles(
3369 std::vector<native_handle_t*> *handles, bool closeFd) {
3370 if (handles == nullptr) {
3371 return;
3372 }
3373 if (closeFd) {
3374 for (auto& handle : *handles) {
3375 native_handle_close(handle);
3376 }
3377 }
3378 for (auto& handle : *handles) {
3379 native_handle_delete(handle);
3380 }
3381 handles->clear();
3382 return;
3383}
3384
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003385status_t Camera3Device::HalInterface::processBatchCaptureRequests(
3386 std::vector<camera3_capture_request_t*>& requests,/*out*/uint32_t* numRequestProcessed) {
3387 ATRACE_NAME("CameraHal::processBatchCaptureRequests");
3388 if (!valid()) return INVALID_OPERATION;
3389
Emilian Peevaebbe412018-01-15 13:53:24 +00003390 sp<device::V3_4::ICameraDeviceSession> hidlSession_3_4;
3391 auto castResult_3_4 = device::V3_4::ICameraDeviceSession::castFrom(mHidlSession);
3392 if (castResult_3_4.isOk()) {
3393 hidlSession_3_4 = castResult_3_4;
3394 }
3395
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003396 hardware::hidl_vec<device::V3_2::CaptureRequest> captureRequests;
Emilian Peevaebbe412018-01-15 13:53:24 +00003397 hardware::hidl_vec<device::V3_4::CaptureRequest> captureRequests_3_4;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003398 size_t batchSize = requests.size();
Emilian Peevaebbe412018-01-15 13:53:24 +00003399 if (hidlSession_3_4 != nullptr) {
3400 captureRequests_3_4.resize(batchSize);
3401 } else {
3402 captureRequests.resize(batchSize);
3403 }
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003404 std::vector<native_handle_t*> handlesCreated;
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003405 std::vector<std::pair<int32_t, int32_t>> inflightBuffers;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003406
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003407 status_t res = OK;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003408 for (size_t i = 0; i < batchSize; i++) {
Emilian Peevaebbe412018-01-15 13:53:24 +00003409 if (hidlSession_3_4 != nullptr) {
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003410 res = wrapAsHidlRequest(requests[i], /*out*/&captureRequests_3_4[i].v3_2,
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003411 /*out*/&handlesCreated, /*out*/&inflightBuffers);
Emilian Peevaebbe412018-01-15 13:53:24 +00003412 } else {
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003413 res = wrapAsHidlRequest(requests[i], /*out*/&captureRequests[i],
3414 /*out*/&handlesCreated, /*out*/&inflightBuffers);
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003415 }
3416 if (res != OK) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003417 mBufferRecords.popInflightBuffers(inflightBuffers);
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003418 cleanupNativeHandles(&handlesCreated);
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003419 return res;
Emilian Peevaebbe412018-01-15 13:53:24 +00003420 }
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003421 }
3422
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003423 std::vector<device::V3_2::BufferCache> cachesToRemove;
3424 {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003425 std::lock_guard<std::mutex> lock(mFreedBuffersLock);
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003426 for (auto& pair : mFreedBuffers) {
3427 // The stream might have been removed since onBufferFreed
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003428 if (mBufferRecords.isStreamCached(pair.first)) {
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003429 cachesToRemove.push_back({pair.first, pair.second});
3430 }
3431 }
3432 mFreedBuffers.clear();
3433 }
3434
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003435 common::V1_0::Status status = common::V1_0::Status::INTERNAL_ERROR;
3436 *numRequestProcessed = 0;
Yifan Hongf79b5542017-04-11 14:44:25 -07003437
3438 // Write metadata to FMQ.
3439 for (size_t i = 0; i < batchSize; i++) {
3440 camera3_capture_request_t* request = requests[i];
Emilian Peevaebbe412018-01-15 13:53:24 +00003441 device::V3_2::CaptureRequest* captureRequest;
3442 if (hidlSession_3_4 != nullptr) {
3443 captureRequest = &captureRequests_3_4[i].v3_2;
3444 } else {
3445 captureRequest = &captureRequests[i];
3446 }
Yifan Hongf79b5542017-04-11 14:44:25 -07003447
3448 if (request->settings != nullptr) {
3449 size_t settingsSize = get_camera_metadata_size(request->settings);
3450 if (mRequestMetadataQueue != nullptr && mRequestMetadataQueue->write(
3451 reinterpret_cast<const uint8_t*>(request->settings), settingsSize)) {
3452 captureRequest->settings.resize(0);
3453 captureRequest->fmqSettingsSize = settingsSize;
3454 } else {
3455 if (mRequestMetadataQueue != nullptr) {
3456 ALOGW("%s: couldn't utilize fmq, fallback to hwbinder", __FUNCTION__);
3457 }
3458 captureRequest->settings.setToExternal(
3459 reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(request->settings)),
3460 get_camera_metadata_size(request->settings));
3461 captureRequest->fmqSettingsSize = 0u;
3462 }
3463 } else {
3464 // A null request settings maps to a size-0 CameraMetadata
3465 captureRequest->settings.resize(0);
3466 captureRequest->fmqSettingsSize = 0u;
3467 }
Emilian Peevaebbe412018-01-15 13:53:24 +00003468
3469 if (hidlSession_3_4 != nullptr) {
3470 captureRequests_3_4[i].physicalCameraSettings.resize(request->num_physcam_settings);
3471 for (size_t j = 0; j < request->num_physcam_settings; j++) {
Emilian Peev00420d22018-02-05 21:33:13 +00003472 if (request->physcam_settings != nullptr) {
3473 size_t settingsSize = get_camera_metadata_size(request->physcam_settings[j]);
3474 if (mRequestMetadataQueue != nullptr && mRequestMetadataQueue->write(
3475 reinterpret_cast<const uint8_t*>(request->physcam_settings[j]),
3476 settingsSize)) {
3477 captureRequests_3_4[i].physicalCameraSettings[j].settings.resize(0);
3478 captureRequests_3_4[i].physicalCameraSettings[j].fmqSettingsSize =
3479 settingsSize;
3480 } else {
3481 if (mRequestMetadataQueue != nullptr) {
3482 ALOGW("%s: couldn't utilize fmq, fallback to hwbinder", __FUNCTION__);
3483 }
3484 captureRequests_3_4[i].physicalCameraSettings[j].settings.setToExternal(
3485 reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(
3486 request->physcam_settings[j])),
3487 get_camera_metadata_size(request->physcam_settings[j]));
3488 captureRequests_3_4[i].physicalCameraSettings[j].fmqSettingsSize = 0u;
Emilian Peevaebbe412018-01-15 13:53:24 +00003489 }
Emilian Peev00420d22018-02-05 21:33:13 +00003490 } else {
Emilian Peevaebbe412018-01-15 13:53:24 +00003491 captureRequests_3_4[i].physicalCameraSettings[j].fmqSettingsSize = 0u;
Emilian Peev00420d22018-02-05 21:33:13 +00003492 captureRequests_3_4[i].physicalCameraSettings[j].settings.resize(0);
Emilian Peevaebbe412018-01-15 13:53:24 +00003493 }
3494 captureRequests_3_4[i].physicalCameraSettings[j].physicalCameraId =
3495 request->physcam_id[j];
3496 }
3497 }
Yifan Hongf79b5542017-04-11 14:44:25 -07003498 }
Emilian Peevaebbe412018-01-15 13:53:24 +00003499
3500 hardware::details::return_status err;
Jayant Chowdharyc8d581e2018-07-16 14:46:23 -07003501 auto resultCallback =
3502 [&status, &numRequestProcessed] (auto s, uint32_t n) {
3503 status = s;
3504 *numRequestProcessed = n;
3505 };
Emilian Peevaebbe412018-01-15 13:53:24 +00003506 if (hidlSession_3_4 != nullptr) {
3507 err = hidlSession_3_4->processCaptureRequest_3_4(captureRequests_3_4, cachesToRemove,
Jayant Chowdharyc8d581e2018-07-16 14:46:23 -07003508 resultCallback);
Emilian Peevaebbe412018-01-15 13:53:24 +00003509 } else {
3510 err = mHidlSession->processCaptureRequest(captureRequests, cachesToRemove,
Jayant Chowdharyc8d581e2018-07-16 14:46:23 -07003511 resultCallback);
Emilian Peevaebbe412018-01-15 13:53:24 +00003512 }
Eino-Ville Talvalac5cbb872017-04-27 12:48:33 -07003513 if (!err.isOk()) {
3514 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003515 status = common::V1_0::Status::CAMERA_DISCONNECTED;
Eino-Ville Talvalac5cbb872017-04-27 12:48:33 -07003516 }
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003517
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003518 if (status == common::V1_0::Status::OK && *numRequestProcessed != batchSize) {
3519 ALOGE("%s: processCaptureRequest returns OK but processed %d/%zu requests",
3520 __FUNCTION__, *numRequestProcessed, batchSize);
3521 status = common::V1_0::Status::INTERNAL_ERROR;
3522 }
3523
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003524 res = CameraProviderManager::mapToStatusT(status);
3525 if (res == OK) {
3526 if (mHidlSession->isRemote()) {
3527 // Only close acquire fence FDs when the HIDL transaction succeeds (so the FDs have been
3528 // sent to camera HAL processes)
3529 cleanupNativeHandles(&handlesCreated, /*closeFd*/true);
3530 } else {
3531 // In passthrough mode the FDs are now owned by HAL
3532 cleanupNativeHandles(&handlesCreated);
3533 }
3534 } else {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003535 mBufferRecords.popInflightBuffers(inflightBuffers);
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003536 cleanupNativeHandles(&handlesCreated);
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003537 }
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003538 return res;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003539}
3540
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003541status_t Camera3Device::HalInterface::flush() {
3542 ATRACE_NAME("CameraHal::flush");
3543 if (!valid()) return INVALID_OPERATION;
3544 status_t res = OK;
3545
Emilian Peev31abd0a2017-05-11 18:37:46 +01003546 auto err = mHidlSession->flush();
3547 if (!err.isOk()) {
3548 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3549 res = DEAD_OBJECT;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003550 } else {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003551 res = CameraProviderManager::mapToStatusT(err);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003552 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003553
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003554 return res;
3555}
3556
Emilian Peev31abd0a2017-05-11 18:37:46 +01003557status_t Camera3Device::HalInterface::dump(int /*fd*/) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003558 ATRACE_NAME("CameraHal::dump");
3559 if (!valid()) return INVALID_OPERATION;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003560
Emilian Peev31abd0a2017-05-11 18:37:46 +01003561 // Handled by CameraProviderManager::dump
3562
3563 return OK;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003564}
3565
3566status_t Camera3Device::HalInterface::close() {
3567 ATRACE_NAME("CameraHal::close()");
3568 if (!valid()) return INVALID_OPERATION;
3569 status_t res = OK;
3570
Emilian Peev31abd0a2017-05-11 18:37:46 +01003571 auto err = mHidlSession->close();
3572 // Interface will be dead shortly anyway, so don't log errors
3573 if (!err.isOk()) {
3574 res = DEAD_OBJECT;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003575 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003576
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003577 return res;
3578}
3579
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003580void Camera3Device::HalInterface::signalPipelineDrain(const std::vector<int>& streamIds) {
3581 ATRACE_NAME("CameraHal::signalPipelineDrain");
3582 if (!valid() || mHidlSession_3_5 == nullptr) {
3583 ALOGE("%s called on invalid camera!", __FUNCTION__);
3584 return;
3585 }
3586
Yin-Chia Yehc300a072019-02-13 14:56:57 -08003587 auto err = mHidlSession_3_5->signalStreamFlush(streamIds, mNextStreamConfigCounter - 1);
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003588 if (!err.isOk()) {
3589 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3590 return;
3591 }
3592}
3593
Yin-Chia Yehb978c382019-10-30 00:22:37 -07003594status_t Camera3Device::HalInterface::switchToOffline(
3595 const std::vector<int32_t>& streamsToKeep,
3596 /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003597 /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
3598 /*out*/camera3::BufferRecords* bufferRecords) {
Yin-Chia Yehb978c382019-10-30 00:22:37 -07003599 ATRACE_NAME("CameraHal::switchToOffline");
3600 if (!valid() || mHidlSession_3_6 == nullptr) {
3601 ALOGE("%s called on invalid camera!", __FUNCTION__);
3602 return INVALID_OPERATION;
3603 }
3604
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003605 if (offlineSessionInfo == nullptr || offlineSession == nullptr || bufferRecords == nullptr) {
3606 ALOGE("%s: output arguments must not be null!", __FUNCTION__);
Yin-Chia Yehb978c382019-10-30 00:22:37 -07003607 return INVALID_OPERATION;
3608 }
3609
3610 common::V1_0::Status status = common::V1_0::Status::INTERNAL_ERROR;
Yin-Chia Yehb978c382019-10-30 00:22:37 -07003611 auto resultCallback =
3612 [&status, &offlineSessionInfo, &offlineSession] (auto s, auto info, auto session) {
3613 status = s;
3614 *offlineSessionInfo = info;
3615 *offlineSession = session;
3616 };
3617 auto err = mHidlSession_3_6->switchToOffline(streamsToKeep, resultCallback);
3618
3619 if (!err.isOk()) {
3620 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3621 return DEAD_OBJECT;
3622 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003623
3624 status_t ret = CameraProviderManager::mapToStatusT(status);
3625 if (ret != OK) {
3626 return ret;
3627 }
3628
3629 // TODO: assert no ongoing requestBuffer/returnBuffer call here
3630 // TODO: update RequestBufferStateMachine to block requestBuffer/returnBuffer once HAL
3631 // returns from switchToOffline.
3632
3633
3634 // Validate buffer caches
3635 std::vector<int32_t> streams;
3636 streams.reserve(offlineSessionInfo->offlineStreams.size());
3637 for (auto offlineStream : offlineSessionInfo->offlineStreams) {
3638 int32_t id = offlineStream.id;
3639 streams.push_back(id);
3640 // Verify buffer caches
3641 std::vector<uint64_t> bufIds(offlineStream.circulatingBufferIds.begin(),
3642 offlineStream.circulatingBufferIds.end());
3643 if (!verifyBufferIds(id, bufIds)) {
3644 ALOGE("%s: stream ID %d buffer cache records mismatch!", __FUNCTION__, id);
3645 return UNKNOWN_ERROR;
3646 }
3647 }
3648
3649 // Move buffer records
3650 bufferRecords->takeBufferCaches(mBufferRecords, streams);
3651 bufferRecords->takeInflightBufferMap(mBufferRecords);
3652 bufferRecords->takeRequestedBufferMap(mBufferRecords);
3653 return ret;
Yin-Chia Yehb978c382019-10-30 00:22:37 -07003654}
3655
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07003656void Camera3Device::HalInterface::getInflightBufferKeys(
3657 std::vector<std::pair<int32_t, int32_t>>* out) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003658 mBufferRecords.getInflightBufferKeys(out);
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07003659 return;
3660}
3661
Yin-Chia Yeh84be5782019-03-01 11:47:02 -08003662void Camera3Device::HalInterface::getInflightRequestBufferKeys(
3663 std::vector<uint64_t>* out) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003664 mBufferRecords.getInflightRequestBufferKeys(out);
Yin-Chia Yeh84be5782019-03-01 11:47:02 -08003665 return;
3666}
3667
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003668bool Camera3Device::HalInterface::verifyBufferIds(
3669 int32_t streamId, std::vector<uint64_t>& bufIds) {
3670 return mBufferRecords.verifyBufferIds(streamId, bufIds);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003671}
3672
3673status_t Camera3Device::HalInterface::popInflightBuffer(
Yin-Chia Yehf4650602017-01-10 13:13:39 -08003674 int32_t frameNumber, int32_t streamId,
3675 /*out*/ buffer_handle_t **buffer) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003676 return mBufferRecords.popInflightBuffer(frameNumber, streamId, buffer);
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003677}
3678
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07003679status_t Camera3Device::HalInterface::pushInflightRequestBuffer(
Yin-Chia Yeh84be5782019-03-01 11:47:02 -08003680 uint64_t bufferId, buffer_handle_t* buf, int32_t streamId) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003681 return mBufferRecords.pushInflightRequestBuffer(bufferId, buf, streamId);
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07003682}
3683
3684// Find and pop a buffer_handle_t based on bufferId
3685status_t Camera3Device::HalInterface::popInflightRequestBuffer(
Yin-Chia Yeh84be5782019-03-01 11:47:02 -08003686 uint64_t bufferId,
3687 /*out*/ buffer_handle_t** buffer,
3688 /*optional out*/ int32_t* streamId) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003689 return mBufferRecords.popInflightRequestBuffer(bufferId, buffer, streamId);
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07003690}
3691
Yin-Chia Yeh77327052017-01-09 18:23:07 -08003692std::pair<bool, uint64_t> Camera3Device::HalInterface::getBufferId(
3693 const buffer_handle_t& buf, int streamId) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003694 return mBufferRecords.getBufferId(buf, streamId);
Yin-Chia Yeh77327052017-01-09 18:23:07 -08003695}
3696
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003697void Camera3Device::HalInterface::onBufferFreed(
3698 int streamId, const native_handle_t* handle) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003699 uint32_t bufferId = mBufferRecords.removeOneBufferCache(streamId, handle);
3700 std::lock_guard<std::mutex> lock(mFreedBuffersLock);
3701 if (bufferId != BUFFER_ID_NO_BUFFER) {
3702 mFreedBuffers.push_back(std::make_pair(streamId, bufferId));
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003703 }
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003704}
3705
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07003706void Camera3Device::HalInterface::onStreamReConfigured(int streamId) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003707 std::vector<uint64_t> bufIds = mBufferRecords.clearBufferCaches(streamId);
3708 std::lock_guard<std::mutex> lock(mFreedBuffersLock);
3709 for (auto bufferId : bufIds) {
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07003710 mFreedBuffers.push_back(std::make_pair(streamId, bufferId));
3711 }
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07003712}
3713
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003714/**
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003715 * RequestThread inner class methods
3716 */
3717
3718Camera3Device::RequestThread::RequestThread(wp<Camera3Device> parent,
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07003719 sp<StatusTracker> statusTracker,
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07003720 sp<HalInterface> interface, const Vector<int32_t>& sessionParamKeys,
3721 bool useHalBufManager) :
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07003722 Thread(/*canCallJava*/false),
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003723 mParent(parent),
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07003724 mStatusTracker(statusTracker),
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003725 mInterface(interface),
Eino-Ville Talvala77c1a352016-06-13 12:32:43 -07003726 mListener(nullptr),
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07003727 mId(getId(parent)),
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003728 mReconfigured(false),
3729 mDoPause(false),
3730 mPaused(true),
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003731 mNotifyPipelineDrain(false),
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003732 mFrameNumber(0),
Jianing Weicb0652e2014-03-12 18:29:36 -07003733 mLatestRequestId(NAME_NOT_FOUND),
Yin-Chia Yehc00a25c2014-08-21 14:27:44 -07003734 mCurrentAfTriggerId(0),
3735 mCurrentPreCaptureTriggerId(0),
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08003736 mRotateAndCropOverride(ANDROID_SCALER_ROTATE_AND_CROP_NONE),
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003737 mRepeatingLastFrameNumber(
3738 hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES),
Shuzhen Wang686f6442017-06-20 16:16:04 -07003739 mPrepareVideoStream(false),
Emilian Peeva14b4dd2018-05-15 11:00:31 +01003740 mConstrainedMode(false),
Emilian Peevac3ce6c2017-12-12 15:27:02 +00003741 mRequestLatency(kRequestLatencyBinSize),
3742 mSessionParamKeys(sessionParamKeys),
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07003743 mLatestSessionParams(sessionParamKeys.size()),
3744 mUseHalBufManager(useHalBufManager) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07003745 mStatusId = statusTracker->addComponent();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003746}
3747
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003748Camera3Device::RequestThread::~RequestThread() {}
3749
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07003750void Camera3Device::RequestThread::setNotificationListener(
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07003751 wp<NotificationListener> listener) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003752 ATRACE_CALL();
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003753 Mutex::Autolock l(mRequestLock);
3754 mListener = listener;
3755}
3756
Emilian Peevac3ce6c2017-12-12 15:27:02 +00003757void Camera3Device::RequestThread::configurationComplete(bool isConstrainedHighSpeed,
3758 const CameraMetadata& sessionParams) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003759 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003760 Mutex::Autolock l(mRequestLock);
3761 mReconfigured = true;
Emilian Peevac3ce6c2017-12-12 15:27:02 +00003762 mLatestSessionParams = sessionParams;
Chien-Yu Chenc66969b2016-05-19 16:37:51 -07003763 // Prepare video stream for high speed recording.
3764 mPrepareVideoStream = isConstrainedHighSpeed;
Emilian Peeva14b4dd2018-05-15 11:00:31 +01003765 mConstrainedMode = isConstrainedHighSpeed;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003766}
3767
Jianing Wei90e59c92014-03-12 18:29:36 -07003768status_t Camera3Device::RequestThread::queueRequestList(
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003769 List<sp<CaptureRequest> > &requests,
3770 /*out*/
3771 int64_t *lastFrameNumber) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003772 ATRACE_CALL();
Jianing Wei90e59c92014-03-12 18:29:36 -07003773 Mutex::Autolock l(mRequestLock);
3774 for (List<sp<CaptureRequest> >::iterator it = requests.begin(); it != requests.end();
3775 ++it) {
3776 mRequestQueue.push_back(*it);
3777 }
3778
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003779 if (lastFrameNumber != NULL) {
3780 *lastFrameNumber = mFrameNumber + mRequestQueue.size() - 1;
3781 ALOGV("%s: requestId %d, mFrameNumber %" PRId32 ", lastFrameNumber %" PRId64 ".",
3782 __FUNCTION__, (*(requests.begin()))->mResultExtras.requestId, mFrameNumber,
3783 *lastFrameNumber);
3784 }
Jianing Weicb0652e2014-03-12 18:29:36 -07003785
Jianing Wei90e59c92014-03-12 18:29:36 -07003786 unpauseForNewRequests();
3787
3788 return OK;
3789}
3790
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003791
3792status_t Camera3Device::RequestThread::queueTrigger(
3793 RequestTrigger trigger[],
3794 size_t count) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003795 ATRACE_CALL();
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003796 Mutex::Autolock l(mTriggerMutex);
3797 status_t ret;
3798
3799 for (size_t i = 0; i < count; ++i) {
3800 ret = queueTriggerLocked(trigger[i]);
3801
3802 if (ret != OK) {
3803 return ret;
3804 }
3805 }
3806
3807 return OK;
3808}
3809
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003810const String8& Camera3Device::RequestThread::getId(const wp<Camera3Device> &device) {
3811 static String8 deadId("<DeadDevice>");
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07003812 sp<Camera3Device> d = device.promote();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003813 if (d != nullptr) return d->mId;
3814 return deadId;
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07003815}
3816
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003817status_t Camera3Device::RequestThread::queueTriggerLocked(
3818 RequestTrigger trigger) {
3819
3820 uint32_t tag = trigger.metadataTag;
3821 ssize_t index = mTriggerMap.indexOfKey(tag);
3822
3823 switch (trigger.getTagType()) {
3824 case TYPE_BYTE:
3825 // fall-through
3826 case TYPE_INT32:
3827 break;
3828 default:
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07003829 ALOGE("%s: Type not supported: 0x%x", __FUNCTION__,
3830 trigger.getTagType());
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003831 return INVALID_OPERATION;
3832 }
3833
3834 /**
3835 * Collect only the latest trigger, since we only have 1 field
3836 * in the request settings per trigger tag, and can't send more than 1
3837 * trigger per request.
3838 */
3839 if (index != NAME_NOT_FOUND) {
3840 mTriggerMap.editValueAt(index) = trigger;
3841 } else {
3842 mTriggerMap.add(tag, trigger);
3843 }
3844
3845 return OK;
3846}
3847
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003848status_t Camera3Device::RequestThread::setRepeatingRequests(
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003849 const RequestList &requests,
3850 /*out*/
3851 int64_t *lastFrameNumber) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003852 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003853 Mutex::Autolock l(mRequestLock);
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003854 if (lastFrameNumber != NULL) {
3855 *lastFrameNumber = mRepeatingLastFrameNumber;
3856 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003857 mRepeatingRequests.clear();
3858 mRepeatingRequests.insert(mRepeatingRequests.begin(),
3859 requests.begin(), requests.end());
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07003860
3861 unpauseForNewRequests();
3862
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003863 mRepeatingLastFrameNumber = hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003864 return OK;
3865}
3866
Chih-Hung Hsieh8b0b9712016-08-09 14:25:53 -07003867bool Camera3Device::RequestThread::isRepeatingRequestLocked(const sp<CaptureRequest>& requestIn) {
Yin-Chia Yeh8684b7f2014-06-13 14:53:05 -07003868 if (mRepeatingRequests.empty()) {
3869 return false;
3870 }
3871 int32_t requestId = requestIn->mResultExtras.requestId;
3872 const RequestList &repeatRequests = mRepeatingRequests;
3873 // All repeating requests are guaranteed to have same id so only check first quest
3874 const sp<CaptureRequest> firstRequest = *repeatRequests.begin();
3875 return (firstRequest->mResultExtras.requestId == requestId);
3876}
3877
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003878status_t Camera3Device::RequestThread::clearRepeatingRequests(/*out*/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);
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07003881 return clearRepeatingRequestsLocked(lastFrameNumber);
3882
3883}
3884
3885status_t Camera3Device::RequestThread::clearRepeatingRequestsLocked(/*out*/int64_t *lastFrameNumber) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003886 mRepeatingRequests.clear();
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003887 if (lastFrameNumber != NULL) {
3888 *lastFrameNumber = mRepeatingLastFrameNumber;
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
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003894status_t Camera3Device::RequestThread::clear(
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003895 /*out*/int64_t *lastFrameNumber) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003896 ATRACE_CALL();
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07003897 Mutex::Autolock l(mRequestLock);
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003898 ALOGV("RequestThread::%s:", __FUNCTION__);
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003899
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07003900 mRepeatingRequests.clear();
Yin-Chia Yeh8684b7f2014-06-13 14:53:05 -07003901
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003902 // Send errors for all requests pending in the request queue, including
3903 // pending repeating requests
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07003904 sp<NotificationListener> listener = mListener.promote();
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003905 if (listener != NULL) {
3906 for (RequestList::iterator it = mRequestQueue.begin();
3907 it != mRequestQueue.end(); ++it) {
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07003908 // Abort the input buffers for reprocess requests.
3909 if ((*it)->mInputStream != NULL) {
3910 camera3_stream_buffer_t inputBuffer;
Eino-Ville Talvalaba435252017-06-21 16:07:25 -07003911 status_t res = (*it)->mInputStream->getInputBuffer(&inputBuffer,
3912 /*respectHalLimit*/ false);
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07003913 if (res != OK) {
3914 ALOGW("%s: %d: couldn't get input buffer while clearing the request "
3915 "list: %s (%d)", __FUNCTION__, __LINE__, strerror(-res), res);
3916 } else {
Shuzhen Wang0cf01cb2019-09-05 13:33:06 -07003917 inputBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07003918 res = (*it)->mInputStream->returnInputBuffer(inputBuffer);
3919 if (res != OK) {
3920 ALOGE("%s: %d: couldn't return input buffer while clearing the request "
3921 "list: %s (%d)", __FUNCTION__, __LINE__, strerror(-res), res);
3922 }
3923 }
3924 }
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003925 // Set the frame number this request would have had, if it
3926 // had been submitted; this frame number will not be reused.
3927 // The requestId and burstId fields were set when the request was
3928 // submitted originally (in convertMetadataListToRequestListLocked)
3929 (*it)->mResultExtras.frameNumber = mFrameNumber++;
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003930 listener->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003931 (*it)->mResultExtras);
Yin-Chia Yeh8684b7f2014-06-13 14:53:05 -07003932 }
3933 }
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07003934 mRequestQueue.clear();
Jinguang Dongb26e7a02016-11-14 16:04:02 +08003935
3936 Mutex::Autolock al(mTriggerMutex);
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07003937 mTriggerMap.clear();
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003938 if (lastFrameNumber != NULL) {
3939 *lastFrameNumber = mRepeatingLastFrameNumber;
3940 }
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003941 mRepeatingLastFrameNumber = hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES;
Emilian Peev8dae54c2019-12-02 15:17:17 -08003942 mRequestSignal.signal();
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07003943 return OK;
3944}
3945
Chien-Yu Chen85a64552015-08-28 15:46:12 -07003946status_t Camera3Device::RequestThread::flush() {
3947 ATRACE_CALL();
3948 Mutex::Autolock l(mFlushLock);
3949
Emilian Peev08dd2452017-04-06 16:55:14 +01003950 return mInterface->flush();
Chien-Yu Chen85a64552015-08-28 15:46:12 -07003951}
3952
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003953void Camera3Device::RequestThread::setPaused(bool paused) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003954 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003955 Mutex::Autolock l(mPauseLock);
3956 mDoPause = paused;
3957 mDoPauseSignal.signal();
3958}
3959
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003960status_t Camera3Device::RequestThread::waitUntilRequestProcessed(
3961 int32_t requestId, nsecs_t timeout) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003962 ATRACE_CALL();
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003963 Mutex::Autolock l(mLatestRequestMutex);
3964 status_t res;
3965 while (mLatestRequestId != requestId) {
3966 nsecs_t startTime = systemTime();
3967
3968 res = mLatestRequestSignal.waitRelative(mLatestRequestMutex, timeout);
3969 if (res != OK) return res;
3970
3971 timeout -= (systemTime() - startTime);
3972 }
3973
3974 return OK;
3975}
3976
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07003977void Camera3Device::RequestThread::requestExit() {
3978 // Call parent to set up shutdown
3979 Thread::requestExit();
3980 // The exit from any possible waits
3981 mDoPauseSignal.signal();
3982 mRequestSignal.signal();
Shuzhen Wang686f6442017-06-20 16:16:04 -07003983
3984 mRequestLatency.log("ProcessCaptureRequest latency histogram");
3985 mRequestLatency.reset();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07003986}
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003987
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07003988void Camera3Device::RequestThread::checkAndStopRepeatingRequest() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003989 ATRACE_CALL();
Yin-Chia Yeh473fad92016-05-23 15:54:41 -07003990 bool surfaceAbandoned = false;
3991 int64_t lastFrameNumber = 0;
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07003992 sp<NotificationListener> listener;
Yin-Chia Yeh473fad92016-05-23 15:54:41 -07003993 {
3994 Mutex::Autolock l(mRequestLock);
3995 // Check all streams needed by repeating requests are still valid. Otherwise, stop
3996 // repeating requests.
3997 for (const auto& request : mRepeatingRequests) {
3998 for (const auto& s : request->mOutputStreams) {
3999 if (s->isAbandoned()) {
4000 surfaceAbandoned = true;
4001 clearRepeatingRequestsLocked(&lastFrameNumber);
4002 break;
4003 }
4004 }
4005 if (surfaceAbandoned) {
4006 break;
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07004007 }
4008 }
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07004009 listener = mListener.promote();
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07004010 }
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07004011
4012 if (listener != NULL && surfaceAbandoned) {
4013 listener->notifyRepeatingRequestError(lastFrameNumber);
Yin-Chia Yeh473fad92016-05-23 15:54:41 -07004014 }
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07004015}
4016
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004017bool Camera3Device::RequestThread::sendRequestsBatch() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004018 ATRACE_CALL();
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004019 status_t res;
4020 size_t batchSize = mNextRequests.size();
4021 std::vector<camera3_capture_request_t*> requests(batchSize);
4022 uint32_t numRequestProcessed = 0;
4023 for (size_t i = 0; i < batchSize; i++) {
4024 requests[i] = &mNextRequests.editItemAt(i).halRequest;
Yin-Chia Yeh885691c2018-05-01 15:54:24 -07004025 ATRACE_ASYNC_BEGIN("frame capture", mNextRequests[i].halRequest.frame_number);
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004026 }
4027
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004028 res = mInterface->processBatchCaptureRequests(requests, &numRequestProcessed);
4029
4030 bool triggerRemoveFailed = false;
4031 NextRequest& triggerFailedRequest = mNextRequests.editItemAt(0);
4032 for (size_t i = 0; i < numRequestProcessed; i++) {
4033 NextRequest& nextRequest = mNextRequests.editItemAt(i);
4034 nextRequest.submitted = true;
4035
Shuzhen Wangc2cba122018-05-17 18:10:24 -07004036 updateNextRequest(nextRequest);
Emilian Peevaebbe412018-01-15 13:53:24 +00004037
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004038 if (!triggerRemoveFailed) {
4039 // Remove any previously queued triggers (after unlock)
4040 status_t removeTriggerRes = removeTriggers(mPrevRequest);
4041 if (removeTriggerRes != OK) {
4042 triggerRemoveFailed = true;
4043 triggerFailedRequest = nextRequest;
4044 }
4045 }
4046 }
4047
4048 if (triggerRemoveFailed) {
4049 SET_ERR("RequestThread: Unable to remove triggers "
4050 "(capture request %d, HAL device: %s (%d)",
4051 triggerFailedRequest.halRequest.frame_number, strerror(-res), res);
4052 cleanUpFailedRequests(/*sendRequestError*/ false);
4053 return false;
4054 }
4055
4056 if (res != OK) {
4057 // Should only get a failure here for malformed requests or device-level
4058 // errors, so consider all errors fatal. Bad metadata failures should
4059 // come through notify.
4060 SET_ERR("RequestThread: Unable to submit capture request %d to HAL device: %s (%d)",
4061 mNextRequests[numRequestProcessed].halRequest.frame_number,
4062 strerror(-res), res);
4063 cleanUpFailedRequests(/*sendRequestError*/ false);
4064 return false;
4065 }
4066 return true;
4067}
4068
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07004069nsecs_t Camera3Device::RequestThread::calculateMaxExpectedDuration(const camera_metadata_t *request) {
4070 nsecs_t maxExpectedDuration = kDefaultExpectedDuration;
4071 camera_metadata_ro_entry_t e = camera_metadata_ro_entry_t();
4072 find_camera_metadata_ro_entry(request,
4073 ANDROID_CONTROL_AE_MODE,
4074 &e);
4075 if (e.count == 0) return maxExpectedDuration;
4076
4077 switch (e.data.u8[0]) {
4078 case ANDROID_CONTROL_AE_MODE_OFF:
4079 find_camera_metadata_ro_entry(request,
4080 ANDROID_SENSOR_EXPOSURE_TIME,
4081 &e);
4082 if (e.count > 0) {
4083 maxExpectedDuration = e.data.i64[0];
4084 }
4085 find_camera_metadata_ro_entry(request,
4086 ANDROID_SENSOR_FRAME_DURATION,
4087 &e);
4088 if (e.count > 0) {
4089 maxExpectedDuration = std::max(e.data.i64[0], maxExpectedDuration);
4090 }
4091 break;
4092 default:
4093 find_camera_metadata_ro_entry(request,
4094 ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
4095 &e);
4096 if (e.count > 1) {
4097 maxExpectedDuration = 1e9 / e.data.u8[0];
4098 }
4099 break;
4100 }
4101
4102 return maxExpectedDuration;
4103}
4104
Emilian Peeva14b4dd2018-05-15 11:00:31 +01004105bool Camera3Device::RequestThread::skipHFRTargetFPSUpdate(int32_t tag,
4106 const camera_metadata_ro_entry_t& newEntry, const camera_metadata_entry_t& currentEntry) {
4107 if (mConstrainedMode && (ANDROID_CONTROL_AE_TARGET_FPS_RANGE == tag) &&
4108 (newEntry.count == currentEntry.count) && (currentEntry.count == 2) &&
4109 (currentEntry.data.i32[1] == newEntry.data.i32[1])) {
4110 return true;
4111 }
4112
4113 return false;
4114}
4115
Shuzhen Wangc2cba122018-05-17 18:10:24 -07004116void Camera3Device::RequestThread::updateNextRequest(NextRequest& nextRequest) {
4117 // Update the latest request sent to HAL
4118 if (nextRequest.halRequest.settings != NULL) { // Don't update if they were unchanged
4119 Mutex::Autolock al(mLatestRequestMutex);
4120
4121 camera_metadata_t* cloned = clone_camera_metadata(nextRequest.halRequest.settings);
4122 mLatestRequest.acquire(cloned);
4123
4124 mLatestPhysicalRequest.clear();
4125 for (uint32_t i = 0; i < nextRequest.halRequest.num_physcam_settings; i++) {
4126 cloned = clone_camera_metadata(nextRequest.halRequest.physcam_settings[i]);
4127 mLatestPhysicalRequest.emplace(nextRequest.halRequest.physcam_id[i],
4128 CameraMetadata(cloned));
4129 }
4130
4131 sp<Camera3Device> parent = mParent.promote();
4132 if (parent != NULL) {
4133 parent->monitorMetadata(TagMonitor::REQUEST,
4134 nextRequest.halRequest.frame_number,
4135 0, mLatestRequest, mLatestPhysicalRequest);
4136 }
4137 }
4138
4139 if (nextRequest.halRequest.settings != NULL) {
4140 nextRequest.captureRequest->mSettingsList.begin()->metadata.unlock(
4141 nextRequest.halRequest.settings);
4142 }
4143
4144 cleanupPhysicalSettings(nextRequest.captureRequest, &nextRequest.halRequest);
4145}
4146
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004147bool Camera3Device::RequestThread::updateSessionParameters(const CameraMetadata& settings) {
4148 ATRACE_CALL();
4149 bool updatesDetected = false;
4150
Emilian Peev4ec17882019-01-24 17:16:58 -08004151 CameraMetadata updatedParams(mLatestSessionParams);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004152 for (auto tag : mSessionParamKeys) {
4153 camera_metadata_ro_entry entry = settings.find(tag);
Emilian Peev4ec17882019-01-24 17:16:58 -08004154 camera_metadata_entry lastEntry = updatedParams.find(tag);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004155
4156 if (entry.count > 0) {
4157 bool isDifferent = false;
4158 if (lastEntry.count > 0) {
4159 // Have a last value, compare to see if changed
4160 if (lastEntry.type == entry.type &&
4161 lastEntry.count == entry.count) {
4162 // Same type and count, compare values
4163 size_t bytesPerValue = camera_metadata_type_size[lastEntry.type];
4164 size_t entryBytes = bytesPerValue * lastEntry.count;
4165 int cmp = memcmp(entry.data.u8, lastEntry.data.u8, entryBytes);
4166 if (cmp != 0) {
4167 isDifferent = true;
4168 }
4169 } else {
4170 // Count or type has changed
4171 isDifferent = true;
4172 }
4173 } else {
4174 // No last entry, so always consider to be different
4175 isDifferent = true;
4176 }
4177
4178 if (isDifferent) {
4179 ALOGV("%s: Session parameter tag id %d changed", __FUNCTION__, tag);
Emilian Peeva14b4dd2018-05-15 11:00:31 +01004180 if (!skipHFRTargetFPSUpdate(tag, entry, lastEntry)) {
4181 updatesDetected = true;
4182 }
Emilian Peev4ec17882019-01-24 17:16:58 -08004183 updatedParams.update(entry);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004184 }
4185 } else if (lastEntry.count > 0) {
4186 // Value has been removed
4187 ALOGV("%s: Session parameter tag id %d removed", __FUNCTION__, tag);
Emilian Peev4ec17882019-01-24 17:16:58 -08004188 updatedParams.erase(tag);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004189 updatesDetected = true;
4190 }
4191 }
4192
Emilian Peev4ec17882019-01-24 17:16:58 -08004193 bool reconfigureRequired;
4194 if (updatesDetected) {
4195 reconfigureRequired = mInterface->isReconfigurationRequired(mLatestSessionParams,
4196 updatedParams);
4197 mLatestSessionParams = updatedParams;
4198 } else {
4199 reconfigureRequired = false;
4200 }
4201
4202 return reconfigureRequired;
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004203}
4204
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004205bool Camera3Device::RequestThread::threadLoop() {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004206 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004207 status_t res;
Jayant Chowdhary37eca242019-11-18 08:55:56 -08004208 // Any function called from threadLoop() must not hold mInterfaceLock since
4209 // it could lead to deadlocks (disconnect() -> hold mInterfaceMutex -> wait for request thread
4210 // to finish -> request thread waits on mInterfaceMutex) http://b/143513518
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004211
4212 // Handle paused state.
4213 if (waitIfPaused()) {
4214 return true;
4215 }
4216
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004217 // Wait for the next batch of requests.
4218 waitForNextRequestBatch();
4219 if (mNextRequests.size() == 0) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004220 return true;
4221 }
4222
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004223 // Get the latest request ID, if any
4224 int latestRequestId;
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004225 camera_metadata_entry_t requestIdEntry = mNextRequests[mNextRequests.size() - 1].
Emilian Peevaebbe412018-01-15 13:53:24 +00004226 captureRequest->mSettingsList.begin()->metadata.find(ANDROID_REQUEST_ID);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004227 if (requestIdEntry.count > 0) {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004228 latestRequestId = requestIdEntry.data.i32[0];
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004229 } else {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004230 ALOGW("%s: Did not have android.request.id set in the request.", __FUNCTION__);
4231 latestRequestId = NAME_NOT_FOUND;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004232 }
4233
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004234 // 'mNextRequests' will at this point contain either a set of HFR batched requests
4235 // or a single request from streaming or burst. In either case the first element
4236 // should contain the latest camera settings that we need to check for any session
4237 // parameter updates.
Emilian Peevaebbe412018-01-15 13:53:24 +00004238 if (updateSessionParameters(mNextRequests[0].captureRequest->mSettingsList.begin()->metadata)) {
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004239 res = OK;
4240
4241 //Input stream buffers are already acquired at this point so an input stream
4242 //will not be able to move to idle state unless we force it.
4243 if (mNextRequests[0].captureRequest->mInputStream != nullptr) {
4244 res = mNextRequests[0].captureRequest->mInputStream->forceToIdle();
4245 if (res != OK) {
4246 ALOGE("%s: Failed to force idle input stream: %d", __FUNCTION__, res);
4247 cleanUpFailedRequests(/*sendRequestError*/ false);
4248 return false;
4249 }
4250 }
4251
4252 if (res == OK) {
4253 sp<StatusTracker> statusTracker = mStatusTracker.promote();
4254 if (statusTracker != 0) {
Eino-Ville Talvala002001b2018-01-23 16:53:50 -08004255 sp<Camera3Device> parent = mParent.promote();
4256 if (parent != nullptr) {
4257 parent->pauseStateNotify(true);
4258 }
4259
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004260 statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);
4261
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004262 if (parent != nullptr) {
4263 mReconfigured |= parent->reconfigureCamera(mLatestSessionParams);
4264 }
4265
4266 statusTracker->markComponentActive(mStatusId);
4267 setPaused(false);
4268 }
4269
4270 if (mNextRequests[0].captureRequest->mInputStream != nullptr) {
4271 mNextRequests[0].captureRequest->mInputStream->restoreConfiguredState();
4272 if (res != OK) {
4273 ALOGE("%s: Failed to restore configured input stream: %d", __FUNCTION__, res);
4274 cleanUpFailedRequests(/*sendRequestError*/ false);
4275 return false;
4276 }
4277 }
4278 }
4279 }
4280
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004281 // Prepare a batch of HAL requests and output buffers.
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004282 res = prepareHalRequests();
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004283 if (res == TIMED_OUT) {
4284 // Not a fatal error if getting output buffers time out.
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004285 cleanUpFailedRequests(/*sendRequestError*/ true);
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07004286 // Check if any stream is abandoned.
4287 checkAndStopRepeatingRequest();
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004288 return true;
4289 } else if (res != OK) {
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004290 cleanUpFailedRequests(/*sendRequestError*/ false);
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07004291 return false;
4292 }
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004293
Zhijun Hecc27e112013-10-03 16:12:43 -07004294 // Inform waitUntilRequestProcessed thread of a new request ID
4295 {
4296 Mutex::Autolock al(mLatestRequestMutex);
4297
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004298 mLatestRequestId = latestRequestId;
Zhijun Hecc27e112013-10-03 16:12:43 -07004299 mLatestRequestSignal.signal();
4300 }
4301
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004302 // Submit a batch of requests to HAL.
4303 // Use flush lock only when submitting multilple requests in a batch.
4304 // TODO: The problem with flush lock is flush() will be blocked by process_capture_request()
4305 // which may take a long time to finish so synchronizing flush() and
4306 // process_capture_request() defeats the purpose of cancelling requests ASAP with flush().
4307 // For now, only synchronize for high speed recording and we should figure something out for
4308 // removing the synchronization.
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004309 bool useFlushLock = mNextRequests.size() > 1;
Eino-Ville Talvala17a61ad2013-06-03 16:53:32 -07004310
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004311 if (useFlushLock) {
4312 mFlushLock.lock();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004313 }
4314
Zhijun Hef0645c12016-08-02 00:58:11 -07004315 ALOGVV("%s: %d: submitting %zu requests in a batch.", __FUNCTION__, __LINE__,
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004316 mNextRequests.size());
Igor Murashkin1e479c02013-09-06 16:55:14 -07004317
Yin-Chia Yehcd333fe2019-02-08 13:45:41 -08004318 sp<Camera3Device> parent = mParent.promote();
4319 if (parent != nullptr) {
4320 parent->mRequestBufferSM.onSubmittingRequest();
4321 }
4322
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004323 bool submitRequestSuccess = false;
Shuzhen Wang686f6442017-06-20 16:16:04 -07004324 nsecs_t tRequestStart = systemTime(SYSTEM_TIME_MONOTONIC);
Yin-Chia Yeh11648852019-05-16 10:42:54 -07004325 submitRequestSuccess = sendRequestsBatch();
4326
Shuzhen Wang686f6442017-06-20 16:16:04 -07004327 nsecs_t tRequestEnd = systemTime(SYSTEM_TIME_MONOTONIC);
4328 mRequestLatency.add(tRequestStart, tRequestEnd);
Igor Murashkin1e479c02013-09-06 16:55:14 -07004329
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004330 if (useFlushLock) {
4331 mFlushLock.unlock();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004332 }
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004333
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004334 // Unset as current request
4335 {
4336 Mutex::Autolock l(mRequestLock);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004337 mNextRequests.clear();
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004338 }
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004339 mRequestSubmittedSignal.signal();
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004340
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004341 return submitRequestSuccess;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004342}
4343
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004344status_t Camera3Device::RequestThread::prepareHalRequests() {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004345 ATRACE_CALL();
4346
Yin-Chia Yehd07b11e2018-06-01 12:50:02 -07004347 bool batchedRequest = mNextRequests[0].captureRequest->mBatchSize > 1;
Shuzhen Wang4a472662017-02-26 23:29:04 -08004348 for (size_t i = 0; i < mNextRequests.size(); i++) {
4349 auto& nextRequest = mNextRequests.editItemAt(i);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004350 sp<CaptureRequest> captureRequest = nextRequest.captureRequest;
4351 camera3_capture_request_t* halRequest = &nextRequest.halRequest;
4352 Vector<camera3_stream_buffer_t>* outputBuffers = &nextRequest.outputBuffers;
4353
4354 // Prepare a request to HAL
4355 halRequest->frame_number = captureRequest->mResultExtras.frameNumber;
4356
4357 // Insert any queued triggers (before metadata is locked)
4358 status_t res = insertTriggers(captureRequest);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004359 if (res < 0) {
4360 SET_ERR("RequestThread: Unable to insert triggers "
4361 "(capture request %d, HAL device: %s (%d)",
4362 halRequest->frame_number, strerror(-res), res);
4363 return INVALID_OPERATION;
4364 }
Eino-Ville Talvala7b8a1fd2018-05-22 15:30:35 -07004365
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004366 int triggerCount = res;
4367 bool triggersMixedIn = (triggerCount > 0 || mPrevTriggers > 0);
4368 mPrevTriggers = triggerCount;
4369
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08004370 bool rotateAndCropChanged = overrideAutoRotateAndCrop(captureRequest);
4371
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004372 // If the request is the same as last, or we had triggers last time
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08004373 bool newRequest =
4374 (mPrevRequest != captureRequest || triggersMixedIn || rotateAndCropChanged) &&
Yin-Chia Yehd07b11e2018-06-01 12:50:02 -07004375 // Request settings are all the same within one batch, so only treat the first
4376 // request in a batch as new
Zhijun He54c36822018-07-18 09:33:39 -07004377 !(batchedRequest && i > 0);
Emilian Peev00420d22018-02-05 21:33:13 +00004378 if (newRequest) {
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08004379 std::set<std::string> cameraIdsWithZoom;
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004380 /**
4381 * HAL workaround:
4382 * Insert a dummy trigger ID if a trigger is set but no trigger ID is
4383 */
4384 res = addDummyTriggerIds(captureRequest);
4385 if (res != OK) {
4386 SET_ERR("RequestThread: Unable to insert dummy trigger IDs "
4387 "(capture request %d, HAL device: %s (%d)",
4388 halRequest->frame_number, strerror(-res), res);
4389 return INVALID_OPERATION;
4390 }
4391
Eino-Ville Talvala7b8a1fd2018-05-22 15:30:35 -07004392 {
4393 // Correct metadata regions for distortion correction if enabled
4394 sp<Camera3Device> parent = mParent.promote();
4395 if (parent != nullptr) {
Shuzhen Wang4f6fa9d2019-03-29 10:40:35 -07004396 List<PhysicalCameraSettings>::iterator it;
4397 for (it = captureRequest->mSettingsList.begin();
4398 it != captureRequest->mSettingsList.end(); it++) {
4399 if (parent->mDistortionMappers.find(it->cameraId) ==
4400 parent->mDistortionMappers.end()) {
4401 continue;
4402 }
4403 res = parent->mDistortionMappers[it->cameraId].correctCaptureRequest(
4404 &(it->metadata));
4405 if (res != OK) {
4406 SET_ERR("RequestThread: Unable to correct capture requests "
4407 "for lens distortion for request %d: %s (%d)",
4408 halRequest->frame_number, strerror(-res), res);
4409 return INVALID_OPERATION;
4410 }
Eino-Ville Talvala7b8a1fd2018-05-22 15:30:35 -07004411 }
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08004412
4413 for (it = captureRequest->mSettingsList.begin();
4414 it != captureRequest->mSettingsList.end(); it++) {
4415 if (parent->mZoomRatioMappers.find(it->cameraId) ==
4416 parent->mZoomRatioMappers.end()) {
4417 continue;
4418 }
4419
4420 camera_metadata_entry_t e = it->metadata.find(ANDROID_CONTROL_ZOOM_RATIO);
4421 if (e.count > 0 && e.data.f[0] != 1.0f) {
4422 cameraIdsWithZoom.insert(it->cameraId);
4423 }
4424
4425 res = parent->mZoomRatioMappers[it->cameraId].updateCaptureRequest(
4426 &(it->metadata));
4427 if (res != OK) {
4428 SET_ERR("RequestThread: Unable to correct capture requests "
4429 "for zoom ratio for request %d: %s (%d)",
4430 halRequest->frame_number, strerror(-res), res);
4431 return INVALID_OPERATION;
4432 }
4433 }
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08004434 if (captureRequest->mRotateAndCropAuto) {
4435 for (it = captureRequest->mSettingsList.begin();
4436 it != captureRequest->mSettingsList.end(); it++) {
4437 auto mapper = parent->mRotateAndCropMappers.find(it->cameraId);
4438 if (mapper != parent->mRotateAndCropMappers.end()) {
4439 res = mapper->second.updateCaptureRequest(&(it->metadata));
4440 if (res != OK) {
4441 SET_ERR("RequestThread: Unable to correct capture requests "
4442 "for rotate-and-crop for request %d: %s (%d)",
4443 halRequest->frame_number, strerror(-res), res);
4444 return INVALID_OPERATION;
4445 }
4446 }
4447 }
4448 }
Eino-Ville Talvala7b8a1fd2018-05-22 15:30:35 -07004449 }
4450 }
4451
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004452 /**
4453 * The request should be presorted so accesses in HAL
4454 * are O(logn). Sidenote, sorting a sorted metadata is nop.
4455 */
Emilian Peevaebbe412018-01-15 13:53:24 +00004456 captureRequest->mSettingsList.begin()->metadata.sort();
4457 halRequest->settings = captureRequest->mSettingsList.begin()->metadata.getAndLock();
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004458 mPrevRequest = captureRequest;
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08004459 mPrevCameraIdsWithZoom = cameraIdsWithZoom;
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004460 ALOGVV("%s: Request settings are NEW", __FUNCTION__);
4461
4462 IF_ALOGV() {
4463 camera_metadata_ro_entry_t e = camera_metadata_ro_entry_t();
4464 find_camera_metadata_ro_entry(
4465 halRequest->settings,
4466 ANDROID_CONTROL_AF_TRIGGER,
4467 &e
4468 );
4469 if (e.count > 0) {
4470 ALOGV("%s: Request (frame num %d) had AF trigger 0x%x",
4471 __FUNCTION__,
4472 halRequest->frame_number,
4473 e.data.u8[0]);
4474 }
4475 }
4476 } else {
4477 // leave request.settings NULL to indicate 'reuse latest given'
4478 ALOGVV("%s: Request settings are REUSED",
4479 __FUNCTION__);
4480 }
4481
Emilian Peevaebbe412018-01-15 13:53:24 +00004482 if (captureRequest->mSettingsList.size() > 1) {
4483 halRequest->num_physcam_settings = captureRequest->mSettingsList.size() - 1;
4484 halRequest->physcam_id = new const char* [halRequest->num_physcam_settings];
Emilian Peev00420d22018-02-05 21:33:13 +00004485 if (newRequest) {
4486 halRequest->physcam_settings =
4487 new const camera_metadata* [halRequest->num_physcam_settings];
4488 } else {
4489 halRequest->physcam_settings = nullptr;
4490 }
Emilian Peevaebbe412018-01-15 13:53:24 +00004491 auto it = ++captureRequest->mSettingsList.begin();
4492 size_t i = 0;
4493 for (; it != captureRequest->mSettingsList.end(); it++, i++) {
4494 halRequest->physcam_id[i] = it->cameraId.c_str();
Emilian Peev00420d22018-02-05 21:33:13 +00004495 if (newRequest) {
4496 it->metadata.sort();
4497 halRequest->physcam_settings[i] = it->metadata.getAndLock();
4498 }
Emilian Peevaebbe412018-01-15 13:53:24 +00004499 }
4500 }
4501
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004502 uint32_t totalNumBuffers = 0;
4503
4504 // Fill in buffers
4505 if (captureRequest->mInputStream != NULL) {
4506 halRequest->input_buffer = &captureRequest->mInputBuffer;
4507 totalNumBuffers += 1;
4508 } else {
4509 halRequest->input_buffer = NULL;
4510 }
4511
4512 outputBuffers->insertAt(camera3_stream_buffer_t(), 0,
4513 captureRequest->mOutputStreams.size());
4514 halRequest->output_buffers = outputBuffers->array();
Shuzhen Wang5c22c152017-12-31 17:12:25 -08004515 std::set<String8> requestedPhysicalCameras;
Yin-Chia Yehb3a80b12018-09-04 12:13:05 -07004516
4517 sp<Camera3Device> parent = mParent.promote();
4518 if (parent == NULL) {
4519 // Should not happen, and nowhere to send errors to, so just log it
4520 CLOGE("RequestThread: Parent is gone");
4521 return INVALID_OPERATION;
4522 }
4523 nsecs_t waitDuration = kBaseGetBufferWait + parent->getExpectedInFlightDuration();
4524
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004525 SurfaceMap uniqueSurfaceIdMap;
Shuzhen Wang4a472662017-02-26 23:29:04 -08004526 for (size_t j = 0; j < captureRequest->mOutputStreams.size(); j++) {
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004527 sp<Camera3OutputStreamInterface> outputStream =
4528 captureRequest->mOutputStreams.editItemAt(j);
4529 int streamId = outputStream->getId();
Chien-Yu Chenc66969b2016-05-19 16:37:51 -07004530
4531 // Prepare video buffers for high speed recording on the first video request.
4532 if (mPrepareVideoStream && outputStream->isVideoStream()) {
4533 // Only try to prepare video stream on the first video request.
4534 mPrepareVideoStream = false;
4535
Shuzhen Wangb3a0fb52018-09-13 17:24:08 -07004536 res = outputStream->startPrepare(Camera3StreamInterface::ALLOCATE_PIPELINE_MAX,
4537 false /*blockRequest*/);
Chien-Yu Chenc66969b2016-05-19 16:37:51 -07004538 while (res == NOT_ENOUGH_DATA) {
4539 res = outputStream->prepareNextBuffer();
4540 }
4541 if (res != OK) {
4542 ALOGW("%s: Preparing video buffers for high speed failed: %s (%d)",
4543 __FUNCTION__, strerror(-res), res);
4544 outputStream->cancelPrepare();
4545 }
4546 }
4547
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004548 std::vector<size_t> uniqueSurfaceIds;
4549 res = outputStream->getUniqueSurfaceIds(
4550 captureRequest->mOutputSurfaces[streamId],
4551 &uniqueSurfaceIds);
4552 // INVALID_OPERATION is normal output for streams not supporting surfaceIds
4553 if (res != OK && res != INVALID_OPERATION) {
4554 ALOGE("%s: failed to query stream %d unique surface IDs",
4555 __FUNCTION__, streamId);
4556 return res;
4557 }
4558 if (res == OK) {
4559 uniqueSurfaceIdMap.insert({streamId, std::move(uniqueSurfaceIds)});
4560 }
4561
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07004562 if (mUseHalBufManager) {
Yin-Chia Yeh110342b2018-11-19 11:47:46 -08004563 if (outputStream->isAbandoned()) {
Yin-Chia Yeha1b56c82019-03-27 15:50:39 -07004564 ALOGV("%s: stream %d is abandoned, skipping request", __FUNCTION__, streamId);
Yin-Chia Yeh110342b2018-11-19 11:47:46 -08004565 return TIMED_OUT;
4566 }
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07004567 // HAL will request buffer through requestStreamBuffer API
4568 camera3_stream_buffer_t& buffer = outputBuffers->editItemAt(j);
4569 buffer.stream = outputStream->asHalStream();
4570 buffer.buffer = nullptr;
4571 buffer.status = CAMERA3_BUFFER_STATUS_OK;
4572 buffer.acquire_fence = -1;
4573 buffer.release_fence = -1;
4574 } else {
4575 res = outputStream->getBuffer(&outputBuffers->editItemAt(j),
4576 waitDuration,
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004577 captureRequest->mOutputSurfaces[streamId]);
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07004578 if (res != OK) {
4579 // Can't get output buffer from gralloc queue - this could be due to
4580 // abandoned queue or other consumer misbehavior, so not a fatal
4581 // error
Yin-Chia Yeha1b56c82019-03-27 15:50:39 -07004582 ALOGV("RequestThread: Can't get output buffer, skipping request:"
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07004583 " %s (%d)", strerror(-res), res);
4584
4585 return TIMED_OUT;
4586 }
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004587 }
Shuzhen Wang68ac7ad2019-01-30 14:03:28 -08004588
4589 {
4590 sp<Camera3Device> parent = mParent.promote();
4591 if (parent != nullptr) {
4592 const String8& streamCameraId = outputStream->getPhysicalCameraId();
4593 for (const auto& settings : captureRequest->mSettingsList) {
4594 if ((streamCameraId.isEmpty() &&
4595 parent->getId() == settings.cameraId.c_str()) ||
4596 streamCameraId == settings.cameraId.c_str()) {
4597 outputStream->fireBufferRequestForFrameNumber(
4598 captureRequest->mResultExtras.frameNumber,
4599 settings.metadata);
4600 }
4601 }
4602 }
4603 }
Shuzhen Wang0129d522016-10-30 22:43:41 -07004604
Shuzhen Wang5c22c152017-12-31 17:12:25 -08004605 String8 physicalCameraId = outputStream->getPhysicalCameraId();
4606
4607 if (!physicalCameraId.isEmpty()) {
4608 // Physical stream isn't supported for input request.
4609 if (halRequest->input_buffer) {
4610 CLOGE("Physical stream is not supported for input request");
4611 return INVALID_OPERATION;
4612 }
4613 requestedPhysicalCameras.insert(physicalCameraId);
4614 }
4615 halRequest->num_output_buffers++;
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004616 }
4617 totalNumBuffers += halRequest->num_output_buffers;
4618
4619 // Log request in the in-flight queue
Shuzhen Wang4a472662017-02-26 23:29:04 -08004620 // If this request list is for constrained high speed recording (not
4621 // preview), and the current request is not the last one in the batch,
4622 // do not send callback to the app.
4623 bool hasCallback = true;
Yin-Chia Yehd07b11e2018-06-01 12:50:02 -07004624 if (batchedRequest && i != mNextRequests.size()-1) {
Shuzhen Wang4a472662017-02-26 23:29:04 -08004625 hasCallback = false;
4626 }
Emilian Peev9dd21f42018-08-03 13:39:29 +01004627 bool isStillCapture = false;
Shuzhen Wang26abaf42018-08-28 15:41:20 -07004628 bool isZslCapture = false;
Emilian Peev9dd21f42018-08-03 13:39:29 +01004629 if (!mNextRequests[0].captureRequest->mSettingsList.begin()->metadata.isEmpty()) {
4630 camera_metadata_ro_entry_t e = camera_metadata_ro_entry_t();
4631 find_camera_metadata_ro_entry(halRequest->settings, ANDROID_CONTROL_CAPTURE_INTENT, &e);
4632 if ((e.count > 0) && (e.data.u8[0] == ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE)) {
4633 isStillCapture = true;
4634 ATRACE_ASYNC_BEGIN("still capture", mNextRequests[i].halRequest.frame_number);
4635 }
Shuzhen Wang26abaf42018-08-28 15:41:20 -07004636
4637 find_camera_metadata_ro_entry(halRequest->settings, ANDROID_CONTROL_ENABLE_ZSL, &e);
4638 if ((e.count > 0) && (e.data.u8[0] == ANDROID_CONTROL_ENABLE_ZSL_TRUE)) {
4639 isZslCapture = true;
4640 }
Emilian Peev9dd21f42018-08-03 13:39:29 +01004641 }
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004642 res = parent->registerInFlight(halRequest->frame_number,
4643 totalNumBuffers, captureRequest->mResultExtras,
4644 /*hasInput*/halRequest->input_buffer != NULL,
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07004645 hasCallback,
Shuzhen Wang5c22c152017-12-31 17:12:25 -08004646 calculateMaxExpectedDuration(halRequest->settings),
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08004647 requestedPhysicalCameras, isStillCapture, isZslCapture,
4648 captureRequest->mRotateAndCropAuto, mPrevCameraIdsWithZoom,
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004649 (mUseHalBufManager) ? uniqueSurfaceIdMap :
4650 SurfaceMap{});
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004651 ALOGVV("%s: registered in flight requestId = %" PRId32 ", frameNumber = %" PRId64
4652 ", burstId = %" PRId32 ".",
4653 __FUNCTION__,
4654 captureRequest->mResultExtras.requestId, captureRequest->mResultExtras.frameNumber,
4655 captureRequest->mResultExtras.burstId);
4656 if (res != OK) {
4657 SET_ERR("RequestThread: Unable to register new in-flight request:"
4658 " %s (%d)", strerror(-res), res);
4659 return INVALID_OPERATION;
4660 }
4661 }
4662
4663 return OK;
4664}
4665
Igor Murashkin1e479c02013-09-06 16:55:14 -07004666CameraMetadata Camera3Device::RequestThread::getLatestRequest() const {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004667 ATRACE_CALL();
Igor Murashkin1e479c02013-09-06 16:55:14 -07004668 Mutex::Autolock al(mLatestRequestMutex);
4669
4670 ALOGV("RequestThread::%s", __FUNCTION__);
4671
4672 return mLatestRequest;
4673}
4674
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07004675bool Camera3Device::RequestThread::isStreamPending(
4676 sp<Camera3StreamInterface>& stream) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004677 ATRACE_CALL();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07004678 Mutex::Autolock l(mRequestLock);
4679
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004680 for (const auto& nextRequest : mNextRequests) {
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004681 if (!nextRequest.submitted) {
4682 for (const auto& s : nextRequest.captureRequest->mOutputStreams) {
4683 if (stream == s) return true;
4684 }
4685 if (stream == nextRequest.captureRequest->mInputStream) return true;
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004686 }
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004687 }
4688
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07004689 for (const auto& request : mRequestQueue) {
4690 for (const auto& s : request->mOutputStreams) {
4691 if (stream == s) return true;
4692 }
4693 if (stream == request->mInputStream) return true;
4694 }
4695
4696 for (const auto& request : mRepeatingRequests) {
4697 for (const auto& s : request->mOutputStreams) {
4698 if (stream == s) return true;
4699 }
4700 if (stream == request->mInputStream) return true;
4701 }
4702
4703 return false;
4704}
Jianing Weicb0652e2014-03-12 18:29:36 -07004705
Emilian Peev40ead602017-09-26 15:46:36 +01004706bool Camera3Device::RequestThread::isOutputSurfacePending(int streamId, size_t surfaceId) {
4707 ATRACE_CALL();
4708 Mutex::Autolock l(mRequestLock);
4709
4710 for (const auto& nextRequest : mNextRequests) {
4711 for (const auto& s : nextRequest.captureRequest->mOutputSurfaces) {
4712 if (s.first == streamId) {
4713 const auto &it = std::find(s.second.begin(), s.second.end(), surfaceId);
4714 if (it != s.second.end()) {
4715 return true;
4716 }
4717 }
4718 }
4719 }
4720
4721 for (const auto& request : mRequestQueue) {
4722 for (const auto& s : request->mOutputSurfaces) {
4723 if (s.first == streamId) {
4724 const auto &it = std::find(s.second.begin(), s.second.end(), surfaceId);
4725 if (it != s.second.end()) {
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004726 return true;
Emilian Peev40ead602017-09-26 15:46:36 +01004727 }
4728 }
4729 }
4730 }
4731
4732 for (const auto& request : mRepeatingRequests) {
4733 for (const auto& s : request->mOutputSurfaces) {
4734 if (s.first == streamId) {
4735 const auto &it = std::find(s.second.begin(), s.second.end(), surfaceId);
4736 if (it != s.second.end()) {
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004737 return true;
Emilian Peev40ead602017-09-26 15:46:36 +01004738 }
4739 }
4740 }
4741 }
4742
4743 return false;
4744}
4745
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07004746void Camera3Device::RequestThread::signalPipelineDrain(const std::vector<int>& streamIds) {
4747 if (!mUseHalBufManager) {
4748 ALOGE("%s called for camera device not supporting HAL buffer management", __FUNCTION__);
4749 return;
4750 }
4751
4752 Mutex::Autolock pl(mPauseLock);
4753 if (mPaused) {
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07004754 mInterface->signalPipelineDrain(streamIds);
4755 return;
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07004756 }
4757 // If request thread is still busy, wait until paused then notify HAL
4758 mNotifyPipelineDrain = true;
4759 mStreamIdsToBeDrained = streamIds;
4760}
4761
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004762status_t Camera3Device::RequestThread::switchToOffline(
4763 const std::vector<int32_t>& streamsToKeep,
4764 /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004765 /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
4766 /*out*/camera3::BufferRecords* bufferRecords) {
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004767 Mutex::Autolock l(mRequestLock);
4768 clearRepeatingRequestsLocked(/*lastFrameNumber*/nullptr);
4769
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004770 // Wait until request thread is fully stopped
4771 // TBD: check if request thread is being paused by other APIs (shouldn't be)
4772
4773 // We could also check for mRepeatingRequests.empty(), but the API interface
4774 // is serialized by Camera3Device::mInterfaceLock so no one should be able to submit any
4775 // new requests during the call; hence skip that check.
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004776 bool queueEmpty = mNextRequests.empty() && mRequestQueue.empty();
4777 while (!queueEmpty) {
4778 status_t res = mRequestSubmittedSignal.waitRelative(mRequestLock, kRequestSubmitTimeout);
4779 if (res == TIMED_OUT) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004780 ALOGE("%s: request thread failed to submit one request within timeout!", __FUNCTION__);
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004781 return res;
4782 } else if (res != OK) {
4783 ALOGE("%s: request thread failed to submit a request: %s (%d)!",
4784 __FUNCTION__, strerror(-res), res);
4785 return res;
4786 }
4787 queueEmpty = mNextRequests.empty() && mRequestQueue.empty();
4788 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004789
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004790 return mInterface->switchToOffline(
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004791 streamsToKeep, offlineSessionInfo, offlineSession, bufferRecords);
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004792}
4793
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08004794status_t Camera3Device::RequestThread::setRotateAndCropAutoBehavior(
4795 camera_metadata_enum_android_scaler_rotate_and_crop_t rotateAndCropValue) {
4796 ATRACE_CALL();
4797 Mutex::Autolock l(mTriggerMutex);
4798 if (rotateAndCropValue == ANDROID_SCALER_ROTATE_AND_CROP_AUTO) {
4799 return BAD_VALUE;
4800 }
4801 mRotateAndCropOverride = rotateAndCropValue;
4802 return OK;
4803}
4804
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07004805nsecs_t Camera3Device::getExpectedInFlightDuration() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004806 ATRACE_CALL();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004807 std::lock_guard<std::mutex> l(mInFlightLock);
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07004808 return mExpectedInflightDuration > kMinInflightDuration ?
4809 mExpectedInflightDuration : kMinInflightDuration;
4810}
4811
Emilian Peevaebbe412018-01-15 13:53:24 +00004812void Camera3Device::RequestThread::cleanupPhysicalSettings(sp<CaptureRequest> request,
4813 camera3_capture_request_t *halRequest) {
4814 if ((request == nullptr) || (halRequest == nullptr)) {
4815 ALOGE("%s: Invalid request!", __FUNCTION__);
4816 return;
4817 }
4818
4819 if (halRequest->num_physcam_settings > 0) {
4820 if (halRequest->physcam_id != nullptr) {
4821 delete [] halRequest->physcam_id;
4822 halRequest->physcam_id = nullptr;
4823 }
4824 if (halRequest->physcam_settings != nullptr) {
4825 auto it = ++(request->mSettingsList.begin());
4826 size_t i = 0;
4827 for (; it != request->mSettingsList.end(); it++, i++) {
4828 it->metadata.unlock(halRequest->physcam_settings[i]);
4829 }
4830 delete [] halRequest->physcam_settings;
4831 halRequest->physcam_settings = nullptr;
4832 }
4833 }
4834}
4835
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004836void Camera3Device::RequestThread::cleanUpFailedRequests(bool sendRequestError) {
4837 if (mNextRequests.empty()) {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004838 return;
4839 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004840
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004841 for (auto& nextRequest : mNextRequests) {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004842 // Skip the ones that have been submitted successfully.
4843 if (nextRequest.submitted) {
4844 continue;
4845 }
4846
4847 sp<CaptureRequest> captureRequest = nextRequest.captureRequest;
4848 camera3_capture_request_t* halRequest = &nextRequest.halRequest;
4849 Vector<camera3_stream_buffer_t>* outputBuffers = &nextRequest.outputBuffers;
4850
4851 if (halRequest->settings != NULL) {
Emilian Peevaebbe412018-01-15 13:53:24 +00004852 captureRequest->mSettingsList.begin()->metadata.unlock(halRequest->settings);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004853 }
4854
Emilian Peevaebbe412018-01-15 13:53:24 +00004855 cleanupPhysicalSettings(captureRequest, halRequest);
4856
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004857 if (captureRequest->mInputStream != NULL) {
4858 captureRequest->mInputBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
4859 captureRequest->mInputStream->returnInputBuffer(captureRequest->mInputBuffer);
4860 }
4861
Yin-Chia Yeh21cb47b2019-01-18 15:08:17 -08004862 // No output buffer can be returned when using HAL buffer manager
4863 if (!mUseHalBufManager) {
4864 for (size_t i = 0; i < halRequest->num_output_buffers; i++) {
4865 //Buffers that failed processing could still have
4866 //valid acquire fence.
4867 int acquireFence = (*outputBuffers)[i].acquire_fence;
4868 if (0 <= acquireFence) {
4869 close(acquireFence);
4870 outputBuffers->editItemAt(i).acquire_fence = -1;
4871 }
4872 outputBuffers->editItemAt(i).status = CAMERA3_BUFFER_STATUS_ERROR;
4873 captureRequest->mOutputStreams.editItemAt(i)->returnBuffer((*outputBuffers)[i], 0,
4874 /*timestampIncreasing*/true, std::vector<size_t> (),
4875 captureRequest->mResultExtras.frameNumber);
Emilian Peevc58cf4c2017-05-11 17:23:41 +01004876 }
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004877 }
4878
4879 if (sendRequestError) {
4880 Mutex::Autolock l(mRequestLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07004881 sp<NotificationListener> listener = mListener.promote();
4882 if (listener != NULL) {
4883 listener->notifyError(
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08004884 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004885 captureRequest->mResultExtras);
4886 }
4887 }
Shuzhen Wangcadb3302016-11-04 14:17:56 -07004888
4889 // Remove yet-to-be submitted inflight request from inflightMap
4890 {
4891 sp<Camera3Device> parent = mParent.promote();
4892 if (parent != NULL) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004893 std::lock_guard<std::mutex> l(parent->mInFlightLock);
Shuzhen Wangcadb3302016-11-04 14:17:56 -07004894 ssize_t idx = parent->mInFlightMap.indexOfKey(captureRequest->mResultExtras.frameNumber);
4895 if (idx >= 0) {
4896 ALOGV("%s: Remove inflight request from queue: frameNumber %" PRId64,
4897 __FUNCTION__, captureRequest->mResultExtras.frameNumber);
4898 parent->removeInFlightMapEntryLocked(idx);
4899 }
4900 }
4901 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004902 }
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004903
4904 Mutex::Autolock l(mRequestLock);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004905 mNextRequests.clear();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004906}
4907
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004908void Camera3Device::RequestThread::waitForNextRequestBatch() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004909 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004910 // Optimized a bit for the simple steady-state case (single repeating
4911 // request), to avoid putting that request in the queue temporarily.
4912 Mutex::Autolock l(mRequestLock);
4913
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004914 assert(mNextRequests.empty());
4915
4916 NextRequest nextRequest;
4917 nextRequest.captureRequest = waitForNextRequestLocked();
4918 if (nextRequest.captureRequest == nullptr) {
4919 return;
4920 }
4921
4922 nextRequest.halRequest = camera3_capture_request_t();
4923 nextRequest.submitted = false;
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004924 mNextRequests.add(nextRequest);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004925
4926 // Wait for additional requests
4927 const size_t batchSize = nextRequest.captureRequest->mBatchSize;
4928
4929 for (size_t i = 1; i < batchSize; i++) {
4930 NextRequest additionalRequest;
4931 additionalRequest.captureRequest = waitForNextRequestLocked();
4932 if (additionalRequest.captureRequest == nullptr) {
4933 break;
4934 }
4935
4936 additionalRequest.halRequest = camera3_capture_request_t();
4937 additionalRequest.submitted = false;
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004938 mNextRequests.add(additionalRequest);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004939 }
4940
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004941 if (mNextRequests.size() < batchSize) {
Eino-Ville Talvalad309fb92015-11-25 12:12:45 -08004942 ALOGE("RequestThread: only get %zu out of %zu requests. Skipping requests.",
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004943 mNextRequests.size(), batchSize);
4944 cleanUpFailedRequests(/*sendRequestError*/true);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004945 }
4946
4947 return;
4948}
4949
4950sp<Camera3Device::CaptureRequest>
4951 Camera3Device::RequestThread::waitForNextRequestLocked() {
4952 status_t res;
4953 sp<CaptureRequest> nextRequest;
4954
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004955 while (mRequestQueue.empty()) {
4956 if (!mRepeatingRequests.empty()) {
4957 // Always atomically enqueue all requests in a repeating request
4958 // list. Guarantees a complete in-sequence set of captures to
4959 // application.
4960 const RequestList &requests = mRepeatingRequests;
4961 RequestList::const_iterator firstRequest =
4962 requests.begin();
4963 nextRequest = *firstRequest;
4964 mRequestQueue.insert(mRequestQueue.end(),
4965 ++firstRequest,
4966 requests.end());
4967 // No need to wait any longer
Jianing Weicb0652e2014-03-12 18:29:36 -07004968
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07004969 mRepeatingLastFrameNumber = mFrameNumber + requests.size() - 1;
Jianing Weicb0652e2014-03-12 18:29:36 -07004970
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004971 break;
4972 }
4973
4974 res = mRequestSignal.waitRelative(mRequestLock, kRequestTimeout);
4975
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004976 if ((mRequestQueue.empty() && mRepeatingRequests.empty()) ||
4977 exitPending()) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004978 Mutex::Autolock pl(mPauseLock);
4979 if (mPaused == false) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004980 ALOGV("%s: RequestThread: Going idle", __FUNCTION__);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004981 mPaused = true;
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07004982 if (mNotifyPipelineDrain) {
4983 mInterface->signalPipelineDrain(mStreamIdsToBeDrained);
4984 mNotifyPipelineDrain = false;
4985 mStreamIdsToBeDrained.clear();
4986 }
Yin-Chia Yehc300a072019-02-13 14:56:57 -08004987 // Let the tracker know
4988 sp<StatusTracker> statusTracker = mStatusTracker.promote();
4989 if (statusTracker != 0) {
4990 statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);
4991 }
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07004992 sp<Camera3Device> parent = mParent.promote();
4993 if (parent != nullptr) {
4994 parent->mRequestBufferSM.onRequestThreadPaused();
4995 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004996 }
4997 // Stop waiting for now and let thread management happen
4998 return NULL;
4999 }
5000 }
5001
5002 if (nextRequest == NULL) {
5003 // Don't have a repeating request already in hand, so queue
5004 // must have an entry now.
5005 RequestList::iterator firstRequest =
5006 mRequestQueue.begin();
5007 nextRequest = *firstRequest;
5008 mRequestQueue.erase(firstRequest);
Shuzhen Wang9d066012016-09-30 11:30:20 -07005009 if (mRequestQueue.empty() && !nextRequest->mRepeating) {
5010 sp<NotificationListener> listener = mListener.promote();
5011 if (listener != NULL) {
5012 listener->notifyRequestQueueEmpty();
5013 }
5014 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005015 }
5016
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07005017 // In case we've been unpaused by setPaused clearing mDoPause, need to
5018 // update internal pause state (capture/setRepeatingRequest unpause
5019 // directly).
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005020 Mutex::Autolock pl(mPauseLock);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005021 if (mPaused) {
5022 ALOGV("%s: RequestThread: Unpaused", __FUNCTION__);
5023 sp<StatusTracker> statusTracker = mStatusTracker.promote();
5024 if (statusTracker != 0) {
5025 statusTracker->markComponentActive(mStatusId);
5026 }
5027 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005028 mPaused = false;
5029
5030 // Check if we've reconfigured since last time, and reset the preview
5031 // request if so. Can't use 'NULL request == repeat' across configure calls.
5032 if (mReconfigured) {
5033 mPrevRequest.clear();
5034 mReconfigured = false;
5035 }
5036
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07005037 if (nextRequest != NULL) {
5038 nextRequest->mResultExtras.frameNumber = mFrameNumber++;
Yin-Chia Yehc00a25c2014-08-21 14:27:44 -07005039 nextRequest->mResultExtras.afTriggerId = mCurrentAfTriggerId;
5040 nextRequest->mResultExtras.precaptureTriggerId = mCurrentPreCaptureTriggerId;
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07005041
5042 // Since RequestThread::clear() removes buffers from the input stream,
5043 // get the right buffer here before unlocking mRequestLock
5044 if (nextRequest->mInputStream != NULL) {
5045 res = nextRequest->mInputStream->getInputBuffer(&nextRequest->mInputBuffer);
5046 if (res != OK) {
5047 // Can't get input buffer from gralloc queue - this could be due to
5048 // disconnected queue or other producer misbehavior, so not a fatal
5049 // error
5050 ALOGE("%s: Can't get input buffer, skipping request:"
5051 " %s (%d)", __FUNCTION__, strerror(-res), res);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005052
5053 sp<NotificationListener> listener = mListener.promote();
5054 if (listener != NULL) {
5055 listener->notifyError(
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08005056 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07005057 nextRequest->mResultExtras);
5058 }
5059 return NULL;
5060 }
5061 }
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07005062 }
Chien-Yu Chend196d612015-06-22 19:49:01 -07005063
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005064 return nextRequest;
5065}
5066
5067bool Camera3Device::RequestThread::waitIfPaused() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005068 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005069 status_t res;
5070 Mutex::Autolock l(mPauseLock);
5071 while (mDoPause) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005072 if (mPaused == false) {
5073 mPaused = true;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005074 ALOGV("%s: RequestThread: Paused", __FUNCTION__);
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07005075 if (mNotifyPipelineDrain) {
5076 mInterface->signalPipelineDrain(mStreamIdsToBeDrained);
5077 mNotifyPipelineDrain = false;
5078 mStreamIdsToBeDrained.clear();
5079 }
Yin-Chia Yehc300a072019-02-13 14:56:57 -08005080 // Let the tracker know
5081 sp<StatusTracker> statusTracker = mStatusTracker.promote();
5082 if (statusTracker != 0) {
5083 statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);
5084 }
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005085 sp<Camera3Device> parent = mParent.promote();
5086 if (parent != nullptr) {
5087 parent->mRequestBufferSM.onRequestThreadPaused();
5088 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005089 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005090
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005091 res = mDoPauseSignal.waitRelative(mPauseLock, kRequestTimeout);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005092 if (res == TIMED_OUT || exitPending()) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005093 return true;
5094 }
5095 }
5096 // We don't set mPaused to false here, because waitForNextRequest needs
5097 // to further manage the paused state in case of starvation.
5098 return false;
5099}
5100
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07005101void Camera3Device::RequestThread::unpauseForNewRequests() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005102 ATRACE_CALL();
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07005103 // With work to do, mark thread as unpaused.
5104 // If paused by request (setPaused), don't resume, to avoid
5105 // extra signaling/waiting overhead to waitUntilPaused
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005106 mRequestSignal.signal();
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07005107 Mutex::Autolock p(mPauseLock);
5108 if (!mDoPause) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005109 ALOGV("%s: RequestThread: Going active", __FUNCTION__);
5110 if (mPaused) {
5111 sp<StatusTracker> statusTracker = mStatusTracker.promote();
5112 if (statusTracker != 0) {
5113 statusTracker->markComponentActive(mStatusId);
5114 }
5115 }
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07005116 mPaused = false;
5117 }
5118}
5119
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07005120void Camera3Device::RequestThread::setErrorState(const char *fmt, ...) {
5121 sp<Camera3Device> parent = mParent.promote();
5122 if (parent != NULL) {
5123 va_list args;
5124 va_start(args, fmt);
5125
5126 parent->setErrorStateV(fmt, args);
5127
5128 va_end(args);
5129 }
5130}
5131
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005132status_t Camera3Device::RequestThread::insertTriggers(
5133 const sp<CaptureRequest> &request) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005134 ATRACE_CALL();
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005135 Mutex::Autolock al(mTriggerMutex);
5136
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07005137 sp<Camera3Device> parent = mParent.promote();
5138 if (parent == NULL) {
5139 CLOGE("RequestThread: Parent is gone");
5140 return DEAD_OBJECT;
5141 }
5142
Emilian Peevaebbe412018-01-15 13:53:24 +00005143 CameraMetadata &metadata = request->mSettingsList.begin()->metadata;
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005144 size_t count = mTriggerMap.size();
5145
5146 for (size_t i = 0; i < count; ++i) {
5147 RequestTrigger trigger = mTriggerMap.valueAt(i);
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005148 uint32_t tag = trigger.metadataTag;
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07005149
5150 if (tag == ANDROID_CONTROL_AF_TRIGGER_ID || tag == ANDROID_CONTROL_AE_PRECAPTURE_ID) {
5151 bool isAeTrigger = (trigger.metadataTag == ANDROID_CONTROL_AE_PRECAPTURE_ID);
5152 uint32_t triggerId = static_cast<uint32_t>(trigger.entryValue);
Yin-Chia Yehc00a25c2014-08-21 14:27:44 -07005153 if (isAeTrigger) {
5154 request->mResultExtras.precaptureTriggerId = triggerId;
5155 mCurrentPreCaptureTriggerId = triggerId;
5156 } else {
5157 request->mResultExtras.afTriggerId = triggerId;
5158 mCurrentAfTriggerId = triggerId;
5159 }
Emilian Peev7e25e5e2017-04-07 15:48:49 +01005160 continue;
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07005161 }
5162
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005163 camera_metadata_entry entry = metadata.find(tag);
5164
5165 if (entry.count > 0) {
5166 /**
5167 * Already has an entry for this trigger in the request.
5168 * Rewrite it with our requested trigger value.
5169 */
5170 RequestTrigger oldTrigger = trigger;
5171
5172 oldTrigger.entryValue = entry.data.u8[0];
5173
5174 mTriggerReplacedMap.add(tag, oldTrigger);
5175 } else {
5176 /**
5177 * More typical, no trigger entry, so we just add it
5178 */
5179 mTriggerRemovedMap.add(tag, trigger);
5180 }
5181
5182 status_t res;
5183
5184 switch (trigger.getTagType()) {
5185 case TYPE_BYTE: {
5186 uint8_t entryValue = static_cast<uint8_t>(trigger.entryValue);
5187 res = metadata.update(tag,
5188 &entryValue,
5189 /*count*/1);
5190 break;
5191 }
5192 case TYPE_INT32:
5193 res = metadata.update(tag,
5194 &trigger.entryValue,
5195 /*count*/1);
5196 break;
5197 default:
5198 ALOGE("%s: Type not supported: 0x%x",
5199 __FUNCTION__,
5200 trigger.getTagType());
5201 return INVALID_OPERATION;
5202 }
5203
5204 if (res != OK) {
5205 ALOGE("%s: Failed to update request metadata with trigger tag %s"
5206 ", value %d", __FUNCTION__, trigger.getTagName(),
5207 trigger.entryValue);
5208 return res;
5209 }
5210
5211 ALOGV("%s: Mixed in trigger %s, value %d", __FUNCTION__,
5212 trigger.getTagName(),
5213 trigger.entryValue);
5214 }
5215
5216 mTriggerMap.clear();
5217
5218 return count;
5219}
5220
5221status_t Camera3Device::RequestThread::removeTriggers(
5222 const sp<CaptureRequest> &request) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005223 ATRACE_CALL();
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005224 Mutex::Autolock al(mTriggerMutex);
5225
Emilian Peevaebbe412018-01-15 13:53:24 +00005226 CameraMetadata &metadata = request->mSettingsList.begin()->metadata;
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005227
5228 /**
5229 * Replace all old entries with their old values.
5230 */
5231 for (size_t i = 0; i < mTriggerReplacedMap.size(); ++i) {
5232 RequestTrigger trigger = mTriggerReplacedMap.valueAt(i);
5233
5234 status_t res;
5235
5236 uint32_t tag = trigger.metadataTag;
5237 switch (trigger.getTagType()) {
5238 case TYPE_BYTE: {
5239 uint8_t entryValue = static_cast<uint8_t>(trigger.entryValue);
5240 res = metadata.update(tag,
5241 &entryValue,
5242 /*count*/1);
5243 break;
5244 }
5245 case TYPE_INT32:
5246 res = metadata.update(tag,
5247 &trigger.entryValue,
5248 /*count*/1);
5249 break;
5250 default:
5251 ALOGE("%s: Type not supported: 0x%x",
5252 __FUNCTION__,
5253 trigger.getTagType());
5254 return INVALID_OPERATION;
5255 }
5256
5257 if (res != OK) {
5258 ALOGE("%s: Failed to restore request metadata with trigger tag %s"
5259 ", trigger value %d", __FUNCTION__,
5260 trigger.getTagName(), trigger.entryValue);
5261 return res;
5262 }
5263 }
5264 mTriggerReplacedMap.clear();
5265
5266 /**
5267 * Remove all new entries.
5268 */
5269 for (size_t i = 0; i < mTriggerRemovedMap.size(); ++i) {
5270 RequestTrigger trigger = mTriggerRemovedMap.valueAt(i);
5271 status_t res = metadata.erase(trigger.metadataTag);
5272
5273 if (res != OK) {
5274 ALOGE("%s: Failed to erase metadata with trigger tag %s"
5275 ", trigger value %d", __FUNCTION__,
5276 trigger.getTagName(), trigger.entryValue);
5277 return res;
5278 }
5279 }
5280 mTriggerRemovedMap.clear();
5281
5282 return OK;
5283}
5284
Eino-Ville Talvala2f876f92013-09-13 11:39:24 -07005285status_t Camera3Device::RequestThread::addDummyTriggerIds(
5286 const sp<CaptureRequest> &request) {
Eino-Ville Talvalad309fb92015-11-25 12:12:45 -08005287 // Trigger ID 0 had special meaning in the HAL2 spec, so avoid it here
Eino-Ville Talvala2f876f92013-09-13 11:39:24 -07005288 static const int32_t dummyTriggerId = 1;
5289 status_t res;
5290
Emilian Peevaebbe412018-01-15 13:53:24 +00005291 CameraMetadata &metadata = request->mSettingsList.begin()->metadata;
Eino-Ville Talvala2f876f92013-09-13 11:39:24 -07005292
5293 // If AF trigger is active, insert a dummy AF trigger ID if none already
5294 // exists
5295 camera_metadata_entry afTrigger = metadata.find(ANDROID_CONTROL_AF_TRIGGER);
5296 camera_metadata_entry afId = metadata.find(ANDROID_CONTROL_AF_TRIGGER_ID);
5297 if (afTrigger.count > 0 &&
5298 afTrigger.data.u8[0] != ANDROID_CONTROL_AF_TRIGGER_IDLE &&
5299 afId.count == 0) {
5300 res = metadata.update(ANDROID_CONTROL_AF_TRIGGER_ID, &dummyTriggerId, 1);
5301 if (res != OK) return res;
5302 }
5303
5304 // If AE precapture trigger is active, insert a dummy precapture trigger ID
5305 // if none already exists
5306 camera_metadata_entry pcTrigger =
5307 metadata.find(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER);
5308 camera_metadata_entry pcId = metadata.find(ANDROID_CONTROL_AE_PRECAPTURE_ID);
5309 if (pcTrigger.count > 0 &&
5310 pcTrigger.data.u8[0] != ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE &&
5311 pcId.count == 0) {
5312 res = metadata.update(ANDROID_CONTROL_AE_PRECAPTURE_ID,
5313 &dummyTriggerId, 1);
5314 if (res != OK) return res;
5315 }
5316
5317 return OK;
5318}
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005319
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08005320bool Camera3Device::RequestThread::overrideAutoRotateAndCrop(
5321 const sp<CaptureRequest> &request) {
5322 ATRACE_CALL();
5323
5324 if (request->mRotateAndCropAuto) {
5325 Mutex::Autolock l(mTriggerMutex);
5326 CameraMetadata &metadata = request->mSettingsList.begin()->metadata;
5327
5328 auto rotateAndCropEntry = metadata.find(ANDROID_SCALER_ROTATE_AND_CROP);
5329 if (rotateAndCropEntry.count > 0) {
5330 if (rotateAndCropEntry.data.u8[0] == mRotateAndCropOverride) {
5331 return false;
5332 } else {
5333 rotateAndCropEntry.data.u8[0] = mRotateAndCropOverride;
5334 return true;
5335 }
5336 } else {
5337 uint8_t rotateAndCrop_u8 = mRotateAndCropOverride;
5338 metadata.update(ANDROID_SCALER_ROTATE_AND_CROP,
5339 &rotateAndCrop_u8, 1);
5340 return true;
5341 }
5342 }
5343 return false;
5344}
5345
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005346/**
5347 * PreparerThread inner class methods
5348 */
5349
5350Camera3Device::PreparerThread::PreparerThread() :
Eino-Ville Talvala77c1a352016-06-13 12:32:43 -07005351 Thread(/*canCallJava*/false), mListener(nullptr),
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005352 mActive(false), mCancelNow(false), mCurrentMaxCount(0), mCurrentPrepareComplete(false) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005353}
5354
5355Camera3Device::PreparerThread::~PreparerThread() {
5356 Thread::requestExitAndWait();
5357 if (mCurrentStream != nullptr) {
5358 mCurrentStream->cancelPrepare();
5359 ATRACE_ASYNC_END("stream prepare", mCurrentStream->getId());
5360 mCurrentStream.clear();
5361 }
5362 clear();
5363}
5364
Ruben Brunkc78ac262015-08-13 17:58:46 -07005365status_t Camera3Device::PreparerThread::prepare(int maxCount, sp<Camera3StreamInterface>& stream) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005366 ATRACE_CALL();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005367 status_t res;
5368
5369 Mutex::Autolock l(mLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005370 sp<NotificationListener> listener = mListener.promote();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005371
Shuzhen Wangb3a0fb52018-09-13 17:24:08 -07005372 res = stream->startPrepare(maxCount, true /*blockRequest*/);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005373 if (res == OK) {
5374 // No preparation needed, fire listener right off
5375 ALOGV("%s: Stream %d already prepared", __FUNCTION__, stream->getId());
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005376 if (listener != NULL) {
5377 listener->notifyPrepared(stream->getId());
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005378 }
5379 return OK;
5380 } else if (res != NOT_ENOUGH_DATA) {
5381 return res;
5382 }
5383
5384 // Need to prepare, start up thread if necessary
5385 if (!mActive) {
5386 // mRunning will change to false before the thread fully shuts down, so wait to be sure it
5387 // isn't running
5388 Thread::requestExitAndWait();
5389 res = Thread::run("C3PrepThread", PRIORITY_BACKGROUND);
5390 if (res != OK) {
5391 ALOGE("%s: Unable to start preparer stream: %d (%s)", __FUNCTION__, res, strerror(-res));
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005392 if (listener != NULL) {
5393 listener->notifyPrepared(stream->getId());
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005394 }
5395 return res;
5396 }
5397 mCancelNow = false;
5398 mActive = true;
5399 ALOGV("%s: Preparer stream started", __FUNCTION__);
5400 }
5401
5402 // queue up the work
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005403 mPendingStreams.emplace(maxCount, stream);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005404 ALOGV("%s: Stream %d queued for preparing", __FUNCTION__, stream->getId());
5405
5406 return OK;
5407}
5408
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005409void Camera3Device::PreparerThread::pause() {
5410 ATRACE_CALL();
5411
5412 Mutex::Autolock l(mLock);
5413
5414 std::unordered_map<int, sp<camera3::Camera3StreamInterface> > pendingStreams;
5415 pendingStreams.insert(mPendingStreams.begin(), mPendingStreams.end());
5416 sp<camera3::Camera3StreamInterface> currentStream = mCurrentStream;
5417 int currentMaxCount = mCurrentMaxCount;
5418 mPendingStreams.clear();
5419 mCancelNow = true;
5420 while (mActive) {
5421 auto res = mThreadActiveSignal.waitRelative(mLock, kActiveTimeout);
5422 if (res == TIMED_OUT) {
5423 ALOGE("%s: Timed out waiting on prepare thread!", __FUNCTION__);
5424 return;
5425 } else if (res != OK) {
5426 ALOGE("%s: Encountered an error: %d waiting on prepare thread!", __FUNCTION__, res);
5427 return;
5428 }
5429 }
5430
5431 //Check whether the prepare thread was able to complete the current
5432 //stream. In case work is still pending emplace it along with the rest
5433 //of the streams in the pending list.
5434 if (currentStream != nullptr) {
5435 if (!mCurrentPrepareComplete) {
5436 pendingStreams.emplace(currentMaxCount, currentStream);
5437 }
5438 }
5439
5440 mPendingStreams.insert(pendingStreams.begin(), pendingStreams.end());
5441 for (const auto& it : mPendingStreams) {
5442 it.second->cancelPrepare();
5443 }
5444}
5445
5446status_t Camera3Device::PreparerThread::resume() {
5447 ATRACE_CALL();
5448 status_t res;
5449
5450 Mutex::Autolock l(mLock);
5451 sp<NotificationListener> listener = mListener.promote();
5452
5453 if (mActive) {
5454 ALOGE("%s: Trying to resume an already active prepare thread!", __FUNCTION__);
5455 return NO_INIT;
5456 }
5457
5458 auto it = mPendingStreams.begin();
5459 for (; it != mPendingStreams.end();) {
Shuzhen Wangb3a0fb52018-09-13 17:24:08 -07005460 res = it->second->startPrepare(it->first, true /*blockRequest*/);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005461 if (res == OK) {
5462 if (listener != NULL) {
5463 listener->notifyPrepared(it->second->getId());
5464 }
5465 it = mPendingStreams.erase(it);
5466 } else if (res != NOT_ENOUGH_DATA) {
5467 ALOGE("%s: Unable to start preparer stream: %d (%s)", __FUNCTION__,
5468 res, strerror(-res));
5469 it = mPendingStreams.erase(it);
5470 } else {
5471 it++;
5472 }
5473 }
5474
5475 if (mPendingStreams.empty()) {
5476 return OK;
5477 }
5478
5479 res = Thread::run("C3PrepThread", PRIORITY_BACKGROUND);
5480 if (res != OK) {
5481 ALOGE("%s: Unable to start preparer stream: %d (%s)",
5482 __FUNCTION__, res, strerror(-res));
5483 return res;
5484 }
5485 mCancelNow = false;
5486 mActive = true;
5487 ALOGV("%s: Preparer stream started", __FUNCTION__);
5488
5489 return OK;
5490}
5491
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005492status_t Camera3Device::PreparerThread::clear() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005493 ATRACE_CALL();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005494 Mutex::Autolock l(mLock);
5495
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005496 for (const auto& it : mPendingStreams) {
5497 it.second->cancelPrepare();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005498 }
5499 mPendingStreams.clear();
5500 mCancelNow = true;
5501
5502 return OK;
5503}
5504
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005505void Camera3Device::PreparerThread::setNotificationListener(wp<NotificationListener> listener) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005506 ATRACE_CALL();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005507 Mutex::Autolock l(mLock);
5508 mListener = listener;
5509}
5510
5511bool Camera3Device::PreparerThread::threadLoop() {
5512 status_t res;
5513 {
5514 Mutex::Autolock l(mLock);
5515 if (mCurrentStream == nullptr) {
5516 // End thread if done with work
5517 if (mPendingStreams.empty()) {
5518 ALOGV("%s: Preparer stream out of work", __FUNCTION__);
5519 // threadLoop _must not_ re-acquire mLock after it sets mActive to false; would
5520 // cause deadlock with prepare()'s requestExitAndWait triggered by !mActive.
5521 mActive = false;
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005522 mThreadActiveSignal.signal();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005523 return false;
5524 }
5525
5526 // Get next stream to prepare
5527 auto it = mPendingStreams.begin();
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005528 mCurrentStream = it->second;
5529 mCurrentMaxCount = it->first;
5530 mCurrentPrepareComplete = false;
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005531 mPendingStreams.erase(it);
5532 ATRACE_ASYNC_BEGIN("stream prepare", mCurrentStream->getId());
5533 ALOGV("%s: Preparing stream %d", __FUNCTION__, mCurrentStream->getId());
5534 } else if (mCancelNow) {
5535 mCurrentStream->cancelPrepare();
5536 ATRACE_ASYNC_END("stream prepare", mCurrentStream->getId());
5537 ALOGV("%s: Cancelling stream %d prepare", __FUNCTION__, mCurrentStream->getId());
5538 mCurrentStream.clear();
5539 mCancelNow = false;
5540 return true;
5541 }
5542 }
5543
5544 res = mCurrentStream->prepareNextBuffer();
5545 if (res == NOT_ENOUGH_DATA) return true;
5546 if (res != OK) {
5547 // Something bad happened; try to recover by cancelling prepare and
5548 // signalling listener anyway
5549 ALOGE("%s: Stream %d returned error %d (%s) during prepare", __FUNCTION__,
5550 mCurrentStream->getId(), res, strerror(-res));
5551 mCurrentStream->cancelPrepare();
5552 }
5553
5554 // This stream has finished, notify listener
5555 Mutex::Autolock l(mLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005556 sp<NotificationListener> listener = mListener.promote();
5557 if (listener != NULL) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005558 ALOGV("%s: Stream %d prepare done, signaling listener", __FUNCTION__,
5559 mCurrentStream->getId());
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005560 listener->notifyPrepared(mCurrentStream->getId());
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005561 }
5562
5563 ATRACE_ASYNC_END("stream prepare", mCurrentStream->getId());
5564 mCurrentStream.clear();
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005565 mCurrentPrepareComplete = true;
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005566
5567 return true;
5568}
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005569
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005570status_t Camera3Device::RequestBufferStateMachine::initialize(
5571 sp<camera3::StatusTracker> statusTracker) {
5572 if (statusTracker == nullptr) {
5573 ALOGE("%s: statusTracker is null", __FUNCTION__);
5574 return BAD_VALUE;
5575 }
5576
5577 std::lock_guard<std::mutex> lock(mLock);
5578 mStatusTracker = statusTracker;
5579 mRequestBufferStatusId = statusTracker->addComponent();
5580 return OK;
5581}
5582
5583bool Camera3Device::RequestBufferStateMachine::startRequestBuffer() {
5584 std::lock_guard<std::mutex> lock(mLock);
Yin-Chia Yeh8a4ccb02018-11-16 15:43:36 -08005585 if (mStatus == RB_STATUS_READY || mStatus == RB_STATUS_PENDING_STOP) {
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005586 mRequestBufferOngoing = true;
Yin-Chia Yeh8a4ccb02018-11-16 15:43:36 -08005587 notifyTrackerLocked(/*active*/true);
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005588 return true;
5589 }
5590 return false;
5591}
5592
5593void Camera3Device::RequestBufferStateMachine::endRequestBuffer() {
5594 std::lock_guard<std::mutex> lock(mLock);
5595 if (!mRequestBufferOngoing) {
5596 ALOGE("%s called without a successful startRequestBuffer call first!", __FUNCTION__);
5597 return;
5598 }
5599 mRequestBufferOngoing = false;
5600 if (mStatus == RB_STATUS_PENDING_STOP) {
5601 checkSwitchToStopLocked();
5602 }
Yin-Chia Yeh8a4ccb02018-11-16 15:43:36 -08005603 notifyTrackerLocked(/*active*/false);
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005604}
5605
5606void Camera3Device::RequestBufferStateMachine::onStreamsConfigured() {
5607 std::lock_guard<std::mutex> lock(mLock);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005608 mSwitchedToOffline = false;
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005609 mStatus = RB_STATUS_READY;
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005610 return;
5611}
5612
Yin-Chia Yehcd333fe2019-02-08 13:45:41 -08005613void Camera3Device::RequestBufferStateMachine::onSubmittingRequest() {
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005614 std::lock_guard<std::mutex> lock(mLock);
5615 mRequestThreadPaused = false;
Yin-Chia Yehcd333fe2019-02-08 13:45:41 -08005616 // inflight map register actually happens in prepareHalRequest now, but it is close enough
5617 // approximation.
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005618 mInflightMapEmpty = false;
5619 if (mStatus == RB_STATUS_STOPPED) {
5620 mStatus = RB_STATUS_READY;
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005621 }
5622 return;
5623}
5624
5625void Camera3Device::RequestBufferStateMachine::onRequestThreadPaused() {
5626 std::lock_guard<std::mutex> lock(mLock);
5627 mRequestThreadPaused = true;
5628 if (mStatus == RB_STATUS_PENDING_STOP) {
5629 checkSwitchToStopLocked();
5630 }
5631 return;
5632}
5633
5634void Camera3Device::RequestBufferStateMachine::onInflightMapEmpty() {
5635 std::lock_guard<std::mutex> lock(mLock);
5636 mInflightMapEmpty = true;
5637 if (mStatus == RB_STATUS_PENDING_STOP) {
5638 checkSwitchToStopLocked();
5639 }
5640 return;
5641}
5642
5643void Camera3Device::RequestBufferStateMachine::onWaitUntilIdle() {
5644 std::lock_guard<std::mutex> lock(mLock);
5645 if (!checkSwitchToStopLocked()) {
5646 mStatus = RB_STATUS_PENDING_STOP;
5647 }
5648 return;
5649}
5650
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005651bool Camera3Device::RequestBufferStateMachine::onSwitchToOfflineSuccess() {
5652 std::lock_guard<std::mutex> lock(mLock);
5653 if (mRequestBufferOngoing) {
5654 ALOGE("%s: HAL must not be requesting buffer after HAL returns switchToOffline!",
5655 __FUNCTION__);
5656 return false;
5657 }
5658 mSwitchedToOffline = true;
5659 mInflightMapEmpty = true;
5660 mRequestThreadPaused = true;
5661 mStatus = RB_STATUS_STOPPED;
5662 return true;
5663}
5664
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005665void Camera3Device::RequestBufferStateMachine::notifyTrackerLocked(bool active) {
5666 sp<StatusTracker> statusTracker = mStatusTracker.promote();
5667 if (statusTracker != nullptr) {
5668 if (active) {
5669 statusTracker->markComponentActive(mRequestBufferStatusId);
5670 } else {
5671 statusTracker->markComponentIdle(mRequestBufferStatusId, Fence::NO_FENCE);
5672 }
5673 }
5674}
5675
5676bool Camera3Device::RequestBufferStateMachine::checkSwitchToStopLocked() {
5677 if (mInflightMapEmpty && mRequestThreadPaused && !mRequestBufferOngoing) {
5678 mStatus = RB_STATUS_STOPPED;
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005679 return true;
5680 }
5681 return false;
5682}
5683
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005684bool Camera3Device::startRequestBuffer() {
5685 return mRequestBufferSM.startRequestBuffer();
5686}
Shuzhen Wang268a1362018-10-16 16:32:59 -07005687
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005688void Camera3Device::endRequestBuffer() {
5689 mRequestBufferSM.endRequestBuffer();
5690}
Shuzhen Wang268a1362018-10-16 16:32:59 -07005691
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005692nsecs_t Camera3Device::getWaitDuration() {
5693 return kBaseGetBufferWait + getExpectedInFlightDuration();
5694}
Shuzhen Wang268a1362018-10-16 16:32:59 -07005695
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005696void Camera3Device::getInflightBufferKeys(std::vector<std::pair<int32_t, int32_t>>* out) {
5697 mInterface->getInflightBufferKeys(out);
5698}
Shuzhen Wang268a1362018-10-16 16:32:59 -07005699
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005700void Camera3Device::getInflightRequestBufferKeys(std::vector<uint64_t>* out) {
5701 mInterface->getInflightRequestBufferKeys(out);
5702}
Shuzhen Wang268a1362018-10-16 16:32:59 -07005703
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005704std::vector<sp<Camera3StreamInterface>> Camera3Device::getAllStreams() {
5705 std::vector<sp<Camera3StreamInterface>> ret;
5706 bool hasInputStream = mInputStream != nullptr;
5707 ret.reserve(mOutputStreams.size() + mDeletedStreams.size() + ((hasInputStream) ? 1 : 0));
5708 if (hasInputStream) {
5709 ret.push_back(mInputStream);
Shuzhen Wang268a1362018-10-16 16:32:59 -07005710 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005711 for (size_t i = 0; i < mOutputStreams.size(); i++) {
5712 ret.push_back(mOutputStreams[i]);
5713 }
5714 for (size_t i = 0; i < mDeletedStreams.size(); i++) {
5715 ret.push_back(mDeletedStreams[i]);
5716 }
5717 return ret;
Shuzhen Wang268a1362018-10-16 16:32:59 -07005718}
5719
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005720status_t Camera3Device::switchToOffline(
5721 const std::vector<int32_t>& streamsToKeep,
5722 /*out*/ sp<CameraOfflineSessionBase>* session) {
5723 ATRACE_CALL();
5724 if (session == nullptr) {
5725 ALOGE("%s: session must not be null", __FUNCTION__);
5726 return BAD_VALUE;
5727 }
5728
5729 Mutex::Autolock il(mInterfaceLock);
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005730
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005731 bool hasInputStream = mInputStream != nullptr;
5732 int32_t inputStreamId = hasInputStream ? mInputStream->getId() : -1;
5733 bool inputStreamSupportsOffline = hasInputStream ?
5734 mInputStream->getOfflineProcessingSupport() : false;
5735 auto outputStreamIds = mOutputStreams.getStreamIds();
5736 auto streamIds = outputStreamIds;
5737 if (hasInputStream) {
5738 streamIds.push_back(mInputStream->getId());
5739 }
5740
5741 // Check all streams in streamsToKeep supports offline mode
5742 for (auto id : streamsToKeep) {
5743 if (std::find(streamIds.begin(), streamIds.end(), id) == streamIds.end()) {
5744 ALOGE("%s: Unknown stream ID %d", __FUNCTION__, id);
5745 return BAD_VALUE;
5746 } else if (id == inputStreamId) {
5747 if (!inputStreamSupportsOffline) {
5748 ALOGE("%s: input stream %d cannot be switched to offline",
5749 __FUNCTION__, id);
5750 return BAD_VALUE;
5751 }
5752 } else {
5753 sp<camera3::Camera3OutputStreamInterface> stream = mOutputStreams.get(id);
5754 if (!stream->getOfflineProcessingSupport()) {
5755 ALOGE("%s: output stream %d cannot be switched to offline",
5756 __FUNCTION__, id);
5757 return BAD_VALUE;
5758 }
5759 }
5760 }
5761
5762 // TODO: block surface sharing and surface group streams until we can support them
5763
5764 // Stop repeating request, wait until all remaining requests are submitted, then call into
5765 // HAL switchToOffline
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005766 hardware::camera::device::V3_6::CameraOfflineSessionInfo offlineSessionInfo;
5767 sp<hardware::camera::device::V3_6::ICameraOfflineSession> offlineSession;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005768 camera3::BufferRecords bufferRecords;
5769 status_t ret = mRequestThread->switchToOffline(
5770 streamsToKeep, &offlineSessionInfo, &offlineSession, &bufferRecords);
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005771
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005772 if (ret != OK) {
5773 SET_ERR("Switch to offline failed: %s (%d)", strerror(-ret), ret);
5774 return ret;
5775 }
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005776
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005777 bool succ = mRequestBufferSM.onSwitchToOfflineSuccess();
5778 if (!succ) {
5779 SET_ERR("HAL must not be calling requestStreamBuffers call");
5780 // TODO: block ALL callbacks from HAL till app configured new streams?
5781 return UNKNOWN_ERROR;
5782 }
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005783
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005784 // Verify offlineSessionInfo
5785 std::vector<int32_t> offlineStreamIds;
5786 offlineStreamIds.reserve(offlineSessionInfo.offlineStreams.size());
5787 for (auto offlineStream : offlineSessionInfo.offlineStreams) {
5788 // verify stream IDs
5789 int32_t id = offlineStream.id;
5790 if (std::find(streamIds.begin(), streamIds.end(), id) == streamIds.end()) {
5791 SET_ERR("stream ID %d not found!", id);
5792 return UNKNOWN_ERROR;
5793 }
5794
5795 // When not using HAL buf manager, only allow streams requested by app to be preserved
5796 if (!mUseHalBufManager) {
5797 if (std::find(streamsToKeep.begin(), streamsToKeep.end(), id) == streamsToKeep.end()) {
5798 SET_ERR("stream ID %d must not be switched to offline!", id);
5799 return UNKNOWN_ERROR;
5800 }
5801 }
5802
5803 offlineStreamIds.push_back(id);
5804 sp<Camera3StreamInterface> stream = (id == inputStreamId) ?
5805 static_cast<sp<Camera3StreamInterface>>(mInputStream) :
5806 static_cast<sp<Camera3StreamInterface>>(mOutputStreams.get(id));
5807 // Verify number of outstanding buffers
5808 if (stream->getOutstandingBuffersCount() != offlineStream.numOutstandingBuffers) {
5809 SET_ERR("Offline stream %d # of remaining buffer mismatch: (%zu,%d) (service/HAL)",
5810 id, stream->getOutstandingBuffersCount(), offlineStream.numOutstandingBuffers);
5811 return UNKNOWN_ERROR;
5812 }
5813 }
5814
5815 // Verify all streams to be deleted don't have any outstanding buffers
5816 if (hasInputStream && std::find(offlineStreamIds.begin(), offlineStreamIds.end(),
5817 inputStreamId) == offlineStreamIds.end()) {
5818 if (mInputStream->hasOutstandingBuffers()) {
5819 SET_ERR("Input stream %d still has %zu outstanding buffer!",
5820 inputStreamId, mInputStream->getOutstandingBuffersCount());
5821 return UNKNOWN_ERROR;
5822 }
5823 }
5824
5825 for (const auto& outStreamId : outputStreamIds) {
5826 if (std::find(offlineStreamIds.begin(), offlineStreamIds.end(),
5827 outStreamId) == offlineStreamIds.end()) {
5828 auto outStream = mOutputStreams.get(outStreamId);
5829 if (outStream->hasOutstandingBuffers()) {
5830 SET_ERR("Output stream %d still has %zu outstanding buffer!",
5831 outStreamId, outStream->getOutstandingBuffersCount());
5832 return UNKNOWN_ERROR;
5833 }
5834 }
5835 }
5836
5837 InFlightRequestMap offlineReqs;
5838 // Verify inflight requests and their pending buffers
5839 {
5840 std::lock_guard<std::mutex> l(mInFlightLock);
5841 for (auto offlineReq : offlineSessionInfo.offlineRequests) {
5842 int idx = mInFlightMap.indexOfKey(offlineReq.frameNumber);
5843 if (idx == NAME_NOT_FOUND) {
5844 SET_ERR("Offline request frame number %d not found!", offlineReq.frameNumber);
5845 return UNKNOWN_ERROR;
5846 }
5847
5848 const auto& inflightReq = mInFlightMap.valueAt(idx);
5849 // TODO: check specific stream IDs
5850 size_t numBuffersLeft = static_cast<size_t>(inflightReq.numBuffersLeft);
5851 if (numBuffersLeft != offlineReq.pendingStreams.size()) {
5852 SET_ERR("Offline request # of remaining buffer mismatch: (%d,%d) (service/HAL)",
5853 inflightReq.numBuffersLeft, offlineReq.pendingStreams.size());
5854 return UNKNOWN_ERROR;
5855 }
5856 offlineReqs.add(offlineReq.frameNumber, inflightReq);
5857 }
5858 }
5859
5860 // Create Camera3OfflineSession and transfer object ownership
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005861 // (streams, inflight requests, buffer caches)
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005862 camera3::StreamSet offlineStreamSet;
5863 sp<camera3::Camera3Stream> inputStream;
5864 for (auto offlineStream : offlineSessionInfo.offlineStreams) {
5865 int32_t id = offlineStream.id;
5866 if (mInputStream != nullptr && id == mInputStream->getId()) {
5867 inputStream = mInputStream;
5868 } else {
5869 offlineStreamSet.add(id, mOutputStreams.get(id));
5870 }
5871 }
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005872
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005873 // TODO: check if we need to lock before copying states
5874 // though technically no other thread should be talking to Camera3Device at this point
5875 Camera3OfflineStates offlineStates(
5876 mTagMonitor, mVendorTagId, mUseHalBufManager, mNeedFixupMonochromeTags,
5877 mUsePartialResult, mNumPartialResults, mNextResultFrameNumber,
5878 mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
5879 mNextShutterFrameNumber, mNextReprocessShutterFrameNumber,
5880 mNextZslStillShutterFrameNumber, mDeviceInfo, mPhysicalDeviceInfoMap,
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08005881 mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005882
5883 *session = new Camera3OfflineSession(mId, inputStream, offlineStreamSet,
5884 std::move(bufferRecords), offlineReqs, offlineStates, offlineSession);
5885
5886 // Delete all streams that has been transferred to offline session
5887 Mutex::Autolock l(mLock);
5888 for (auto offlineStream : offlineSessionInfo.offlineStreams) {
5889 int32_t id = offlineStream.id;
5890 if (mInputStream != nullptr && id == mInputStream->getId()) {
5891 mInputStream.clear();
5892 } else {
5893 mOutputStreams.remove(id);
5894 }
5895 }
5896
5897 // disconnect all other streams and switch to UNCONFIGURED state
5898 if (mInputStream != nullptr) {
5899 ret = mInputStream->disconnect();
5900 if (ret != OK) {
5901 SET_ERR_L("disconnect input stream failed!");
5902 return UNKNOWN_ERROR;
5903 }
5904 }
5905
5906 for (auto streamId : mOutputStreams.getStreamIds()) {
5907 sp<Camera3StreamInterface> stream = mOutputStreams.get(streamId);
5908 ret = stream->disconnect();
5909 if (ret != OK) {
5910 SET_ERR_L("disconnect output stream %d failed!", streamId);
5911 return UNKNOWN_ERROR;
5912 }
5913 }
5914
5915 mInputStream.clear();
5916 mOutputStreams.clear();
5917 mNeedConfig = true;
5918 internalUpdateStatusLocked(STATUS_UNCONFIGURED);
5919 mOperatingMode = NO_MODE;
5920 mIsConstrainedHighSpeedConfiguration = false;
5921
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005922 return OK;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005923 // TO be done by CameraDeviceClient/Camera3OfflineSession
5924 // register the offline client to camera service
5925 // Setup result passthing threads etc
5926 // Initialize offline session so HAL can start sending callback to it (result Fmq)
5927 // TODO: check how many onIdle callback will be sent
5928 // Java side to make sure the CameraCaptureSession is properly closed
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005929}
5930
Emilian Peevcc0b7952020-01-07 13:54:47 -08005931void Camera3Device::getOfflineStreamIds(std::vector<int> *offlineStreamIds) {
5932 ATRACE_CALL();
5933
5934 if (offlineStreamIds == nullptr) {
5935 return;
5936 }
5937
5938 Mutex::Autolock il(mInterfaceLock);
5939
5940 auto streamIds = mOutputStreams.getStreamIds();
5941 bool hasInputStream = mInputStream != nullptr;
5942 if (hasInputStream && mInputStream->getOfflineProcessingSupport()) {
5943 offlineStreamIds->push_back(mInputStream->getId());
5944 }
5945
5946 for (const auto & streamId : streamIds) {
5947 sp<camera3::Camera3OutputStreamInterface> stream = mOutputStreams.get(streamId);
5948 // Streams that use the camera buffer manager are currently not supported in
5949 // offline mode
5950 if (stream->getOfflineProcessingSupport() &&
5951 (stream->getStreamSetId() == CAMERA3_STREAM_SET_ID_INVALID)) {
5952 offlineStreamIds->push_back(streamId);
5953 }
5954 }
5955}
5956
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08005957status_t Camera3Device::setRotateAndCropAutoBehavior(
5958 camera_metadata_enum_android_scaler_rotate_and_crop_t rotateAndCropValue) {
5959 ATRACE_CALL();
5960 Mutex::Autolock il(mInterfaceLock);
5961 Mutex::Autolock l(mLock);
5962 if (mRequestThread == nullptr) {
5963 return INVALID_OPERATION;
5964 }
5965 return mRequestThread->setRotateAndCropAutoBehavior(rotateAndCropValue);
5966}
5967
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08005968}; // namespace android