blob: 0385a6f63e98f22f612c35d8e041f1b28b4d58e7 [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 Talvala7fa43f32013-02-06 17:20:07 -0800354 return OK;
355}
356
357status_t Camera3Device::disconnect() {
Yin-Chia Yehc5248132018-08-15 12:19:20 -0700358 return disconnectImpl();
359}
360
361status_t Camera3Device::disconnectImpl() {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800362 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700363 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800364
Yin-Chia Yehe1c80632016-08-08 14:48:05 -0700365 ALOGI("%s: E", __FUNCTION__);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800366
Eino-Ville Talvala214a17f2013-06-13 12:20:02 -0700367 status_t res = OK;
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700368 std::vector<wp<Camera3StreamInterface>> streams;
Yin-Chia Yeh598fc602017-07-24 11:37:23 -0700369 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700370 {
371 Mutex::Autolock l(mLock);
372 if (mStatus == STATUS_UNINITIALIZED) return res;
373
374 if (mStatus == STATUS_ACTIVE ||
375 (mStatus == STATUS_ERROR && mRequestThread != NULL)) {
376 res = mRequestThread->clearRepeatingRequests();
Eino-Ville Talvala214a17f2013-06-13 12:20:02 -0700377 if (res != OK) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700378 SET_ERR_L("Can't stop streaming");
Eino-Ville Talvala214a17f2013-06-13 12:20:02 -0700379 // Continue to close device even in case of error
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700380 } else {
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -0700381 res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700382 if (res != OK) {
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -0700383 SET_ERR_L("Timeout waiting for HAL to drain (% " PRIi64 " ns)",
384 maxExpectedDuration);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700385 // Continue to close device even in case of error
386 }
Eino-Ville Talvala214a17f2013-06-13 12:20:02 -0700387 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800388 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800389
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700390 if (mStatus == STATUS_ERROR) {
391 CLOGE("Shutting down in an error state");
Eino-Ville Talvala214a17f2013-06-13 12:20:02 -0700392 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700393
394 if (mStatusTracker != NULL) {
395 mStatusTracker->requestExit();
396 }
397
398 if (mRequestThread != NULL) {
399 mRequestThread->requestExit();
400 }
401
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700402 streams.reserve(mOutputStreams.size() + (mInputStream != nullptr ? 1 : 0));
403 for (size_t i = 0; i < mOutputStreams.size(); i++) {
404 streams.push_back(mOutputStreams[i]);
405 }
406 if (mInputStream != nullptr) {
407 streams.push_back(mInputStream);
408 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700409 }
410
411 // Joining done without holding mLock, otherwise deadlocks may ensue
412 // as the threads try to access parent state
413 if (mRequestThread != NULL && mStatus != STATUS_ERROR) {
414 // HAL may be in a bad state, so waiting for request thread
415 // (which may be stuck in the HAL processCaptureRequest call)
416 // could be dangerous.
417 mRequestThread->join();
418 }
419
420 if (mStatusTracker != NULL) {
421 mStatusTracker->join();
422 }
423
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800424 HalInterface* interface;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700425 {
426 Mutex::Autolock l(mLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800427 mRequestThread.clear();
Emilian Peev2843c362018-09-26 08:49:40 +0100428 Mutex::Autolock stLock(mTrackerLock);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700429 mStatusTracker.clear();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800430 interface = mInterface.get();
Eino-Ville Talvalaefff1c42015-08-28 16:27:27 -0700431 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800432
Eino-Ville Talvalaefff1c42015-08-28 16:27:27 -0700433 // Call close without internal mutex held, as the HAL close may need to
434 // wait on assorted callbacks,etc, to complete before it can return.
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800435 interface->close();
Eino-Ville Talvalaefff1c42015-08-28 16:27:27 -0700436
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700437 flushInflightRequests();
438
Eino-Ville Talvalaefff1c42015-08-28 16:27:27 -0700439 {
440 Mutex::Autolock l(mLock);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800441 mInterface->clear();
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700442 mOutputStreams.clear();
443 mInputStream.clear();
Yin-Chia Yeh5090c732017-07-20 16:05:29 -0700444 mDeletedStreams.clear();
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700445 mBufferManager.clear();
Ruben Brunk183f0562015-08-12 12:55:02 -0700446 internalUpdateStatusLocked(STATUS_UNINITIALIZED);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700447 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800448
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700449 for (auto& weakStream : streams) {
450 sp<Camera3StreamInterface> stream = weakStream.promote();
451 if (stream != nullptr) {
452 ALOGE("%s: Stream %d leaked! strong reference (%d)!",
453 __FUNCTION__, stream->getId(), stream->getStrongCount() - 1);
454 }
455 }
456
Yin-Chia Yehe1c80632016-08-08 14:48:05 -0700457 ALOGI("%s: X", __FUNCTION__);
Eino-Ville Talvala214a17f2013-06-13 12:20:02 -0700458 return res;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800459}
460
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700461// For dumping/debugging only -
462// try to acquire a lock a few times, eventually give up to proceed with
463// debug/dump operations
464bool Camera3Device::tryLockSpinRightRound(Mutex& lock) {
465 bool gotLock = false;
466 for (size_t i = 0; i < kDumpLockAttempts; ++i) {
467 if (lock.tryLock() == NO_ERROR) {
468 gotLock = true;
469 break;
470 } else {
471 usleep(kDumpSleepDuration);
472 }
473 }
474 return gotLock;
475}
476
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700477Camera3Device::Size Camera3Device::getMaxJpegResolution() const {
478 int32_t maxJpegWidth = 0, maxJpegHeight = 0;
Emilian Peev08dd2452017-04-06 16:55:14 +0100479 const int STREAM_CONFIGURATION_SIZE = 4;
480 const int STREAM_FORMAT_OFFSET = 0;
481 const int STREAM_WIDTH_OFFSET = 1;
482 const int STREAM_HEIGHT_OFFSET = 2;
483 const int STREAM_IS_INPUT_OFFSET = 3;
484 camera_metadata_ro_entry_t availableStreamConfigs =
485 mDeviceInfo.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
486 if (availableStreamConfigs.count == 0 ||
487 availableStreamConfigs.count % STREAM_CONFIGURATION_SIZE != 0) {
488 return Size(0, 0);
489 }
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700490
Emilian Peev08dd2452017-04-06 16:55:14 +0100491 // Get max jpeg size (area-wise).
492 for (size_t i=0; i < availableStreamConfigs.count; i+= STREAM_CONFIGURATION_SIZE) {
493 int32_t format = availableStreamConfigs.data.i32[i + STREAM_FORMAT_OFFSET];
494 int32_t width = availableStreamConfigs.data.i32[i + STREAM_WIDTH_OFFSET];
495 int32_t height = availableStreamConfigs.data.i32[i + STREAM_HEIGHT_OFFSET];
496 int32_t isInput = availableStreamConfigs.data.i32[i + STREAM_IS_INPUT_OFFSET];
497 if (isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT
498 && format == HAL_PIXEL_FORMAT_BLOB &&
499 (width * height > maxJpegWidth * maxJpegHeight)) {
500 maxJpegWidth = width;
501 maxJpegHeight = height;
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700502 }
503 }
Emilian Peev08dd2452017-04-06 16:55:14 +0100504
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700505 return Size(maxJpegWidth, maxJpegHeight);
506}
507
Shuzhen Wangc28dccc2016-02-11 23:48:46 -0800508nsecs_t Camera3Device::getMonoToBoottimeOffset() {
509 // try three times to get the clock offset, choose the one
510 // with the minimum gap in measurements.
511 const int tries = 3;
512 nsecs_t bestGap, measured;
513 for (int i = 0; i < tries; ++i) {
514 const nsecs_t tmono = systemTime(SYSTEM_TIME_MONOTONIC);
515 const nsecs_t tbase = systemTime(SYSTEM_TIME_BOOTTIME);
516 const nsecs_t tmono2 = systemTime(SYSTEM_TIME_MONOTONIC);
517 const nsecs_t gap = tmono2 - tmono;
518 if (i == 0 || gap < bestGap) {
519 bestGap = gap;
520 measured = tbase - ((tmono + tmono2) >> 1);
521 }
522 }
523 return measured;
524}
525
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800526hardware::graphics::common::V1_0::PixelFormat Camera3Device::mapToPixelFormat(
527 int frameworkFormat) {
528 return (hardware::graphics::common::V1_0::PixelFormat) frameworkFormat;
529}
530
531DataspaceFlags Camera3Device::mapToHidlDataspace(
532 android_dataspace dataSpace) {
533 return dataSpace;
534}
535
Chia-I Wu67a0c0e2017-04-06 13:37:01 -0700536BufferUsageFlags Camera3Device::mapToConsumerUsage(
Emilian Peev050f5dc2017-05-18 14:43:56 +0100537 uint64_t usage) {
Yin-Chia Yeh47cf8e62017-04-04 13:00:03 -0700538 return usage;
539}
540
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800541StreamRotation Camera3Device::mapToStreamRotation(camera3_stream_rotation_t rotation) {
542 switch (rotation) {
543 case CAMERA3_STREAM_ROTATION_0:
544 return StreamRotation::ROTATION_0;
545 case CAMERA3_STREAM_ROTATION_90:
546 return StreamRotation::ROTATION_90;
547 case CAMERA3_STREAM_ROTATION_180:
548 return StreamRotation::ROTATION_180;
549 case CAMERA3_STREAM_ROTATION_270:
550 return StreamRotation::ROTATION_270;
551 }
552 ALOGE("%s: Unknown stream rotation %d", __FUNCTION__, rotation);
553 return StreamRotation::ROTATION_0;
554}
555
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -0800556status_t Camera3Device::mapToStreamConfigurationMode(
557 camera3_stream_configuration_mode_t operationMode, StreamConfigurationMode *mode) {
558 if (mode == nullptr) return BAD_VALUE;
559 if (operationMode < CAMERA3_VENDOR_STREAM_CONFIGURATION_MODE_START) {
560 switch(operationMode) {
561 case CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE:
562 *mode = StreamConfigurationMode::NORMAL_MODE;
563 break;
564 case CAMERA3_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE:
565 *mode = StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE;
566 break;
567 default:
568 ALOGE("%s: Unknown stream configuration mode %d", __FUNCTION__, operationMode);
569 return BAD_VALUE;
570 }
571 } else {
572 *mode = static_cast<StreamConfigurationMode>(operationMode);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800573 }
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -0800574 return OK;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800575}
576
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800577int Camera3Device::mapToFrameworkFormat(
578 hardware::graphics::common::V1_0::PixelFormat pixelFormat) {
579 return static_cast<uint32_t>(pixelFormat);
580}
581
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -0700582android_dataspace Camera3Device::mapToFrameworkDataspace(
583 DataspaceFlags dataSpace) {
584 return static_cast<android_dataspace>(dataSpace);
585}
586
Emilian Peev050f5dc2017-05-18 14:43:56 +0100587uint64_t Camera3Device::mapConsumerToFrameworkUsage(
Chia-I Wu67a0c0e2017-04-06 13:37:01 -0700588 BufferUsageFlags usage) {
Yin-Chia Yeh47cf8e62017-04-04 13:00:03 -0700589 return usage;
590}
591
Emilian Peev050f5dc2017-05-18 14:43:56 +0100592uint64_t Camera3Device::mapProducerToFrameworkUsage(
Chia-I Wu67a0c0e2017-04-06 13:37:01 -0700593 BufferUsageFlags usage) {
Yin-Chia Yeh47cf8e62017-04-04 13:00:03 -0700594 return usage;
595}
596
Zhijun Hef7da0962014-04-24 13:27:56 -0700597ssize_t Camera3Device::getJpegBufferSize(uint32_t width, uint32_t height) const {
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700598 // Get max jpeg size (area-wise).
599 Size maxJpegResolution = getMaxJpegResolution();
600 if (maxJpegResolution.width == 0) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800601 ALOGE("%s: Camera %s: Can't find valid available jpeg sizes in static metadata!",
602 __FUNCTION__, mId.string());
Zhijun Hef7da0962014-04-24 13:27:56 -0700603 return BAD_VALUE;
604 }
605
Zhijun Hef7da0962014-04-24 13:27:56 -0700606 // Get max jpeg buffer size
607 ssize_t maxJpegBufferSize = 0;
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700608 camera_metadata_ro_entry jpegBufMaxSize = mDeviceInfo.find(ANDROID_JPEG_MAX_SIZE);
609 if (jpegBufMaxSize.count == 0) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800610 ALOGE("%s: Camera %s: Can't find maximum JPEG size in static metadata!", __FUNCTION__,
611 mId.string());
Zhijun Hef7da0962014-04-24 13:27:56 -0700612 return BAD_VALUE;
613 }
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700614 maxJpegBufferSize = jpegBufMaxSize.data.i32[0];
Yin-Chia Yeh0c4e56d2015-01-09 15:21:27 -0800615 assert(kMinJpegBufferSize < maxJpegBufferSize);
Zhijun Hef7da0962014-04-24 13:27:56 -0700616
617 // Calculate final jpeg buffer size for the given resolution.
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700618 float scaleFactor = ((float) (width * height)) /
619 (maxJpegResolution.width * maxJpegResolution.height);
Yin-Chia Yeh0c4e56d2015-01-09 15:21:27 -0800620 ssize_t jpegBufferSize = scaleFactor * (maxJpegBufferSize - kMinJpegBufferSize) +
621 kMinJpegBufferSize;
Zhijun Hef7da0962014-04-24 13:27:56 -0700622 if (jpegBufferSize > maxJpegBufferSize) {
623 jpegBufferSize = maxJpegBufferSize;
Zhijun Hef7da0962014-04-24 13:27:56 -0700624 }
625
626 return jpegBufferSize;
627}
628
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -0700629ssize_t Camera3Device::getPointCloudBufferSize() const {
630 const int FLOATS_PER_POINT=4;
631 camera_metadata_ro_entry maxPointCount = mDeviceInfo.find(ANDROID_DEPTH_MAX_DEPTH_SAMPLES);
632 if (maxPointCount.count == 0) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800633 ALOGE("%s: Camera %s: Can't find maximum depth point cloud size in static metadata!",
634 __FUNCTION__, mId.string());
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -0700635 return BAD_VALUE;
636 }
637 ssize_t maxBytesForPointCloud = sizeof(android_depth_points) +
638 maxPointCount.data.i32[0] * sizeof(float) * FLOATS_PER_POINT;
639 return maxBytesForPointCloud;
640}
641
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800642ssize_t Camera3Device::getRawOpaqueBufferSize(int32_t width, int32_t height) const {
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800643 const int PER_CONFIGURATION_SIZE = 3;
644 const int WIDTH_OFFSET = 0;
645 const int HEIGHT_OFFSET = 1;
646 const int SIZE_OFFSET = 2;
647 camera_metadata_ro_entry rawOpaqueSizes =
648 mDeviceInfo.find(ANDROID_SENSOR_OPAQUE_RAW_SIZE);
Aurimas Liutikasbc57b122016-02-16 09:59:16 -0800649 size_t count = rawOpaqueSizes.count;
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800650 if (count == 0 || (count % PER_CONFIGURATION_SIZE)) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800651 ALOGE("%s: Camera %s: bad opaque RAW size static metadata length(%zu)!",
652 __FUNCTION__, mId.string(), count);
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800653 return BAD_VALUE;
654 }
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -0700655
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800656 for (size_t i = 0; i < count; i += PER_CONFIGURATION_SIZE) {
657 if (width == rawOpaqueSizes.data.i32[i + WIDTH_OFFSET] &&
658 height == rawOpaqueSizes.data.i32[i + HEIGHT_OFFSET]) {
659 return rawOpaqueSizes.data.i32[i + SIZE_OFFSET];
660 }
661 }
662
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800663 ALOGE("%s: Camera %s: cannot find size for %dx%d opaque RAW image!",
664 __FUNCTION__, mId.string(), width, height);
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800665 return BAD_VALUE;
666}
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -0700667
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800668status_t Camera3Device::dump(int fd, const Vector<String16> &args) {
669 ATRACE_CALL();
670 (void)args;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700671
672 // Try to lock, but continue in case of failure (to avoid blocking in
673 // deadlocks)
674 bool gotInterfaceLock = tryLockSpinRightRound(mInterfaceLock);
675 bool gotLock = tryLockSpinRightRound(mLock);
676
677 ALOGW_IF(!gotInterfaceLock,
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800678 "Camera %s: %s: Unable to lock interface lock, proceeding anyway",
679 mId.string(), __FUNCTION__);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700680 ALOGW_IF(!gotLock,
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800681 "Camera %s: %s: Unable to lock main lock, proceeding anyway",
682 mId.string(), __FUNCTION__);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700683
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800684 bool dumpTemplates = false;
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700685
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800686 String16 templatesOption("-t");
687 int n = args.size();
688 for (int i = 0; i < n; i++) {
689 if (args[i] == templatesOption) {
690 dumpTemplates = true;
691 }
Emilian Peevbd8c5032018-02-14 23:05:40 +0000692 if (args[i] == TagMonitor::kMonitorOption) {
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700693 if (i + 1 < n) {
694 String8 monitorTags = String8(args[i + 1]);
695 if (monitorTags == "off") {
696 mTagMonitor.disableMonitoring();
697 } else {
698 mTagMonitor.parseTagsToMonitor(monitorTags);
699 }
700 } else {
701 mTagMonitor.disableMonitoring();
702 }
703 }
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800704 }
705
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800706 String8 lines;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800707
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800708 const char *status =
709 mStatus == STATUS_ERROR ? "ERROR" :
710 mStatus == STATUS_UNINITIALIZED ? "UNINITIALIZED" :
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700711 mStatus == STATUS_UNCONFIGURED ? "UNCONFIGURED" :
712 mStatus == STATUS_CONFIGURED ? "CONFIGURED" :
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800713 mStatus == STATUS_ACTIVE ? "ACTIVE" :
714 "Unknown";
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700715
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800716 lines.appendFormat(" Device status: %s\n", status);
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -0700717 if (mStatus == STATUS_ERROR) {
718 lines.appendFormat(" Error cause: %s\n", mErrorCause.string());
719 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800720 lines.appendFormat(" Stream configuration:\n");
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -0800721 const char *mode =
722 mOperatingMode == static_cast<int>(StreamConfigurationMode::NORMAL_MODE) ? "NORMAL" :
723 mOperatingMode == static_cast<int>(
724 StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE) ? "CONSTRAINED_HIGH_SPEED" :
725 "CUSTOM";
726 lines.appendFormat(" Operation mode: %s (%d) \n", mode, mOperatingMode);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800727
728 if (mInputStream != NULL) {
729 write(fd, lines.string(), lines.size());
730 mInputStream->dump(fd, args);
731 } else {
732 lines.appendFormat(" No input stream.\n");
733 write(fd, lines.string(), lines.size());
734 }
735 for (size_t i = 0; i < mOutputStreams.size(); i++) {
736 mOutputStreams[i]->dump(fd,args);
737 }
738
Zhijun He431503c2016-03-07 17:30:16 -0800739 if (mBufferManager != NULL) {
740 lines = String8(" Camera3 Buffer Manager:\n");
741 write(fd, lines.string(), lines.size());
742 mBufferManager->dump(fd, args);
743 }
Zhijun He125684a2015-12-26 15:07:30 -0800744
Eino-Ville Talvala42368d92013-04-09 14:13:50 -0700745 lines = String8(" In-flight requests:\n");
746 if (mInFlightMap.size() == 0) {
747 lines.append(" None\n");
748 } else {
749 for (size_t i = 0; i < mInFlightMap.size(); i++) {
750 InFlightRequest r = mInFlightMap.valueAt(i);
Colin Crosse5729fa2014-03-21 15:04:25 -0700751 lines.appendFormat(" Frame %d | Timestamp: %" PRId64 ", metadata"
Eino-Ville Talvala42368d92013-04-09 14:13:50 -0700752 " arrived: %s, buffers left: %d\n", mInFlightMap.keyAt(i),
Chien-Yu Chen43e69a62014-11-25 16:38:33 -0800753 r.shutterTimestamp, r.haveResultMetadata ? "true" : "false",
Eino-Ville Talvala42368d92013-04-09 14:13:50 -0700754 r.numBuffersLeft);
755 }
756 }
757 write(fd, lines.string(), lines.size());
758
Shuzhen Wang686f6442017-06-20 16:16:04 -0700759 if (mRequestThread != NULL) {
760 mRequestThread->dumpCaptureRequestLatency(fd,
761 " ProcessCaptureRequest latency histogram:");
762 }
763
Igor Murashkin1e479c02013-09-06 16:55:14 -0700764 {
765 lines = String8(" Last request sent:\n");
766 write(fd, lines.string(), lines.size());
767
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700768 CameraMetadata lastRequest = getLatestRequestLocked();
Igor Murashkin1e479c02013-09-06 16:55:14 -0700769 lastRequest.dump(fd, /*verbosity*/2, /*indentation*/6);
770 }
771
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800772 if (dumpTemplates) {
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -0800773 const char *templateNames[CAMERA3_TEMPLATE_COUNT] = {
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800774 "TEMPLATE_PREVIEW",
775 "TEMPLATE_STILL_CAPTURE",
776 "TEMPLATE_VIDEO_RECORD",
777 "TEMPLATE_VIDEO_SNAPSHOT",
778 "TEMPLATE_ZERO_SHUTTER_LAG",
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -0800779 "TEMPLATE_MANUAL",
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800780 };
781
782 for (int i = 1; i < CAMERA3_TEMPLATE_COUNT; i++) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800783 camera_metadata_t *templateRequest = nullptr;
784 mInterface->constructDefaultRequestSettings(
785 (camera3_request_template_t) i, &templateRequest);
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800786 lines = String8::format(" HAL Request %s:\n", templateNames[i-1]);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800787 if (templateRequest == nullptr) {
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800788 lines.append(" Not supported\n");
789 write(fd, lines.string(), lines.size());
790 } else {
791 write(fd, lines.string(), lines.size());
792 dump_indented_camera_metadata(templateRequest,
793 fd, /*verbosity*/2, /*indentation*/8);
794 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800795 free_camera_metadata(templateRequest);
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800796 }
797 }
798
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700799 mTagMonitor.dumpMonitoredMetadata(fd);
800
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800801 if (mInterface->valid()) {
Eino-Ville Talvalad00111e2017-01-31 11:59:12 -0800802 lines = String8(" HAL device dump:\n");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800803 write(fd, lines.string(), lines.size());
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800804 mInterface->dump(fd);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800805 }
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800806
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700807 if (gotLock) mLock.unlock();
808 if (gotInterfaceLock) mInterfaceLock.unlock();
809
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800810 return OK;
811}
812
Shuzhen Wang2e7f58f2018-07-11 14:00:29 -0700813const CameraMetadata& Camera3Device::info(const String8& physicalId) const {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800814 ALOGVV("%s: E", __FUNCTION__);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800815 if (CC_UNLIKELY(mStatus == STATUS_UNINITIALIZED ||
816 mStatus == STATUS_ERROR)) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -0700817 ALOGW("%s: Access to static info %s!", __FUNCTION__,
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800818 mStatus == STATUS_ERROR ?
819 "when in error state" : "before init");
820 }
Shuzhen Wang2e7f58f2018-07-11 14:00:29 -0700821 if (physicalId.isEmpty()) {
822 return mDeviceInfo;
823 } else {
824 std::string id(physicalId.c_str());
825 if (mPhysicalDeviceInfoMap.find(id) != mPhysicalDeviceInfoMap.end()) {
826 return mPhysicalDeviceInfoMap.at(id);
827 } else {
828 ALOGE("%s: Invalid physical camera id %s", __FUNCTION__, physicalId.c_str());
829 return mDeviceInfo;
830 }
831 }
832}
833
834const CameraMetadata& Camera3Device::info() const {
835 String8 emptyId;
836 return info(emptyId);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800837}
838
Jianing Wei90e59c92014-03-12 18:29:36 -0700839status_t Camera3Device::checkStatusOkToCaptureLocked() {
840 switch (mStatus) {
841 case STATUS_ERROR:
842 CLOGE("Device has encountered a serious error");
843 return INVALID_OPERATION;
844 case STATUS_UNINITIALIZED:
845 CLOGE("Device not initialized");
846 return INVALID_OPERATION;
847 case STATUS_UNCONFIGURED:
848 case STATUS_CONFIGURED:
849 case STATUS_ACTIVE:
850 // OK
851 break;
852 default:
853 SET_ERR_L("Unexpected status: %d", mStatus);
854 return INVALID_OPERATION;
855 }
856 return OK;
857}
858
859status_t Camera3Device::convertMetadataListToRequestListLocked(
Emilian Peevaebbe412018-01-15 13:53:24 +0000860 const List<const PhysicalCameraSettingsList> &metadataList,
Shuzhen Wang0129d522016-10-30 22:43:41 -0700861 const std::list<const SurfaceMap> &surfaceMaps,
862 bool repeating,
Shuzhen Wang9d066012016-09-30 11:30:20 -0700863 RequestList *requestList) {
Jianing Wei90e59c92014-03-12 18:29:36 -0700864 if (requestList == NULL) {
865 CLOGE("requestList cannot be NULL.");
866 return BAD_VALUE;
867 }
868
Jianing Weicb0652e2014-03-12 18:29:36 -0700869 int32_t burstId = 0;
Emilian Peevaebbe412018-01-15 13:53:24 +0000870 List<const PhysicalCameraSettingsList>::const_iterator metadataIt = metadataList.begin();
Shuzhen Wang0129d522016-10-30 22:43:41 -0700871 std::list<const SurfaceMap>::const_iterator surfaceMapIt = surfaceMaps.begin();
872 for (; metadataIt != metadataList.end() && surfaceMapIt != surfaceMaps.end();
873 ++metadataIt, ++surfaceMapIt) {
874 sp<CaptureRequest> newRequest = setUpRequestLocked(*metadataIt, *surfaceMapIt);
Jianing Wei90e59c92014-03-12 18:29:36 -0700875 if (newRequest == 0) {
876 CLOGE("Can't create capture request");
877 return BAD_VALUE;
878 }
Jianing Weicb0652e2014-03-12 18:29:36 -0700879
Shuzhen Wang9d066012016-09-30 11:30:20 -0700880 newRequest->mRepeating = repeating;
881
Jianing Weicb0652e2014-03-12 18:29:36 -0700882 // Setup burst Id and request Id
883 newRequest->mResultExtras.burstId = burstId++;
Emilian Peevaebbe412018-01-15 13:53:24 +0000884 if (metadataIt->begin()->metadata.exists(ANDROID_REQUEST_ID)) {
885 if (metadataIt->begin()->metadata.find(ANDROID_REQUEST_ID).count == 0) {
Jianing Weicb0652e2014-03-12 18:29:36 -0700886 CLOGE("RequestID entry exists; but must not be empty in metadata");
887 return BAD_VALUE;
888 }
Emilian Peevaebbe412018-01-15 13:53:24 +0000889 newRequest->mResultExtras.requestId = metadataIt->begin()->metadata.find(
890 ANDROID_REQUEST_ID).data.i32[0];
Jianing Weicb0652e2014-03-12 18:29:36 -0700891 } else {
892 CLOGE("RequestID does not exist in metadata");
893 return BAD_VALUE;
894 }
895
Jianing Wei90e59c92014-03-12 18:29:36 -0700896 requestList->push_back(newRequest);
Jianing Wei2d6bb3f2014-04-11 10:00:31 -0700897
898 ALOGV("%s: requestId = %" PRId32, __FUNCTION__, newRequest->mResultExtras.requestId);
Jianing Wei90e59c92014-03-12 18:29:36 -0700899 }
Shuzhen Wang0129d522016-10-30 22:43:41 -0700900 if (metadataIt != metadataList.end() || surfaceMapIt != surfaceMaps.end()) {
901 ALOGE("%s: metadataList and surfaceMaps are not the same size!", __FUNCTION__);
902 return BAD_VALUE;
903 }
Chien-Yu Chen85a64552015-08-28 15:46:12 -0700904
905 // Setup batch size if this is a high speed video recording request.
906 if (mIsConstrainedHighSpeedConfiguration && requestList->size() > 0) {
907 auto firstRequest = requestList->begin();
908 for (auto& outputStream : (*firstRequest)->mOutputStreams) {
909 if (outputStream->isVideoStream()) {
910 (*firstRequest)->mBatchSize = requestList->size();
911 break;
912 }
913 }
914 }
915
Jianing Wei90e59c92014-03-12 18:29:36 -0700916 return OK;
917}
918
Yin-Chia Yeh7e5a2042019-02-06 16:01:06 -0800919status_t Camera3Device::capture(CameraMetadata &request, int64_t* lastFrameNumber) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800920 ATRACE_CALL();
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800921
Emilian Peevaebbe412018-01-15 13:53:24 +0000922 List<const PhysicalCameraSettingsList> requestsList;
Shuzhen Wang0129d522016-10-30 22:43:41 -0700923 std::list<const SurfaceMap> surfaceMaps;
Emilian Peevaebbe412018-01-15 13:53:24 +0000924 convertToRequestList(requestsList, surfaceMaps, request);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700925
Yin-Chia Yeh7e5a2042019-02-06 16:01:06 -0800926 return captureList(requestsList, surfaceMaps, lastFrameNumber);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700927}
928
Emilian Peevaebbe412018-01-15 13:53:24 +0000929void Camera3Device::convertToRequestList(List<const PhysicalCameraSettingsList>& requestsList,
Shuzhen Wang0129d522016-10-30 22:43:41 -0700930 std::list<const SurfaceMap>& surfaceMaps,
931 const CameraMetadata& request) {
Emilian Peevaebbe412018-01-15 13:53:24 +0000932 PhysicalCameraSettingsList requestList;
933 requestList.push_back({std::string(getId().string()), request});
934 requestsList.push_back(requestList);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700935
936 SurfaceMap surfaceMap;
937 camera_metadata_ro_entry streams = request.find(ANDROID_REQUEST_OUTPUT_STREAMS);
938 // With no surface list passed in, stream and surface will have 1-to-1
939 // mapping. So the surface index is 0 for each stream in the surfaceMap.
940 for (size_t i = 0; i < streams.count; i++) {
941 surfaceMap[streams.data.i32[i]].push_back(0);
942 }
943 surfaceMaps.push_back(surfaceMap);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800944}
945
Jianing Wei90e59c92014-03-12 18:29:36 -0700946status_t Camera3Device::submitRequestsHelper(
Emilian Peevaebbe412018-01-15 13:53:24 +0000947 const List<const PhysicalCameraSettingsList> &requests,
Shuzhen Wang0129d522016-10-30 22:43:41 -0700948 const std::list<const SurfaceMap> &surfaceMaps,
949 bool repeating,
Jianing Wei2d6bb3f2014-04-11 10:00:31 -0700950 /*out*/
951 int64_t *lastFrameNumber) {
Jianing Wei90e59c92014-03-12 18:29:36 -0700952 ATRACE_CALL();
953 Mutex::Autolock il(mInterfaceLock);
954 Mutex::Autolock l(mLock);
955
956 status_t res = checkStatusOkToCaptureLocked();
957 if (res != OK) {
958 // error logged by previous call
959 return res;
960 }
961
962 RequestList requestList;
963
Shuzhen Wang0129d522016-10-30 22:43:41 -0700964 res = convertMetadataListToRequestListLocked(requests, surfaceMaps,
965 repeating, /*out*/&requestList);
Jianing Wei90e59c92014-03-12 18:29:36 -0700966 if (res != OK) {
967 // error logged by previous call
968 return res;
969 }
970
971 if (repeating) {
Jianing Wei2d6bb3f2014-04-11 10:00:31 -0700972 res = mRequestThread->setRepeatingRequests(requestList, lastFrameNumber);
Jianing Wei90e59c92014-03-12 18:29:36 -0700973 } else {
Jianing Wei2d6bb3f2014-04-11 10:00:31 -0700974 res = mRequestThread->queueRequestList(requestList, lastFrameNumber);
Jianing Wei90e59c92014-03-12 18:29:36 -0700975 }
976
977 if (res == OK) {
978 waitUntilStateThenRelock(/*active*/true, kActiveTimeout);
979 if (res != OK) {
980 SET_ERR_L("Can't transition to active in %f seconds!",
981 kActiveTimeout/1e9);
982 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800983 ALOGV("Camera %s: Capture request %" PRId32 " enqueued", mId.string(),
Jianing Wei2d6bb3f2014-04-11 10:00:31 -0700984 (*(requestList.begin()))->mResultExtras.requestId);
Jianing Wei90e59c92014-03-12 18:29:36 -0700985 } else {
986 CLOGE("Cannot queue request. Impossible.");
987 return BAD_VALUE;
988 }
989
990 return res;
991}
992
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -0700993hardware::Return<void> Camera3Device::requestStreamBuffers(
994 const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& bufReqs,
995 requestStreamBuffers_cb _hidl_cb) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800996 RequestBufferStates states {
997 mId, mRequestBufferInterfaceLock, mUseHalBufManager, mOutputStreams,
998 *this, *mInterface, *this};
999 camera3::requestStreamBuffers(states, bufReqs, _hidl_cb);
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07001000 return hardware::Void();
1001}
1002
1003hardware::Return<void> Camera3Device::returnStreamBuffers(
1004 const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer>& buffers) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001005 ReturnBufferStates states {
1006 mId, mUseHalBufManager, mOutputStreams, *mInterface};
1007 camera3::returnStreamBuffers(states, buffers);
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07001008 return hardware::Void();
1009}
1010
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001011hardware::Return<void> Camera3Device::processCaptureResult_3_4(
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001012 const hardware::hidl_vec<
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001013 hardware::camera::device::V3_4::CaptureResult>& results) {
Yin-Chia Yeh657c1872017-07-18 18:09:57 -07001014 // Ideally we should grab mLock, but that can lead to deadlock, and
1015 // it's not super important to get up to date value of mStatus for this
1016 // warning print, hence skipping the lock here
1017 if (mStatus == STATUS_ERROR) {
1018 // Per API contract, HAL should act as closed after device error
1019 // But mStatus can be set to error by framework as well, so just log
1020 // a warning here.
1021 ALOGW("%s: received capture result in error state.", __FUNCTION__);
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07001022 }
Yifan Honga640c5a2017-04-12 16:30:31 -07001023
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001024 sp<NotificationListener> listener;
1025 {
1026 std::lock_guard<std::mutex> l(mOutputLock);
1027 listener = mListener.promote();
1028 }
1029
Yifan Honga640c5a2017-04-12 16:30:31 -07001030 if (mProcessCaptureResultLock.tryLock() != OK) {
1031 // This should never happen; it indicates a wrong client implementation
1032 // that doesn't follow the contract. But, we can be tolerant here.
1033 ALOGE("%s: callback overlapped! waiting 1s...",
1034 __FUNCTION__);
1035 if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
1036 ALOGE("%s: cannot acquire lock in 1s, dropping results",
1037 __FUNCTION__);
1038 // really don't know what to do, so bail out.
1039 return hardware::Void();
1040 }
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001041 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001042 CaptureOutputStates states {
1043 mId,
1044 mInFlightLock, mInFlightMap,
1045 mOutputLock, mResultQueue, mResultSignal,
1046 mNextShutterFrameNumber,
1047 mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
1048 mNextResultFrameNumber,
1049 mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
1050 mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
1051 mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
1052 mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mTagMonitor,
1053 mInputStream, mOutputStreams, listener, *this, *this, *mInterface
1054 };
1055
Yifan Honga640c5a2017-04-12 16:30:31 -07001056 for (const auto& result : results) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001057 processOneCaptureResultLocked(states, result.v3_2, result.physicalCameraMetadata);
Yifan Honga640c5a2017-04-12 16:30:31 -07001058 }
1059 mProcessCaptureResultLock.unlock();
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001060 return hardware::Void();
1061}
1062
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001063// Only one processCaptureResult should be called at a time, so
1064// the locks won't block. The locks are present here simply to enforce this.
1065hardware::Return<void> Camera3Device::processCaptureResult(
1066 const hardware::hidl_vec<
1067 hardware::camera::device::V3_2::CaptureResult>& results) {
1068 hardware::hidl_vec<hardware::camera::device::V3_4::PhysicalCameraMetadata> noPhysMetadata;
1069
1070 // Ideally we should grab mLock, but that can lead to deadlock, and
1071 // it's not super important to get up to date value of mStatus for this
1072 // warning print, hence skipping the lock here
1073 if (mStatus == STATUS_ERROR) {
1074 // Per API contract, HAL should act as closed after device error
1075 // But mStatus can be set to error by framework as well, so just log
1076 // a warning here.
1077 ALOGW("%s: received capture result in error state.", __FUNCTION__);
1078 }
1079
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001080 sp<NotificationListener> listener;
1081 {
1082 std::lock_guard<std::mutex> l(mOutputLock);
1083 listener = mListener.promote();
1084 }
1085
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001086 if (mProcessCaptureResultLock.tryLock() != OK) {
1087 // This should never happen; it indicates a wrong client implementation
1088 // that doesn't follow the contract. But, we can be tolerant here.
1089 ALOGE("%s: callback overlapped! waiting 1s...",
1090 __FUNCTION__);
1091 if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
1092 ALOGE("%s: cannot acquire lock in 1s, dropping results",
1093 __FUNCTION__);
1094 // really don't know what to do, so bail out.
1095 return hardware::Void();
1096 }
1097 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001098
1099 CaptureOutputStates states {
1100 mId,
1101 mInFlightLock, mInFlightMap,
1102 mOutputLock, mResultQueue, mResultSignal,
1103 mNextShutterFrameNumber,
1104 mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
1105 mNextResultFrameNumber,
1106 mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
1107 mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
1108 mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
1109 mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mTagMonitor,
1110 mInputStream, mOutputStreams, listener, *this, *this, *mInterface
1111 };
1112
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001113 for (const auto& result : results) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001114 processOneCaptureResultLocked(states, result, noPhysMetadata);
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001115 }
1116 mProcessCaptureResultLock.unlock();
1117 return hardware::Void();
1118}
1119
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001120hardware::Return<void> Camera3Device::notify(
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001121 const hardware::hidl_vec<hardware::camera::device::V3_2::NotifyMsg>& msgs) {
Yin-Chia Yeh657c1872017-07-18 18:09:57 -07001122 // Ideally we should grab mLock, but that can lead to deadlock, and
1123 // it's not super important to get up to date value of mStatus for this
1124 // warning print, hence skipping the lock here
1125 if (mStatus == STATUS_ERROR) {
1126 // Per API contract, HAL should act as closed after device error
1127 // But mStatus can be set to error by framework as well, so just log
1128 // a warning here.
1129 ALOGW("%s: received notify message in error state.", __FUNCTION__);
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07001130 }
Yin-Chia Yeh657c1872017-07-18 18:09:57 -07001131
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001132 sp<NotificationListener> listener;
1133 {
1134 std::lock_guard<std::mutex> l(mOutputLock);
1135 listener = mListener.promote();
1136 }
1137
1138 CaptureOutputStates states {
1139 mId,
1140 mInFlightLock, mInFlightMap,
1141 mOutputLock, mResultQueue, mResultSignal,
1142 mNextShutterFrameNumber,
1143 mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
1144 mNextResultFrameNumber,
1145 mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
1146 mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
1147 mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
1148 mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mTagMonitor,
1149 mInputStream, mOutputStreams, listener, *this, *this, *mInterface
1150 };
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001151 for (const auto& msg : msgs) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001152 camera3::notify(states, msg);
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001153 }
1154 return hardware::Void();
1155}
1156
Emilian Peevaebbe412018-01-15 13:53:24 +00001157status_t Camera3Device::captureList(const List<const PhysicalCameraSettingsList> &requestsList,
Shuzhen Wang0129d522016-10-30 22:43:41 -07001158 const std::list<const SurfaceMap> &surfaceMaps,
Jianing Weicb0652e2014-03-12 18:29:36 -07001159 int64_t *lastFrameNumber) {
Jianing Wei90e59c92014-03-12 18:29:36 -07001160 ATRACE_CALL();
1161
Emilian Peevaebbe412018-01-15 13:53:24 +00001162 return submitRequestsHelper(requestsList, surfaceMaps, /*repeating*/false, lastFrameNumber);
Jianing Wei90e59c92014-03-12 18:29:36 -07001163}
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001164
Jianing Weicb0652e2014-03-12 18:29:36 -07001165status_t Camera3Device::setStreamingRequest(const CameraMetadata &request,
1166 int64_t* /*lastFrameNumber*/) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001167 ATRACE_CALL();
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001168
Emilian Peevaebbe412018-01-15 13:53:24 +00001169 List<const PhysicalCameraSettingsList> requestsList;
Shuzhen Wang0129d522016-10-30 22:43:41 -07001170 std::list<const SurfaceMap> surfaceMaps;
Emilian Peevaebbe412018-01-15 13:53:24 +00001171 convertToRequestList(requestsList, surfaceMaps, request);
Shuzhen Wang0129d522016-10-30 22:43:41 -07001172
Emilian Peevaebbe412018-01-15 13:53:24 +00001173 return setStreamingRequestList(requestsList, /*surfaceMap*/surfaceMaps,
Shuzhen Wang0129d522016-10-30 22:43:41 -07001174 /*lastFrameNumber*/NULL);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001175}
1176
Emilian Peevaebbe412018-01-15 13:53:24 +00001177status_t Camera3Device::setStreamingRequestList(
1178 const List<const PhysicalCameraSettingsList> &requestsList,
1179 const std::list<const SurfaceMap> &surfaceMaps, int64_t *lastFrameNumber) {
Jianing Wei90e59c92014-03-12 18:29:36 -07001180 ATRACE_CALL();
1181
Emilian Peevaebbe412018-01-15 13:53:24 +00001182 return submitRequestsHelper(requestsList, surfaceMaps, /*repeating*/true, lastFrameNumber);
Jianing Wei90e59c92014-03-12 18:29:36 -07001183}
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001184
1185sp<Camera3Device::CaptureRequest> Camera3Device::setUpRequestLocked(
Emilian Peevaebbe412018-01-15 13:53:24 +00001186 const PhysicalCameraSettingsList &request, const SurfaceMap &surfaceMap) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001187 status_t res;
1188
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001189 if (mStatus == STATUS_UNCONFIGURED || mNeedConfig) {
Eino-Ville Talvalae7091aa2017-03-07 15:23:06 -08001190 // This point should only be reached via API1 (API2 must explicitly call configureStreams)
1191 // so unilaterally select normal operating mode.
Emilian Peevaebbe412018-01-15 13:53:24 +00001192 res = filterParamsAndConfigureLocked(request.begin()->metadata,
1193 CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE);
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07001194 // Stream configuration failed. Client might try other configuraitons.
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001195 if (res != OK) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07001196 CLOGE("Can't set up streams: %s (%d)", strerror(-res), res);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001197 return NULL;
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07001198 } else if (mStatus == STATUS_UNCONFIGURED) {
1199 // Stream configuration successfully configure to empty stream configuration.
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001200 CLOGE("No streams configured");
1201 return NULL;
1202 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001203 }
1204
Shuzhen Wang0129d522016-10-30 22:43:41 -07001205 sp<CaptureRequest> newRequest = createCaptureRequest(request, surfaceMap);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001206 return newRequest;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001207}
1208
Jianing Weicb0652e2014-03-12 18:29:36 -07001209status_t Camera3Device::clearStreamingRequest(int64_t *lastFrameNumber) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001210 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001211 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001212 Mutex::Autolock l(mLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001213
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001214 switch (mStatus) {
1215 case STATUS_ERROR:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001216 CLOGE("Device has encountered a serious error");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001217 return INVALID_OPERATION;
1218 case STATUS_UNINITIALIZED:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001219 CLOGE("Device not initialized");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001220 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001221 case STATUS_UNCONFIGURED:
1222 case STATUS_CONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001223 case STATUS_ACTIVE:
1224 // OK
1225 break;
1226 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001227 SET_ERR_L("Unexpected status: %d", mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001228 return INVALID_OPERATION;
1229 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001230 ALOGV("Camera %s: Clearing repeating request", mId.string());
Jianing Weicb0652e2014-03-12 18:29:36 -07001231
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07001232 return mRequestThread->clearRepeatingRequests(lastFrameNumber);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001233}
1234
1235status_t Camera3Device::waitUntilRequestReceived(int32_t requestId, nsecs_t timeout) {
1236 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001237 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001238
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001239 return mRequestThread->waitUntilRequestProcessed(requestId, timeout);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001240}
1241
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001242status_t Camera3Device::createInputStream(
1243 uint32_t width, uint32_t height, int format, int *id) {
1244 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001245 Mutex::Autolock il(mInterfaceLock);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001246 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001247 Mutex::Autolock l(mLock);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001248 ALOGV("Camera %s: Creating new input stream %d: %d x %d, format %d",
1249 mId.string(), mNextStreamId, width, height, format);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001250
1251 status_t res;
1252 bool wasActive = false;
1253
1254 switch (mStatus) {
1255 case STATUS_ERROR:
1256 ALOGE("%s: Device has encountered a serious error", __FUNCTION__);
1257 return INVALID_OPERATION;
1258 case STATUS_UNINITIALIZED:
1259 ALOGE("%s: Device not initialized", __FUNCTION__);
1260 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001261 case STATUS_UNCONFIGURED:
1262 case STATUS_CONFIGURED:
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001263 // OK
1264 break;
1265 case STATUS_ACTIVE:
1266 ALOGV("%s: Stopping activity to reconfigure streams", __FUNCTION__);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001267 res = internalPauseAndWaitLocked(maxExpectedDuration);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001268 if (res != OK) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001269 SET_ERR_L("Can't pause captures to reconfigure streams!");
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001270 return res;
1271 }
1272 wasActive = true;
1273 break;
1274 default:
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001275 SET_ERR_L("%s: Unexpected status: %d", mStatus);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001276 return INVALID_OPERATION;
1277 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001278 assert(mStatus != STATUS_ACTIVE);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001279
1280 if (mInputStream != 0) {
1281 ALOGE("%s: Cannot create more than 1 input stream", __FUNCTION__);
1282 return INVALID_OPERATION;
1283 }
1284
1285 sp<Camera3InputStream> newStream = new Camera3InputStream(mNextStreamId,
1286 width, height, format);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001287 newStream->setStatusTracker(mStatusTracker);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001288
1289 mInputStream = newStream;
1290
1291 *id = mNextStreamId++;
1292
1293 // Continue captures if active at start
1294 if (wasActive) {
1295 ALOGV("%s: Restarting activity to reconfigure streams", __FUNCTION__);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001296 // Reuse current operating mode and session parameters for new stream config
1297 res = configureStreamsLocked(mOperatingMode, mSessionParams);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001298 if (res != OK) {
1299 ALOGE("%s: Can't reconfigure device for new stream %d: %s (%d)",
1300 __FUNCTION__, mNextStreamId, strerror(-res), res);
1301 return res;
1302 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001303 internalResumeLocked();
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001304 }
1305
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001306 ALOGV("Camera %s: Created input stream", mId.string());
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001307 return OK;
1308}
1309
Eino-Ville Talvala727d1722015-06-09 13:44:19 -07001310status_t Camera3Device::createStream(sp<Surface> consumer,
Shuzhen Wang0129d522016-10-30 22:43:41 -07001311 uint32_t width, uint32_t height, int format,
1312 android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001313 const String8& physicalCameraId,
Emilian Peev40ead602017-09-26 15:46:36 +01001314 std::vector<int> *surfaceIds, int streamSetId, bool isShared, uint64_t consumerUsage) {
Shuzhen Wang0129d522016-10-30 22:43:41 -07001315 ATRACE_CALL();
1316
1317 if (consumer == nullptr) {
1318 ALOGE("%s: consumer must not be null", __FUNCTION__);
1319 return BAD_VALUE;
1320 }
1321
1322 std::vector<sp<Surface>> consumers;
1323 consumers.push_back(consumer);
1324
1325 return createStream(consumers, /*hasDeferredConsumer*/ false, width, height,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001326 format, dataSpace, rotation, id, physicalCameraId, surfaceIds, streamSetId,
1327 isShared, consumerUsage);
Shuzhen Wang0129d522016-10-30 22:43:41 -07001328}
1329
1330status_t Camera3Device::createStream(const std::vector<sp<Surface>>& consumers,
1331 bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
1332 android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001333 const String8& physicalCameraId,
Emilian Peev40ead602017-09-26 15:46:36 +01001334 std::vector<int> *surfaceIds, int streamSetId, bool isShared, uint64_t consumerUsage) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001335 ATRACE_CALL();
Emilian Peev40ead602017-09-26 15:46:36 +01001336
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001337 Mutex::Autolock il(mInterfaceLock);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001338 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001339 Mutex::Autolock l(mLock);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001340 ALOGV("Camera %s: Creating new stream %d: %d x %d, format %d, dataspace %d rotation %d"
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001341 " consumer usage %" PRIu64 ", isShared %d, physicalCameraId %s", mId.string(),
1342 mNextStreamId, width, height, format, dataSpace, rotation, consumerUsage, isShared,
1343 physicalCameraId.string());
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001344
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001345 status_t res;
1346 bool wasActive = false;
1347
1348 switch (mStatus) {
1349 case STATUS_ERROR:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001350 CLOGE("Device has encountered a serious error");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001351 return INVALID_OPERATION;
1352 case STATUS_UNINITIALIZED:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001353 CLOGE("Device not initialized");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001354 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001355 case STATUS_UNCONFIGURED:
1356 case STATUS_CONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001357 // OK
1358 break;
1359 case STATUS_ACTIVE:
1360 ALOGV("%s: Stopping activity to reconfigure streams", __FUNCTION__);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001361 res = internalPauseAndWaitLocked(maxExpectedDuration);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001362 if (res != OK) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001363 SET_ERR_L("Can't pause captures to reconfigure streams!");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001364 return res;
1365 }
1366 wasActive = true;
1367 break;
1368 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001369 SET_ERR_L("Unexpected status: %d", mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001370 return INVALID_OPERATION;
1371 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001372 assert(mStatus != STATUS_ACTIVE);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001373
1374 sp<Camera3OutputStream> newStream;
Zhijun He5d677d12016-05-29 16:52:39 -07001375
Shuzhen Wang0129d522016-10-30 22:43:41 -07001376 if (consumers.size() == 0 && !hasDeferredConsumer) {
1377 ALOGE("%s: Number of consumers cannot be smaller than 1", __FUNCTION__);
1378 return BAD_VALUE;
1379 }
Zhijun He5d677d12016-05-29 16:52:39 -07001380
Shuzhen Wang0129d522016-10-30 22:43:41 -07001381 if (hasDeferredConsumer && format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
Zhijun He5d677d12016-05-29 16:52:39 -07001382 ALOGE("Deferred consumer stream creation only support IMPLEMENTATION_DEFINED format");
1383 return BAD_VALUE;
1384 }
1385
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001386 if (format == HAL_PIXEL_FORMAT_BLOB) {
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -07001387 ssize_t blobBufferSize;
Shuzhen Wang68ac7ad2019-01-30 14:03:28 -08001388 if (dataSpace == HAL_DATASPACE_DEPTH) {
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -07001389 blobBufferSize = getPointCloudBufferSize();
1390 if (blobBufferSize <= 0) {
1391 SET_ERR_L("Invalid point cloud buffer size %zd", blobBufferSize);
1392 return BAD_VALUE;
1393 }
Shuzhen Wang68ac7ad2019-01-30 14:03:28 -08001394 } else if (dataSpace == static_cast<android_dataspace>(HAL_DATASPACE_JPEG_APP_SEGMENTS)) {
1395 blobBufferSize = width * height;
1396 } else {
1397 blobBufferSize = getJpegBufferSize(width, height);
1398 if (blobBufferSize <= 0) {
1399 SET_ERR_L("Invalid jpeg buffer size %zd", blobBufferSize);
1400 return BAD_VALUE;
1401 }
Zhijun Hef7da0962014-04-24 13:27:56 -07001402 }
Shuzhen Wang0129d522016-10-30 22:43:41 -07001403 newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
Shuzhen Wangc28dccc2016-02-11 23:48:46 -08001404 width, height, blobBufferSize, format, dataSpace, rotation,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001405 mTimestampOffset, physicalCameraId, streamSetId);
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -08001406 } else if (format == HAL_PIXEL_FORMAT_RAW_OPAQUE) {
1407 ssize_t rawOpaqueBufferSize = getRawOpaqueBufferSize(width, height);
1408 if (rawOpaqueBufferSize <= 0) {
1409 SET_ERR_L("Invalid RAW opaque buffer size %zd", rawOpaqueBufferSize);
1410 return BAD_VALUE;
1411 }
Shuzhen Wang0129d522016-10-30 22:43:41 -07001412 newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
Shuzhen Wangc28dccc2016-02-11 23:48:46 -08001413 width, height, rawOpaqueBufferSize, format, dataSpace, rotation,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001414 mTimestampOffset, physicalCameraId, streamSetId);
Shuzhen Wang758c2152017-01-10 18:26:18 -08001415 } else if (isShared) {
1416 newStream = new Camera3SharedOutputStream(mNextStreamId, consumers,
1417 width, height, format, consumerUsage, dataSpace, rotation,
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07001418 mTimestampOffset, physicalCameraId, streamSetId,
1419 mUseHalBufManager);
Shuzhen Wang0129d522016-10-30 22:43:41 -07001420 } else if (consumers.size() == 0 && hasDeferredConsumer) {
Zhijun He5d677d12016-05-29 16:52:39 -07001421 newStream = new Camera3OutputStream(mNextStreamId,
1422 width, height, format, consumerUsage, dataSpace, rotation,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001423 mTimestampOffset, physicalCameraId, streamSetId);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001424 } else {
Shuzhen Wang0129d522016-10-30 22:43:41 -07001425 newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
Shuzhen Wangc28dccc2016-02-11 23:48:46 -08001426 width, height, format, dataSpace, rotation,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001427 mTimestampOffset, physicalCameraId, streamSetId);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001428 }
Emilian Peev40ead602017-09-26 15:46:36 +01001429
1430 size_t consumerCount = consumers.size();
1431 for (size_t i = 0; i < consumerCount; i++) {
1432 int id = newStream->getSurfaceId(consumers[i]);
1433 if (id < 0) {
1434 SET_ERR_L("Invalid surface id");
1435 return BAD_VALUE;
1436 }
1437 if (surfaceIds != nullptr) {
1438 surfaceIds->push_back(id);
1439 }
1440 }
1441
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001442 newStream->setStatusTracker(mStatusTracker);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001443
Emilian Peev08dd2452017-04-06 16:55:14 +01001444 newStream->setBufferManager(mBufferManager);
Zhijun He125684a2015-12-26 15:07:30 -08001445
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001446 res = mOutputStreams.add(mNextStreamId, newStream);
1447 if (res < 0) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001448 SET_ERR_L("Can't add new stream to set: %s (%d)", strerror(-res), res);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001449 return res;
1450 }
1451
1452 *id = mNextStreamId++;
Eino-Ville Talvalaea26c772013-06-11 16:04:06 -07001453 mNeedConfig = true;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001454
1455 // Continue captures if active at start
1456 if (wasActive) {
1457 ALOGV("%s: Restarting activity to reconfigure streams", __FUNCTION__);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001458 // Reuse current operating mode and session parameters for new stream config
1459 res = configureStreamsLocked(mOperatingMode, mSessionParams);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001460 if (res != OK) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001461 CLOGE("Can't reconfigure device for new stream %d: %s (%d)",
1462 mNextStreamId, strerror(-res), res);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001463 return res;
1464 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001465 internalResumeLocked();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001466 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001467 ALOGV("Camera %s: Created new stream", mId.string());
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001468 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001469}
1470
Emilian Peev710c1422017-08-30 11:19:38 +01001471status_t Camera3Device::getStreamInfo(int id, StreamInfo *streamInfo) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001472 ATRACE_CALL();
Emilian Peev710c1422017-08-30 11:19:38 +01001473 if (nullptr == streamInfo) {
1474 return BAD_VALUE;
1475 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001476 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001477 Mutex::Autolock l(mLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001478
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001479 switch (mStatus) {
1480 case STATUS_ERROR:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001481 CLOGE("Device has encountered a serious error");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001482 return INVALID_OPERATION;
1483 case STATUS_UNINITIALIZED:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001484 CLOGE("Device not initialized!");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001485 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001486 case STATUS_UNCONFIGURED:
1487 case STATUS_CONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001488 case STATUS_ACTIVE:
1489 // OK
1490 break;
1491 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001492 SET_ERR_L("Unexpected status: %d", mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001493 return INVALID_OPERATION;
1494 }
1495
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001496 sp<Camera3StreamInterface> stream = mOutputStreams.get(id);
1497 if (stream == nullptr) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001498 CLOGE("Stream %d is unknown", id);
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001499 return BAD_VALUE;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001500 }
1501
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001502 streamInfo->width = stream->getWidth();
1503 streamInfo->height = stream->getHeight();
1504 streamInfo->format = stream->getFormat();
1505 streamInfo->dataSpace = stream->getDataSpace();
1506 streamInfo->formatOverridden = stream->isFormatOverridden();
1507 streamInfo->originalFormat = stream->getOriginalFormat();
1508 streamInfo->dataSpaceOverridden = stream->isDataSpaceOverridden();
1509 streamInfo->originalDataSpace = stream->getOriginalDataSpace();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001510 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001511}
1512
1513status_t Camera3Device::setStreamTransform(int id,
1514 int transform) {
1515 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001516 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001517 Mutex::Autolock l(mLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001518
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001519 switch (mStatus) {
1520 case STATUS_ERROR:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001521 CLOGE("Device has encountered a serious error");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001522 return INVALID_OPERATION;
1523 case STATUS_UNINITIALIZED:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001524 CLOGE("Device not initialized");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001525 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001526 case STATUS_UNCONFIGURED:
1527 case STATUS_CONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001528 case STATUS_ACTIVE:
1529 // OK
1530 break;
1531 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001532 SET_ERR_L("Unexpected status: %d", mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001533 return INVALID_OPERATION;
1534 }
1535
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001536 sp<Camera3OutputStreamInterface> stream = mOutputStreams.get(id);
1537 if (stream == nullptr) {
1538 CLOGE("Stream %d does not exist", id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001539 return BAD_VALUE;
1540 }
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001541 return stream->setTransform(transform);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001542}
1543
1544status_t Camera3Device::deleteStream(int id) {
1545 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001546 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001547 Mutex::Autolock l(mLock);
1548 status_t res;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001549
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001550 ALOGV("%s: Camera %s: Deleting stream %d", __FUNCTION__, mId.string(), id);
Igor Murashkine2172be2013-05-28 15:31:39 -07001551
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001552 // CameraDevice semantics require device to already be idle before
1553 // deleteStream is called, unlike for createStream.
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001554 if (mStatus == STATUS_ACTIVE) {
Yin-Chia Yeh693047d2018-03-08 12:14:19 -08001555 ALOGW("%s: Camera %s: Device not idle", __FUNCTION__, mId.string());
Igor Murashkin52827132013-05-13 14:53:44 -07001556 return -EBUSY;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001557 }
1558
Yin-Chia Yeh5090c732017-07-20 16:05:29 -07001559 if (mStatus == STATUS_ERROR) {
1560 ALOGW("%s: Camera %s: deleteStream not allowed in ERROR state",
1561 __FUNCTION__, mId.string());
1562 return -EBUSY;
1563 }
1564
Igor Murashkin2fba5842013-04-22 14:03:54 -07001565 sp<Camera3StreamInterface> deletedStream;
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001566 sp<Camera3StreamInterface> stream = mOutputStreams.get(id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001567 if (mInputStream != NULL && id == mInputStream->getId()) {
1568 deletedStream = mInputStream;
1569 mInputStream.clear();
1570 } else {
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001571 if (stream == nullptr) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001572 CLOGE("Stream %d does not exist", id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001573 return BAD_VALUE;
1574 }
Zhijun He5f446352014-01-22 09:49:33 -08001575 }
1576
1577 // Delete output stream or the output part of a bi-directional stream.
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001578 if (stream != nullptr) {
1579 deletedStream = stream;
1580 mOutputStreams.remove(id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001581 }
1582
1583 // Free up the stream endpoint so that it can be used by some other stream
1584 res = deletedStream->disconnect();
1585 if (res != OK) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001586 SET_ERR_L("Can't disconnect deleted stream %d", id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001587 // fall through since we want to still list the stream as deleted.
1588 }
1589 mDeletedStreams.add(deletedStream);
Eino-Ville Talvalaea26c772013-06-11 16:04:06 -07001590 mNeedConfig = true;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001591
1592 return res;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001593}
1594
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001595status_t Camera3Device::configureStreams(const CameraMetadata& sessionParams, int operatingMode) {
Igor Murashkine2d167e2014-08-19 16:19:59 -07001596 ATRACE_CALL();
1597 ALOGV("%s: E", __FUNCTION__);
1598
1599 Mutex::Autolock il(mInterfaceLock);
1600 Mutex::Autolock l(mLock);
Chien-Yu Chen17338fc2015-06-18 16:30:12 -07001601
Emilian Peev811d2952018-05-25 11:08:40 +01001602 // In case the client doesn't include any session parameter, try a
1603 // speculative configuration using the values from the last cached
1604 // default request.
1605 if (sessionParams.isEmpty() &&
1606 ((mLastTemplateId > 0) && (mLastTemplateId < CAMERA3_TEMPLATE_COUNT)) &&
1607 (!mRequestTemplateCache[mLastTemplateId].isEmpty())) {
1608 ALOGV("%s: Speculative session param configuration with template id: %d", __func__,
1609 mLastTemplateId);
1610 return filterParamsAndConfigureLocked(mRequestTemplateCache[mLastTemplateId],
1611 operatingMode);
1612 }
1613
Emilian Peevac3ce6c2017-12-12 15:27:02 +00001614 return filterParamsAndConfigureLocked(sessionParams, operatingMode);
1615}
1616
1617status_t Camera3Device::filterParamsAndConfigureLocked(const CameraMetadata& sessionParams,
1618 int operatingMode) {
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001619 //Filter out any incoming session parameters
1620 const CameraMetadata params(sessionParams);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001621 camera_metadata_entry_t availableSessionKeys = mDeviceInfo.find(
1622 ANDROID_REQUEST_AVAILABLE_SESSION_KEYS);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00001623 CameraMetadata filteredParams(availableSessionKeys.count);
1624 camera_metadata_t *meta = const_cast<camera_metadata_t *>(
1625 filteredParams.getAndLock());
1626 set_camera_metadata_vendor_id(meta, mVendorTagId);
1627 filteredParams.unlock(meta);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001628 if (availableSessionKeys.count > 0) {
1629 for (size_t i = 0; i < availableSessionKeys.count; i++) {
1630 camera_metadata_ro_entry entry = params.find(
1631 availableSessionKeys.data.i32[i]);
1632 if (entry.count > 0) {
1633 filteredParams.update(entry);
1634 }
1635 }
1636 }
1637
1638 return configureStreamsLocked(operatingMode, filteredParams);
Igor Murashkine2d167e2014-08-19 16:19:59 -07001639}
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001640
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -07001641status_t Camera3Device::getInputBufferProducer(
1642 sp<IGraphicBufferProducer> *producer) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07001643 ATRACE_CALL();
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -07001644 Mutex::Autolock il(mInterfaceLock);
1645 Mutex::Autolock l(mLock);
1646
1647 if (producer == NULL) {
1648 return BAD_VALUE;
1649 } else if (mInputStream == NULL) {
1650 return INVALID_OPERATION;
1651 }
1652
1653 return mInputStream->getInputBufferProducer(producer);
1654}
1655
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001656status_t Camera3Device::createDefaultRequest(int templateId,
1657 CameraMetadata *request) {
1658 ATRACE_CALL();
Alex Rayfe7e0c62013-05-30 00:12:13 -07001659 ALOGV("%s: for template %d", __FUNCTION__, templateId);
Chien-Yu Chen9cd14022016-03-09 12:21:01 -08001660
1661 if (templateId <= 0 || templateId >= CAMERA3_TEMPLATE_COUNT) {
1662 android_errorWriteWithInfoLog(CameraService::SN_EVENT_LOG_ID, "26866110",
Jayant Chowdhary12361932018-08-27 14:46:13 -07001663 CameraThreadState::getCallingUid(), nullptr, 0);
Chien-Yu Chen9cd14022016-03-09 12:21:01 -08001664 return BAD_VALUE;
1665 }
1666
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001667 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001668
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001669 {
1670 Mutex::Autolock l(mLock);
1671 switch (mStatus) {
1672 case STATUS_ERROR:
1673 CLOGE("Device has encountered a serious error");
1674 return INVALID_OPERATION;
1675 case STATUS_UNINITIALIZED:
1676 CLOGE("Device is not initialized!");
1677 return INVALID_OPERATION;
1678 case STATUS_UNCONFIGURED:
1679 case STATUS_CONFIGURED:
1680 case STATUS_ACTIVE:
1681 // OK
1682 break;
1683 default:
1684 SET_ERR_L("Unexpected status: %d", mStatus);
1685 return INVALID_OPERATION;
1686 }
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001687
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001688 if (!mRequestTemplateCache[templateId].isEmpty()) {
1689 *request = mRequestTemplateCache[templateId];
Emilian Peev811d2952018-05-25 11:08:40 +01001690 mLastTemplateId = templateId;
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001691 return OK;
1692 }
Zhijun Hea1530f12014-09-14 12:44:20 -07001693 }
1694
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001695 camera_metadata_t *rawRequest;
1696 status_t res = mInterface->constructDefaultRequestSettings(
1697 (camera3_request_template_t) templateId, &rawRequest);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001698
1699 {
1700 Mutex::Autolock l(mLock);
1701 if (res == BAD_VALUE) {
1702 ALOGI("%s: template %d is not supported on this camera device",
1703 __FUNCTION__, templateId);
1704 return res;
1705 } else if (res != OK) {
1706 CLOGE("Unable to construct request template %d: %s (%d)",
1707 templateId, strerror(-res), res);
1708 return res;
1709 }
1710
1711 set_camera_metadata_vendor_id(rawRequest, mVendorTagId);
1712 mRequestTemplateCache[templateId].acquire(rawRequest);
1713
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08001714 // Override the template request with zoomRatioMapper
1715 res = mZoomRatioMappers[mId.c_str()].initZoomRatioInTemplate(
1716 &mRequestTemplateCache[templateId]);
1717 if (res != OK) {
1718 CLOGE("Failed to update zoom ratio for template %d: %s (%d)",
1719 templateId, strerror(-res), res);
1720 return res;
1721 }
1722
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001723 *request = mRequestTemplateCache[templateId];
Emilian Peev811d2952018-05-25 11:08:40 +01001724 mLastTemplateId = templateId;
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001725 }
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001726 return OK;
1727}
1728
1729status_t Camera3Device::waitUntilDrained() {
1730 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001731 Mutex::Autolock il(mInterfaceLock);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001732 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001733 Mutex::Autolock l(mLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001734
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001735 return waitUntilDrainedLocked(maxExpectedDuration);
Zhijun He69a37482014-03-23 18:44:49 -07001736}
1737
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001738status_t Camera3Device::waitUntilDrainedLocked(nsecs_t maxExpectedDuration) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001739 switch (mStatus) {
1740 case STATUS_UNINITIALIZED:
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001741 case STATUS_UNCONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001742 ALOGV("%s: Already idle", __FUNCTION__);
1743 return OK;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001744 case STATUS_CONFIGURED:
1745 // To avoid race conditions, check with tracker to be sure
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001746 case STATUS_ERROR:
1747 case STATUS_ACTIVE:
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001748 // Need to verify shut down
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001749 break;
1750 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001751 SET_ERR_L("Unexpected status: %d",mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001752 return INVALID_OPERATION;
1753 }
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07001754 ALOGV("%s: Camera %s: Waiting until idle (%" PRIi64 "ns)", __FUNCTION__, mId.string(),
1755 maxExpectedDuration);
1756 status_t res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration);
Eino-Ville Talvala9c8a0912014-09-14 14:52:19 -07001757 if (res != OK) {
1758 SET_ERR_L("Error waiting for HAL to drain: %s (%d)", strerror(-res),
1759 res);
1760 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001761 return res;
1762}
1763
Ruben Brunk183f0562015-08-12 12:55:02 -07001764
1765void Camera3Device::internalUpdateStatusLocked(Status status) {
1766 mStatus = status;
1767 mRecentStatusUpdates.add(mStatus);
1768 mStatusChanged.broadcast();
1769}
1770
Eino-Ville Talvala002001b2018-01-23 16:53:50 -08001771void Camera3Device::pauseStateNotify(bool enable) {
Jayant Chowdhary37eca242019-11-18 08:55:56 -08001772 // We must not hold mInterfaceLock here since this function is called from
1773 // RequestThread::threadLoop and holding mInterfaceLock could lead to
1774 // deadlocks (http://b/143513518)
Eino-Ville Talvala002001b2018-01-23 16:53:50 -08001775 Mutex::Autolock l(mLock);
1776
1777 mPauseStateNotify = enable;
1778}
1779
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001780// Pause to reconfigure
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001781status_t Camera3Device::internalPauseAndWaitLocked(nsecs_t maxExpectedDuration) {
Emilian Peeve86358b2019-02-15 13:51:39 -08001782 if (mRequestThread.get() != nullptr) {
1783 mRequestThread->setPaused(true);
1784 } else {
1785 return NO_INIT;
1786 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001787
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07001788 ALOGV("%s: Camera %s: Internal wait until idle (% " PRIi64 " ns)", __FUNCTION__, mId.string(),
1789 maxExpectedDuration);
1790 status_t res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001791 if (res != OK) {
1792 SET_ERR_L("Can't idle device in %f seconds!",
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07001793 maxExpectedDuration/1e9);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001794 }
1795
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001796 return res;
1797}
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001798
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001799// Resume after internalPauseAndWaitLocked
1800status_t Camera3Device::internalResumeLocked() {
1801 status_t res;
1802
1803 mRequestThread->setPaused(false);
1804
Eino-Ville Talvala002001b2018-01-23 16:53:50 -08001805 ALOGV("%s: Camera %s: Internal wait until active (% " PRIi64 " ns)", __FUNCTION__, mId.string(),
1806 kActiveTimeout);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001807 res = waitUntilStateThenRelock(/*active*/ true, kActiveTimeout);
1808 if (res != OK) {
1809 SET_ERR_L("Can't transition to active in %f seconds!",
1810 kActiveTimeout/1e9);
1811 }
1812 mPauseStateNotify = false;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001813 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001814}
1815
Ruben Brunk183f0562015-08-12 12:55:02 -07001816status_t Camera3Device::waitUntilStateThenRelock(bool active, nsecs_t timeout) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001817 status_t res = OK;
Ruben Brunk183f0562015-08-12 12:55:02 -07001818
1819 size_t startIndex = 0;
1820 if (mStatusWaiters == 0) {
1821 // Clear the list of recent statuses if there are no existing threads waiting on updates to
1822 // this status list
1823 mRecentStatusUpdates.clear();
1824 } else {
1825 // If other threads are waiting on updates to this status list, set the position of the
1826 // first element that this list will check rather than clearing the list.
1827 startIndex = mRecentStatusUpdates.size();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001828 }
1829
Ruben Brunk183f0562015-08-12 12:55:02 -07001830 mStatusWaiters++;
1831
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07001832 if (!active && mUseHalBufManager) {
1833 auto streamIds = mOutputStreams.getStreamIds();
Yin-Chia Yehcd333fe2019-02-08 13:45:41 -08001834 if (mStatus == STATUS_ACTIVE) {
1835 mRequestThread->signalPipelineDrain(streamIds);
1836 }
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07001837 mRequestBufferSM.onWaitUntilIdle();
1838 }
1839
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001840 bool stateSeen = false;
1841 do {
Ruben Brunk183f0562015-08-12 12:55:02 -07001842 if (active == (mStatus == STATUS_ACTIVE)) {
1843 // Desired state is current
1844 break;
1845 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001846
1847 res = mStatusChanged.waitRelative(mLock, timeout);
1848 if (res != OK) break;
1849
Ruben Brunk183f0562015-08-12 12:55:02 -07001850 // This is impossible, but if not, could result in subtle deadlocks and invalid state
1851 // transitions.
1852 LOG_ALWAYS_FATAL_IF(startIndex > mRecentStatusUpdates.size(),
1853 "%s: Skipping status updates in Camera3Device, may result in deadlock.",
1854 __FUNCTION__);
1855
1856 // Encountered desired state since we began waiting
1857 for (size_t i = startIndex; i < mRecentStatusUpdates.size(); i++) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001858 if (active == (mRecentStatusUpdates[i] == STATUS_ACTIVE) ) {
1859 stateSeen = true;
1860 break;
1861 }
1862 }
1863 } while (!stateSeen);
1864
Ruben Brunk183f0562015-08-12 12:55:02 -07001865 mStatusWaiters--;
1866
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001867 return res;
1868}
1869
1870
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07001871status_t Camera3Device::setNotifyCallback(wp<NotificationListener> listener) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001872 ATRACE_CALL();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001873 std::lock_guard<std::mutex> l(mOutputLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001874
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001875 if (listener != NULL && mListener != NULL) {
1876 ALOGW("%s: Replacing old callback listener", __FUNCTION__);
1877 }
1878 mListener = listener;
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07001879 mRequestThread->setNotificationListener(listener);
1880 mPreparerThread->setNotificationListener(listener);
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001881
1882 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001883}
1884
Eino-Ville Talvala46910bd2013-07-18 19:15:17 -07001885bool Camera3Device::willNotify3A() {
1886 return false;
1887}
1888
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001889status_t Camera3Device::waitForNextFrame(nsecs_t timeout) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07001890 ATRACE_CALL();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001891 std::unique_lock<std::mutex> l(mOutputLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001892
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001893 while (mResultQueue.empty()) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001894 auto st = mResultSignal.wait_for(l, std::chrono::nanoseconds(timeout));
1895 if (st == std::cv_status::timeout) {
1896 return TIMED_OUT;
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001897 }
1898 }
1899 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001900}
1901
Jianing Weicb0652e2014-03-12 18:29:36 -07001902status_t Camera3Device::getNextResult(CaptureResult *frame) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001903 ATRACE_CALL();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001904 std::lock_guard<std::mutex> l(mOutputLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001905
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001906 if (mResultQueue.empty()) {
1907 return NOT_ENOUGH_DATA;
1908 }
1909
Jianing Weicb0652e2014-03-12 18:29:36 -07001910 if (frame == NULL) {
1911 ALOGE("%s: argument cannot be NULL", __FUNCTION__);
1912 return BAD_VALUE;
1913 }
1914
1915 CaptureResult &result = *(mResultQueue.begin());
1916 frame->mResultExtras = result.mResultExtras;
1917 frame->mMetadata.acquire(result.mMetadata);
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001918 frame->mPhysicalMetadatas = std::move(result.mPhysicalMetadatas);
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001919 mResultQueue.erase(mResultQueue.begin());
1920
1921 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001922}
1923
1924status_t Camera3Device::triggerAutofocus(uint32_t id) {
1925 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001926 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001927
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001928 ALOGV("%s: Triggering autofocus, id %d", __FUNCTION__, id);
1929 // Mix-in this trigger into the next request and only the next request.
1930 RequestTrigger trigger[] = {
1931 {
1932 ANDROID_CONTROL_AF_TRIGGER,
1933 ANDROID_CONTROL_AF_TRIGGER_START
1934 },
1935 {
1936 ANDROID_CONTROL_AF_TRIGGER_ID,
1937 static_cast<int32_t>(id)
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07001938 }
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001939 };
1940
1941 return mRequestThread->queueTrigger(trigger,
1942 sizeof(trigger)/sizeof(trigger[0]));
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001943}
1944
1945status_t Camera3Device::triggerCancelAutofocus(uint32_t id) {
1946 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001947 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001948
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001949 ALOGV("%s: Triggering cancel autofocus, id %d", __FUNCTION__, id);
1950 // Mix-in this trigger into the next request and only the next request.
1951 RequestTrigger trigger[] = {
1952 {
1953 ANDROID_CONTROL_AF_TRIGGER,
1954 ANDROID_CONTROL_AF_TRIGGER_CANCEL
1955 },
1956 {
1957 ANDROID_CONTROL_AF_TRIGGER_ID,
1958 static_cast<int32_t>(id)
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07001959 }
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001960 };
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001961
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001962 return mRequestThread->queueTrigger(trigger,
1963 sizeof(trigger)/sizeof(trigger[0]));
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001964}
1965
1966status_t Camera3Device::triggerPrecaptureMetering(uint32_t id) {
1967 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001968 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001969
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001970 ALOGV("%s: Triggering precapture metering, id %d", __FUNCTION__, id);
1971 // Mix-in this trigger into the next request and only the next request.
1972 RequestTrigger trigger[] = {
1973 {
1974 ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
1975 ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_START
1976 },
1977 {
1978 ANDROID_CONTROL_AE_PRECAPTURE_ID,
1979 static_cast<int32_t>(id)
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07001980 }
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001981 };
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001982
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001983 return mRequestThread->queueTrigger(trigger,
1984 sizeof(trigger)/sizeof(trigger[0]));
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001985}
1986
Jianing Weicb0652e2014-03-12 18:29:36 -07001987status_t Camera3Device::flush(int64_t *frameNumber) {
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07001988 ATRACE_CALL();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001989 ALOGV("%s: Camera %s: Flushing all requests", __FUNCTION__, mId.string());
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001990 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07001991
Zhijun He7ef20392014-04-21 16:04:17 -07001992 {
1993 Mutex::Autolock l(mLock);
Emilian Peeved2ebe42018-09-25 16:59:09 +01001994
1995 // b/116514106 "disconnect()" can get called twice for the same device. The
1996 // camera device will not be initialized during the second run.
1997 if (mStatus == STATUS_UNINITIALIZED) {
1998 return OK;
1999 }
2000
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07002001 mRequestThread->clear(/*out*/frameNumber);
Zhijun He7ef20392014-04-21 16:04:17 -07002002 }
2003
Emilian Peev08dd2452017-04-06 16:55:14 +01002004 return mRequestThread->flush();
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07002005}
2006
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002007status_t Camera3Device::prepare(int streamId) {
Ruben Brunkc78ac262015-08-13 17:58:46 -07002008 return prepare(camera3::Camera3StreamInterface::ALLOCATE_PIPELINE_MAX, streamId);
2009}
2010
2011status_t Camera3Device::prepare(int maxCount, int streamId) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002012 ATRACE_CALL();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002013 ALOGV("%s: Camera %s: Preparing stream %d", __FUNCTION__, mId.string(), streamId);
Eino-Ville Talvala261394e2015-05-13 14:28:38 -07002014 Mutex::Autolock il(mInterfaceLock);
2015 Mutex::Autolock l(mLock);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002016
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002017 sp<Camera3StreamInterface> stream = mOutputStreams.get(streamId);
2018 if (stream == nullptr) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002019 CLOGE("Stream %d does not exist", streamId);
2020 return BAD_VALUE;
2021 }
2022
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002023 if (stream->isUnpreparable() || stream->hasOutstandingBuffers() ) {
Eino-Ville Talvala261394e2015-05-13 14:28:38 -07002024 CLOGE("Stream %d has already been a request target", streamId);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002025 return BAD_VALUE;
2026 }
2027
2028 if (mRequestThread->isStreamPending(stream)) {
Eino-Ville Talvala261394e2015-05-13 14:28:38 -07002029 CLOGE("Stream %d is already a target in a pending request", streamId);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002030 return BAD_VALUE;
2031 }
2032
Ruben Brunkc78ac262015-08-13 17:58:46 -07002033 return mPreparerThread->prepare(maxCount, stream);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002034}
2035
Eino-Ville Talvalab25e3c82015-07-15 16:04:27 -07002036status_t Camera3Device::tearDown(int streamId) {
2037 ATRACE_CALL();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002038 ALOGV("%s: Camera %s: Tearing down stream %d", __FUNCTION__, mId.string(), streamId);
Eino-Ville Talvalab25e3c82015-07-15 16:04:27 -07002039 Mutex::Autolock il(mInterfaceLock);
2040 Mutex::Autolock l(mLock);
2041
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002042 sp<Camera3StreamInterface> stream = mOutputStreams.get(streamId);
2043 if (stream == nullptr) {
Eino-Ville Talvalab25e3c82015-07-15 16:04:27 -07002044 CLOGE("Stream %d does not exist", streamId);
2045 return BAD_VALUE;
2046 }
2047
Eino-Ville Talvalab25e3c82015-07-15 16:04:27 -07002048 if (stream->hasOutstandingBuffers() || mRequestThread->isStreamPending(stream)) {
2049 CLOGE("Stream %d is a target of a in-progress request", streamId);
2050 return BAD_VALUE;
2051 }
2052
2053 return stream->tearDown();
2054}
2055
Shuzhen Wangb0fdc1e2016-03-20 23:21:39 -07002056status_t Camera3Device::addBufferListenerForStream(int streamId,
2057 wp<Camera3StreamBufferListener> listener) {
2058 ATRACE_CALL();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002059 ALOGV("%s: Camera %s: Adding buffer listener for stream %d", __FUNCTION__, mId.string(), streamId);
Shuzhen Wangb0fdc1e2016-03-20 23:21:39 -07002060 Mutex::Autolock il(mInterfaceLock);
2061 Mutex::Autolock l(mLock);
2062
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002063 sp<Camera3StreamInterface> stream = mOutputStreams.get(streamId);
2064 if (stream == nullptr) {
Shuzhen Wangb0fdc1e2016-03-20 23:21:39 -07002065 CLOGE("Stream %d does not exist", streamId);
2066 return BAD_VALUE;
2067 }
Shuzhen Wangb0fdc1e2016-03-20 23:21:39 -07002068 stream->addBufferListener(listener);
2069
2070 return OK;
2071}
2072
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002073/**
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002074 * Methods called by subclasses
2075 */
2076
2077void Camera3Device::notifyStatus(bool idle) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07002078 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002079 {
2080 // Need mLock to safely update state and synchronize to current
2081 // state of methods in flight.
2082 Mutex::Autolock l(mLock);
2083 // We can get various system-idle notices from the status tracker
2084 // while starting up. Only care about them if we've actually sent
2085 // in some requests recently.
2086 if (mStatus != STATUS_ACTIVE && mStatus != STATUS_CONFIGURED) {
2087 return;
2088 }
Eino-Ville Talvala002001b2018-01-23 16:53:50 -08002089 ALOGV("%s: Camera %s: Now %s, pauseState: %s", __FUNCTION__, mId.string(),
2090 idle ? "idle" : "active", mPauseStateNotify ? "true" : "false");
Ruben Brunk183f0562015-08-12 12:55:02 -07002091 internalUpdateStatusLocked(idle ? STATUS_CONFIGURED : STATUS_ACTIVE);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002092
2093 // Skip notifying listener if we're doing some user-transparent
2094 // state changes
2095 if (mPauseStateNotify) return;
2096 }
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07002097
2098 sp<NotificationListener> listener;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002099 {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002100 std::lock_guard<std::mutex> l(mOutputLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07002101 listener = mListener.promote();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002102 }
2103 if (idle && listener != NULL) {
2104 listener->notifyIdle();
2105 }
2106}
2107
Shuzhen Wang758c2152017-01-10 18:26:18 -08002108status_t Camera3Device::setConsumerSurfaces(int streamId,
Emilian Peev40ead602017-09-26 15:46:36 +01002109 const std::vector<sp<Surface>>& consumers, std::vector<int> *surfaceIds) {
Zhijun He5d677d12016-05-29 16:52:39 -07002110 ATRACE_CALL();
Shuzhen Wang758c2152017-01-10 18:26:18 -08002111 ALOGV("%s: Camera %s: set consumer surface for stream %d",
2112 __FUNCTION__, mId.string(), streamId);
Emilian Peev40ead602017-09-26 15:46:36 +01002113
2114 if (surfaceIds == nullptr) {
2115 return BAD_VALUE;
2116 }
2117
Zhijun He5d677d12016-05-29 16:52:39 -07002118 Mutex::Autolock il(mInterfaceLock);
2119 Mutex::Autolock l(mLock);
2120
Shuzhen Wang758c2152017-01-10 18:26:18 -08002121 if (consumers.size() == 0) {
2122 CLOGE("No consumer is passed!");
Zhijun He5d677d12016-05-29 16:52:39 -07002123 return BAD_VALUE;
2124 }
2125
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002126 sp<Camera3OutputStreamInterface> stream = mOutputStreams.get(streamId);
2127 if (stream == nullptr) {
Zhijun He5d677d12016-05-29 16:52:39 -07002128 CLOGE("Stream %d is unknown", streamId);
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002129 return BAD_VALUE;
Zhijun He5d677d12016-05-29 16:52:39 -07002130 }
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002131
2132 // isConsumerConfigurationDeferred will be off after setConsumers
2133 bool isDeferred = stream->isConsumerConfigurationDeferred();
Shuzhen Wang758c2152017-01-10 18:26:18 -08002134 status_t res = stream->setConsumers(consumers);
Zhijun He5d677d12016-05-29 16:52:39 -07002135 if (res != OK) {
2136 CLOGE("Stream %d set consumer failed (error %d %s) ", streamId, res, strerror(-res));
2137 return res;
2138 }
2139
Emilian Peev40ead602017-09-26 15:46:36 +01002140 for (auto &consumer : consumers) {
2141 int id = stream->getSurfaceId(consumer);
2142 if (id < 0) {
2143 CLOGE("Invalid surface id!");
2144 return BAD_VALUE;
2145 }
2146 surfaceIds->push_back(id);
2147 }
2148
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002149 if (isDeferred) {
Shuzhen Wang0129d522016-10-30 22:43:41 -07002150 if (!stream->isConfiguring()) {
2151 CLOGE("Stream %d was already fully configured.", streamId);
2152 return INVALID_OPERATION;
2153 }
Zhijun He5d677d12016-05-29 16:52:39 -07002154
Shuzhen Wang0129d522016-10-30 22:43:41 -07002155 res = stream->finishConfiguration();
2156 if (res != OK) {
Shuzhen Wang210ba5c2018-07-25 16:47:40 -07002157 // If finishConfiguration fails due to abandoned surface, do not set
2158 // device to error state.
2159 bool isSurfaceAbandoned =
2160 (res == NO_INIT || res == DEAD_OBJECT) && stream->isAbandoned();
2161 if (!isSurfaceAbandoned) {
2162 SET_ERR_L("Can't finish configuring output stream %d: %s (%d)",
2163 stream->getId(), strerror(-res), res);
2164 }
Shuzhen Wang0129d522016-10-30 22:43:41 -07002165 return res;
2166 }
Zhijun He5d677d12016-05-29 16:52:39 -07002167 }
2168
2169 return OK;
2170}
2171
Emilian Peev40ead602017-09-26 15:46:36 +01002172status_t Camera3Device::updateStream(int streamId, const std::vector<sp<Surface>> &newSurfaces,
2173 const std::vector<OutputStreamInfo> &outputInfo,
2174 const std::vector<size_t> &removedSurfaceIds, KeyedVector<sp<Surface>, size_t> *outputMap) {
2175 Mutex::Autolock il(mInterfaceLock);
2176 Mutex::Autolock l(mLock);
2177
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002178 sp<Camera3OutputStreamInterface> stream = mOutputStreams.get(streamId);
2179 if (stream == nullptr) {
Emilian Peev40ead602017-09-26 15:46:36 +01002180 CLOGE("Stream %d is unknown", streamId);
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002181 return BAD_VALUE;
Emilian Peev40ead602017-09-26 15:46:36 +01002182 }
2183
2184 for (const auto &it : removedSurfaceIds) {
2185 if (mRequestThread->isOutputSurfacePending(streamId, it)) {
2186 CLOGE("Shared surface still part of a pending request!");
2187 return -EBUSY;
2188 }
2189 }
2190
Emilian Peev40ead602017-09-26 15:46:36 +01002191 status_t res = stream->updateStream(newSurfaces, outputInfo, removedSurfaceIds, outputMap);
2192 if (res != OK) {
2193 CLOGE("Stream %d failed to update stream (error %d %s) ",
2194 streamId, res, strerror(-res));
2195 if (res == UNKNOWN_ERROR) {
2196 SET_ERR_L("%s: Stream update failed to revert to previous output configuration!",
2197 __FUNCTION__);
2198 }
2199 return res;
2200 }
2201
2202 return res;
2203}
2204
Chien-Yu Chena936ac22017-10-23 15:59:49 -07002205status_t Camera3Device::dropStreamBuffers(bool dropping, int streamId) {
2206 Mutex::Autolock il(mInterfaceLock);
2207 Mutex::Autolock l(mLock);
2208
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002209 sp<Camera3OutputStreamInterface> stream = mOutputStreams.get(streamId);
2210 if (stream == nullptr) {
Chien-Yu Chena936ac22017-10-23 15:59:49 -07002211 ALOGE("%s: Stream %d is not found.", __FUNCTION__, streamId);
2212 return BAD_VALUE;
2213 }
Chien-Yu Chena936ac22017-10-23 15:59:49 -07002214 return stream->dropBuffers(dropping);
2215}
2216
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002217/**
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002218 * Camera3Device private methods
2219 */
2220
2221sp<Camera3Device::CaptureRequest> Camera3Device::createCaptureRequest(
Emilian Peevaebbe412018-01-15 13:53:24 +00002222 const PhysicalCameraSettingsList &request, const SurfaceMap &surfaceMap) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002223 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002224
2225 sp<CaptureRequest> newRequest = new CaptureRequest;
Emilian Peevaebbe412018-01-15 13:53:24 +00002226 newRequest->mSettingsList = request;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002227
2228 camera_metadata_entry_t inputStreams =
Emilian Peevaebbe412018-01-15 13:53:24 +00002229 newRequest->mSettingsList.begin()->metadata.find(ANDROID_REQUEST_INPUT_STREAMS);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002230 if (inputStreams.count > 0) {
2231 if (mInputStream == NULL ||
Zhijun Hed1d64672013-09-06 15:00:01 -07002232 mInputStream->getId() != inputStreams.data.i32[0]) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002233 CLOGE("Request references unknown input stream %d",
2234 inputStreams.data.u8[0]);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002235 return NULL;
2236 }
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002237
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002238 if (mInputStream->isConfiguring()) {
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002239 SET_ERR_L("%s: input stream %d is not configured!",
2240 __FUNCTION__, mInputStream->getId());
2241 return NULL;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002242 }
Shuzhen Wangb3a0fb52018-09-13 17:24:08 -07002243 // Check if stream prepare is blocking requests.
2244 if (mInputStream->isBlockedByPrepare()) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002245 CLOGE("Request references an input stream that's being prepared!");
2246 return NULL;
2247 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002248
2249 newRequest->mInputStream = mInputStream;
Emilian Peevaebbe412018-01-15 13:53:24 +00002250 newRequest->mSettingsList.begin()->metadata.erase(ANDROID_REQUEST_INPUT_STREAMS);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002251 }
2252
2253 camera_metadata_entry_t streams =
Emilian Peevaebbe412018-01-15 13:53:24 +00002254 newRequest->mSettingsList.begin()->metadata.find(ANDROID_REQUEST_OUTPUT_STREAMS);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002255 if (streams.count == 0) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002256 CLOGE("Zero output streams specified!");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002257 return NULL;
2258 }
2259
2260 for (size_t i = 0; i < streams.count; i++) {
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002261 sp<Camera3OutputStreamInterface> stream = mOutputStreams.get(streams.data.i32[i]);
2262 if (stream == nullptr) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002263 CLOGE("Request references unknown stream %d",
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002264 streams.data.i32[i]);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002265 return NULL;
2266 }
Zhijun He5d677d12016-05-29 16:52:39 -07002267 // It is illegal to include a deferred consumer output stream into a request
Shuzhen Wang0129d522016-10-30 22:43:41 -07002268 auto iter = surfaceMap.find(streams.data.i32[i]);
2269 if (iter != surfaceMap.end()) {
2270 const std::vector<size_t>& surfaces = iter->second;
2271 for (const auto& surface : surfaces) {
2272 if (stream->isConsumerConfigurationDeferred(surface)) {
2273 CLOGE("Stream %d surface %zu hasn't finished configuration yet "
2274 "due to deferred consumer", stream->getId(), surface);
2275 return NULL;
2276 }
2277 }
Yin-Chia Yeh0b287572018-10-15 12:38:13 -07002278 newRequest->mOutputSurfaces[streams.data.i32[i]] = surfaces;
Zhijun He5d677d12016-05-29 16:52:39 -07002279 }
2280
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002281 if (stream->isConfiguring()) {
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002282 SET_ERR_L("%s: stream %d is not configured!", __FUNCTION__, stream->getId());
2283 return NULL;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002284 }
Shuzhen Wangb3a0fb52018-09-13 17:24:08 -07002285 // Check if stream prepare is blocking requests.
2286 if (stream->isBlockedByPrepare()) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002287 CLOGE("Request references an output stream that's being prepared!");
2288 return NULL;
2289 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002290
2291 newRequest->mOutputStreams.push(stream);
2292 }
Emilian Peevaebbe412018-01-15 13:53:24 +00002293 newRequest->mSettingsList.begin()->metadata.erase(ANDROID_REQUEST_OUTPUT_STREAMS);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07002294 newRequest->mBatchSize = 1;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002295
2296 return newRequest;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002297}
2298
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002299void Camera3Device::cancelStreamsConfigurationLocked() {
2300 int res = OK;
2301 if (mInputStream != NULL && mInputStream->isConfiguring()) {
2302 res = mInputStream->cancelConfiguration();
2303 if (res != OK) {
2304 CLOGE("Can't cancel configuring input stream %d: %s (%d)",
2305 mInputStream->getId(), strerror(-res), res);
2306 }
2307 }
2308
2309 for (size_t i = 0; i < mOutputStreams.size(); i++) {
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002310 sp<Camera3OutputStreamInterface> outputStream = mOutputStreams[i];
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002311 if (outputStream->isConfiguring()) {
2312 res = outputStream->cancelConfiguration();
2313 if (res != OK) {
2314 CLOGE("Can't cancel configuring output stream %d: %s (%d)",
2315 outputStream->getId(), strerror(-res), res);
2316 }
2317 }
2318 }
2319
2320 // Return state to that at start of call, so that future configures
2321 // properly clean things up
2322 internalUpdateStatusLocked(STATUS_UNCONFIGURED);
2323 mNeedConfig = true;
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002324
2325 res = mPreparerThread->resume();
2326 if (res != OK) {
2327 ALOGE("%s: Camera %s: Preparer thread failed to resume!", __FUNCTION__, mId.string());
2328 }
2329}
2330
2331bool Camera3Device::reconfigureCamera(const CameraMetadata& sessionParams) {
2332 ATRACE_CALL();
2333 bool ret = false;
2334
Jayant Chowdhary37eca242019-11-18 08:55:56 -08002335 // We must not hold mInterfaceLock here since this function is called from
2336 // RequestThread::threadLoop and holding mInterfaceLock could lead to
2337 // deadlocks (http://b/143513518)
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002338 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
2339
2340 Mutex::Autolock l(mLock);
2341 auto rc = internalPauseAndWaitLocked(maxExpectedDuration);
2342 if (rc == NO_ERROR) {
2343 mNeedConfig = true;
2344 rc = configureStreamsLocked(mOperatingMode, sessionParams, /*notifyRequestThread*/ false);
2345 if (rc == NO_ERROR) {
2346 ret = true;
2347 mPauseStateNotify = false;
2348 //Moving to active state while holding 'mLock' is important.
2349 //There could be pending calls to 'create-/deleteStream' which
2350 //will trigger another stream configuration while the already
2351 //present streams end up with outstanding buffers that will
2352 //not get drained.
2353 internalUpdateStatusLocked(STATUS_ACTIVE);
Shuzhen Wang210ba5c2018-07-25 16:47:40 -07002354 } else if (rc == DEAD_OBJECT) {
2355 // DEAD_OBJECT can be returned if either the consumer surface is
2356 // abandoned, or the HAL has died.
2357 // - If the HAL has died, configureStreamsLocked call will set
2358 // device to error state,
2359 // - If surface is abandoned, we should not set device to error
2360 // state.
2361 ALOGE("Failed to re-configure camera due to abandoned surface");
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002362 } else {
Shuzhen Wang210ba5c2018-07-25 16:47:40 -07002363 SET_ERR_L("Failed to re-configure camera: %d", rc);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002364 }
2365 } else {
2366 ALOGE("%s: Failed to pause streaming: %d", __FUNCTION__, rc);
2367 }
2368
2369 return ret;
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002370}
2371
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01002372status_t Camera3Device::configureStreamsLocked(int operatingMode,
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002373 const CameraMetadata& sessionParams, bool notifyRequestThread) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002374 ATRACE_CALL();
2375 status_t res;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002376
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002377 if (mStatus != STATUS_UNCONFIGURED && mStatus != STATUS_CONFIGURED) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002378 CLOGE("Not idle");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002379 return INVALID_OPERATION;
2380 }
2381
Eino-Ville Talvalae7091aa2017-03-07 15:23:06 -08002382 if (operatingMode < 0) {
2383 CLOGE("Invalid operating mode: %d", operatingMode);
2384 return BAD_VALUE;
2385 }
2386
2387 bool isConstrainedHighSpeed =
2388 static_cast<int>(StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE) ==
2389 operatingMode;
2390
2391 if (mOperatingMode != operatingMode) {
2392 mNeedConfig = true;
2393 mIsConstrainedHighSpeedConfiguration = isConstrainedHighSpeed;
2394 mOperatingMode = operatingMode;
2395 }
2396
Shuzhen Wang0cf01cb2019-09-05 13:33:06 -07002397 // In case called from configureStreams, abort queued input buffers not belonging to
2398 // any pending requests.
2399 if (mInputStream != NULL && notifyRequestThread) {
2400 while (true) {
2401 camera3_stream_buffer_t inputBuffer;
2402 status_t res = mInputStream->getInputBuffer(&inputBuffer,
2403 /*respectHalLimit*/ false);
2404 if (res != OK) {
2405 // Exhausted acquiring all input buffers.
2406 break;
2407 }
2408
2409 inputBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
2410 res = mInputStream->returnInputBuffer(inputBuffer);
2411 if (res != OK) {
2412 ALOGE("%s: %d: couldn't return input buffer while clearing input queue: "
2413 "%s (%d)", __FUNCTION__, __LINE__, strerror(-res), res);
2414 }
2415 }
2416 }
2417
Eino-Ville Talvalaea26c772013-06-11 16:04:06 -07002418 if (!mNeedConfig) {
2419 ALOGV("%s: Skipping config, no stream changes", __FUNCTION__);
2420 return OK;
2421 }
2422
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002423 // Workaround for device HALv3.2 or older spec bug - zero streams requires
2424 // adding a dummy stream instead.
2425 // TODO: Bug: 17321404 for fixing the HAL spec and removing this workaround.
2426 if (mOutputStreams.size() == 0) {
2427 addDummyStreamLocked();
2428 } else {
2429 tryRemoveDummyStreamLocked();
2430 }
2431
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002432 // Start configuring the streams
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002433 ALOGV("%s: Camera %s: Starting stream configuration", __FUNCTION__, mId.string());
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002434
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002435 mPreparerThread->pause();
2436
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002437 camera3_stream_configuration config;
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -08002438 config.operation_mode = mOperatingMode;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002439 config.num_streams = (mInputStream != NULL) + mOutputStreams.size();
2440
2441 Vector<camera3_stream_t*> streams;
2442 streams.setCapacity(config.num_streams);
Emilian Peev192ee832018-01-31 14:46:47 +00002443 std::vector<uint32_t> bufferSizes(config.num_streams, 0);
Yin-Chia Yehfb6e55b2018-01-25 10:50:26 -08002444
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002445
2446 if (mInputStream != NULL) {
2447 camera3_stream_t *inputStream;
2448 inputStream = mInputStream->startConfiguration();
2449 if (inputStream == NULL) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002450 CLOGE("Can't start input stream configuration");
2451 cancelStreamsConfigurationLocked();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002452 return INVALID_OPERATION;
2453 }
2454 streams.add(inputStream);
2455 }
2456
2457 for (size_t i = 0; i < mOutputStreams.size(); i++) {
Igor Murashkin2fba5842013-04-22 14:03:54 -07002458
2459 // Don't configure bidi streams twice, nor add them twice to the list
2460 if (mOutputStreams[i].get() ==
2461 static_cast<Camera3StreamInterface*>(mInputStream.get())) {
2462
2463 config.num_streams--;
2464 continue;
2465 }
2466
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002467 camera3_stream_t *outputStream;
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002468 outputStream = mOutputStreams[i]->startConfiguration();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002469 if (outputStream == NULL) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002470 CLOGE("Can't start output stream configuration");
2471 cancelStreamsConfigurationLocked();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002472 return INVALID_OPERATION;
2473 }
2474 streams.add(outputStream);
Yin-Chia Yehfb6e55b2018-01-25 10:50:26 -08002475
Shuzhen Wangb7ab1e42019-02-20 15:42:23 -08002476 if (outputStream->format == HAL_PIXEL_FORMAT_BLOB) {
Emilian Peev192ee832018-01-31 14:46:47 +00002477 size_t k = i + ((mInputStream != nullptr) ? 1 : 0); // Input stream if present should
2478 // always occupy the initial entry.
Shuzhen Wangb7ab1e42019-02-20 15:42:23 -08002479 if (outputStream->data_space == HAL_DATASPACE_V0_JFIF) {
2480 bufferSizes[k] = static_cast<uint32_t>(
2481 getJpegBufferSize(outputStream->width, outputStream->height));
2482 } else if (outputStream->data_space ==
2483 static_cast<android_dataspace>(HAL_DATASPACE_JPEG_APP_SEGMENTS)) {
2484 bufferSizes[k] = outputStream->width * outputStream->height;
2485 } else {
2486 ALOGW("%s: Blob dataSpace %d not supported",
2487 __FUNCTION__, outputStream->data_space);
2488 }
Yin-Chia Yehfb6e55b2018-01-25 10:50:26 -08002489 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002490 }
2491
2492 config.streams = streams.editArray();
2493
2494 // Do the HAL configuration; will potentially touch stream
Shuzhen Wang92653952019-05-07 15:11:43 -07002495 // max_buffers, usage, and priv fields, as well as data_space and format
2496 // fields for IMPLEMENTATION_DEFINED formats.
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002497
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01002498 const camera_metadata_t *sessionBuffer = sessionParams.getAndLock();
Emilian Peev192ee832018-01-31 14:46:47 +00002499 res = mInterface->configureStreams(sessionBuffer, &config, bufferSizes);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01002500 sessionParams.unlock(sessionBuffer);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002501
Eino-Ville Talvala17543512014-08-06 14:32:02 -07002502 if (res == BAD_VALUE) {
2503 // HAL rejected this set of streams as unsupported, clean up config
2504 // attempt and return to unconfigured state
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002505 CLOGE("Set of requested inputs/outputs not supported by HAL");
2506 cancelStreamsConfigurationLocked();
Eino-Ville Talvala17543512014-08-06 14:32:02 -07002507 return BAD_VALUE;
2508 } else if (res != OK) {
2509 // Some other kind of error from configure_streams - this is not
2510 // expected
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002511 SET_ERR_L("Unable to configure streams with HAL: %s (%d)",
2512 strerror(-res), res);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002513 return res;
2514 }
2515
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002516 // Finish all stream configuration immediately.
2517 // TODO: Try to relax this later back to lazy completion, which should be
2518 // faster
2519
Igor Murashkin073f8572013-05-02 14:59:28 -07002520 if (mInputStream != NULL && mInputStream->isConfiguring()) {
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002521 bool streamReConfigured = false;
2522 res = mInputStream->finishConfiguration(&streamReConfigured);
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002523 if (res != OK) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002524 CLOGE("Can't finish configuring input stream %d: %s (%d)",
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002525 mInputStream->getId(), strerror(-res), res);
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002526 cancelStreamsConfigurationLocked();
Shuzhen Wang210ba5c2018-07-25 16:47:40 -07002527 if ((res == NO_INIT || res == DEAD_OBJECT) && mInputStream->isAbandoned()) {
2528 return DEAD_OBJECT;
2529 }
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002530 return BAD_VALUE;
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002531 }
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002532 if (streamReConfigured) {
2533 mInterface->onStreamReConfigured(mInputStream->getId());
2534 }
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002535 }
2536
2537 for (size_t i = 0; i < mOutputStreams.size(); i++) {
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002538 sp<Camera3OutputStreamInterface> outputStream = mOutputStreams[i];
Zhijun He5d677d12016-05-29 16:52:39 -07002539 if (outputStream->isConfiguring() && !outputStream->isConsumerConfigurationDeferred()) {
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002540 bool streamReConfigured = false;
2541 res = outputStream->finishConfiguration(&streamReConfigured);
Igor Murashkin073f8572013-05-02 14:59:28 -07002542 if (res != OK) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002543 CLOGE("Can't finish configuring output stream %d: %s (%d)",
Igor Murashkin073f8572013-05-02 14:59:28 -07002544 outputStream->getId(), strerror(-res), res);
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002545 cancelStreamsConfigurationLocked();
Shuzhen Wang210ba5c2018-07-25 16:47:40 -07002546 if ((res == NO_INIT || res == DEAD_OBJECT) && outputStream->isAbandoned()) {
2547 return DEAD_OBJECT;
2548 }
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002549 return BAD_VALUE;
Igor Murashkin073f8572013-05-02 14:59:28 -07002550 }
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002551 if (streamReConfigured) {
2552 mInterface->onStreamReConfigured(outputStream->getId());
2553 }
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002554 }
2555 }
2556
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002557 // Request thread needs to know to avoid using repeat-last-settings protocol
2558 // across configure_streams() calls
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002559 if (notifyRequestThread) {
2560 mRequestThread->configurationComplete(mIsConstrainedHighSpeedConfiguration, sessionParams);
2561 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002562
Zhijun He90f7c372016-08-16 16:19:43 -07002563 char value[PROPERTY_VALUE_MAX];
2564 property_get("camera.fifo.disable", value, "0");
2565 int32_t disableFifo = atoi(value);
2566 if (disableFifo != 1) {
2567 // Boost priority of request thread to SCHED_FIFO.
2568 pid_t requestThreadTid = mRequestThread->getTid();
2569 res = requestPriority(getpid(), requestThreadTid,
Mikhail Naganov83f04272017-02-07 10:45:09 -08002570 kRequestThreadPriority, /*isForApp*/ false, /*asynchronous*/ false);
Zhijun He90f7c372016-08-16 16:19:43 -07002571 if (res != OK) {
2572 ALOGW("Can't set realtime priority for request processing thread: %s (%d)",
2573 strerror(-res), res);
2574 } else {
2575 ALOGD("Set real time priority for request queue thread (tid %d)", requestThreadTid);
2576 }
Eino-Ville Talvalaf99498e2015-09-25 16:52:55 -07002577 }
2578
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002579 // Update device state
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01002580 const camera_metadata_t *newSessionParams = sessionParams.getAndLock();
2581 const camera_metadata_t *currentSessionParams = mSessionParams.getAndLock();
2582 bool updateSessionParams = (newSessionParams != currentSessionParams) ? true : false;
2583 sessionParams.unlock(newSessionParams);
2584 mSessionParams.unlock(currentSessionParams);
2585 if (updateSessionParams) {
2586 mSessionParams = sessionParams;
2587 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002588
Eino-Ville Talvalaea26c772013-06-11 16:04:06 -07002589 mNeedConfig = false;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002590
Ruben Brunk183f0562015-08-12 12:55:02 -07002591 internalUpdateStatusLocked((mDummyStreamId == NO_STREAM) ?
2592 STATUS_CONFIGURED : STATUS_UNCONFIGURED);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002593
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002594 ALOGV("%s: Camera %s: Stream configuration complete", __FUNCTION__, mId.string());
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002595
Zhijun He0a210512014-07-24 13:45:15 -07002596 // tear down the deleted streams after configure streams.
2597 mDeletedStreams.clear();
2598
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002599 auto rc = mPreparerThread->resume();
2600 if (rc != OK) {
2601 SET_ERR_L("%s: Camera %s: Preparer thread failed to resume!", __FUNCTION__, mId.string());
2602 return rc;
2603 }
2604
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07002605 if (mDummyStreamId == NO_STREAM) {
2606 mRequestBufferSM.onStreamsConfigured();
2607 }
2608
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002609 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002610}
2611
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002612status_t Camera3Device::addDummyStreamLocked() {
2613 ATRACE_CALL();
2614 status_t res;
2615
2616 if (mDummyStreamId != NO_STREAM) {
2617 // Should never be adding a second dummy stream when one is already
2618 // active
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002619 SET_ERR_L("%s: Camera %s: A dummy stream already exists!",
2620 __FUNCTION__, mId.string());
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002621 return INVALID_OPERATION;
2622 }
2623
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002624 ALOGV("%s: Camera %s: Adding a dummy stream", __FUNCTION__, mId.string());
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002625
2626 sp<Camera3OutputStreamInterface> dummyStream =
2627 new Camera3DummyStream(mNextStreamId);
2628
2629 res = mOutputStreams.add(mNextStreamId, dummyStream);
2630 if (res < 0) {
2631 SET_ERR_L("Can't add dummy stream to set: %s (%d)", strerror(-res), res);
2632 return res;
2633 }
2634
2635 mDummyStreamId = mNextStreamId;
2636 mNextStreamId++;
2637
2638 return OK;
2639}
2640
2641status_t Camera3Device::tryRemoveDummyStreamLocked() {
2642 ATRACE_CALL();
2643 status_t res;
2644
2645 if (mDummyStreamId == NO_STREAM) return OK;
2646 if (mOutputStreams.size() == 1) return OK;
2647
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002648 ALOGV("%s: Camera %s: Removing the dummy stream", __FUNCTION__, mId.string());
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002649
2650 // Ok, have a dummy stream and there's at least one other output stream,
2651 // so remove the dummy
2652
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002653 sp<Camera3StreamInterface> deletedStream = mOutputStreams.get(mDummyStreamId);
2654 if (deletedStream == nullptr) {
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002655 SET_ERR_L("Dummy stream %d does not appear to exist", mDummyStreamId);
2656 return INVALID_OPERATION;
2657 }
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002658 mOutputStreams.remove(mDummyStreamId);
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002659
2660 // Free up the stream endpoint so that it can be used by some other stream
2661 res = deletedStream->disconnect();
2662 if (res != OK) {
2663 SET_ERR_L("Can't disconnect deleted dummy stream %d", mDummyStreamId);
2664 // fall through since we want to still list the stream as deleted.
2665 }
2666 mDeletedStreams.add(deletedStream);
2667 mDummyStreamId = NO_STREAM;
2668
2669 return res;
2670}
2671
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002672void Camera3Device::setErrorState(const char *fmt, ...) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07002673 ATRACE_CALL();
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002674 Mutex::Autolock l(mLock);
2675 va_list args;
2676 va_start(args, fmt);
2677
2678 setErrorStateLockedV(fmt, args);
2679
2680 va_end(args);
2681}
2682
2683void Camera3Device::setErrorStateV(const char *fmt, va_list args) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07002684 ATRACE_CALL();
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002685 Mutex::Autolock l(mLock);
2686 setErrorStateLockedV(fmt, args);
2687}
2688
2689void Camera3Device::setErrorStateLocked(const char *fmt, ...) {
2690 va_list args;
2691 va_start(args, fmt);
2692
2693 setErrorStateLockedV(fmt, args);
2694
2695 va_end(args);
2696}
2697
2698void Camera3Device::setErrorStateLockedV(const char *fmt, va_list args) {
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002699 // Print out all error messages to log
2700 String8 errorCause = String8::formatV(fmt, args);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002701 ALOGE("Camera %s: %s", mId.string(), errorCause.string());
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002702
2703 // But only do error state transition steps for the first error
Zhijun Heb05eeae2013-06-06 13:51:22 -07002704 if (mStatus == STATUS_ERROR || mStatus == STATUS_UNINITIALIZED) return;
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002705
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002706 mErrorCause = errorCause;
2707
Yin-Chia Yeh3d145ae2017-07-27 12:47:03 -07002708 if (mRequestThread != nullptr) {
2709 mRequestThread->setPaused(true);
2710 }
Ruben Brunk183f0562015-08-12 12:55:02 -07002711 internalUpdateStatusLocked(STATUS_ERROR);
Eino-Ville Talvala17543512014-08-06 14:32:02 -07002712
2713 // Notify upstream about a device error
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07002714 sp<NotificationListener> listener = mListener.promote();
2715 if (listener != NULL) {
2716 listener->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
Eino-Ville Talvala17543512014-08-06 14:32:02 -07002717 CaptureResultExtras());
2718 }
2719
2720 // Save stack trace. View by dumping it later.
2721 CameraTraces::saveTrace();
2722 // TODO: consider adding errorCause and client pid/procname
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002723}
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002724
2725/**
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002726 * In-flight request management
2727 */
2728
Jianing Weicb0652e2014-03-12 18:29:36 -07002729status_t Camera3Device::registerInFlight(uint32_t frameNumber,
Chien-Yu Chend196d612015-06-22 19:49:01 -07002730 int32_t numBuffers, CaptureResultExtras resultExtras, bool hasInput,
Shuzhen Wang5c22c152017-12-31 17:12:25 -08002731 bool hasAppCallback, nsecs_t maxExpectedDuration,
Shuzhen Wang26abaf42018-08-28 15:41:20 -07002732 std::set<String8>& physicalCameraIds, bool isStillCapture,
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08002733 bool isZslCapture, const std::set<std::string>& cameraIdsWithZoom,
2734 const SurfaceMap& outputSurfaces) {
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002735 ATRACE_CALL();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002736 std::lock_guard<std::mutex> l(mInFlightLock);
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002737
2738 ssize_t res;
Chien-Yu Chend196d612015-06-22 19:49:01 -07002739 res = mInFlightMap.add(frameNumber, InFlightRequest(numBuffers, resultExtras, hasInput,
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07002740 hasAppCallback, maxExpectedDuration, physicalCameraIds, isStillCapture, isZslCapture,
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08002741 cameraIdsWithZoom, outputSurfaces));
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002742 if (res < 0) return res;
2743
Eino-Ville Talvala24b366e2016-07-21 12:53:07 -07002744 if (mInFlightMap.size() == 1) {
Emilian Peev26d975d2018-07-05 14:52:57 +01002745 // Hold a separate dedicated tracker lock to prevent race with disconnect and also
2746 // avoid a deadlock during reprocess requests.
2747 Mutex::Autolock l(mTrackerLock);
Yin-Chia Yeh38dfde52017-06-27 17:13:33 -07002748 if (mStatusTracker != nullptr) {
2749 mStatusTracker->markComponentActive(mInFlightStatusId);
2750 }
Eino-Ville Talvala24b366e2016-07-21 12:53:07 -07002751 }
2752
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07002753 mExpectedInflightDuration += maxExpectedDuration;
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002754 return OK;
2755}
2756
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002757void Camera3Device::onInflightEntryRemovedLocked(nsecs_t duration) {
Shuzhen Wangcadb3302016-11-04 14:17:56 -07002758 // Indicate idle inFlightMap to the status tracker
2759 if (mInFlightMap.size() == 0) {
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07002760 mRequestBufferSM.onInflightMapEmpty();
Emilian Peev26d975d2018-07-05 14:52:57 +01002761 // Hold a separate dedicated tracker lock to prevent race with disconnect and also
2762 // avoid a deadlock during reprocess requests.
2763 Mutex::Autolock l(mTrackerLock);
Yin-Chia Yeh38dfde52017-06-27 17:13:33 -07002764 if (mStatusTracker != nullptr) {
2765 mStatusTracker->markComponentIdle(mInFlightStatusId, Fence::NO_FENCE);
2766 }
Shuzhen Wangcadb3302016-11-04 14:17:56 -07002767 }
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07002768 mExpectedInflightDuration -= duration;
Shuzhen Wangcadb3302016-11-04 14:17:56 -07002769}
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08002770
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002771void Camera3Device::checkInflightMapLengthLocked() {
Yin-Chia Yeh99fd0972019-06-27 14:22:44 -07002772 // Sanity check - if we have too many in-flight frames with long total inflight duration,
2773 // something has likely gone wrong. This might still be legit only if application send in
2774 // a long burst of long exposure requests.
2775 if (mExpectedInflightDuration > kMinWarnInflightDuration) {
2776 if (!mIsConstrainedHighSpeedConfiguration && mInFlightMap.size() > kInFlightWarnLimit) {
2777 CLOGW("In-flight list too large: %zu, total inflight duration %" PRIu64,
2778 mInFlightMap.size(), mExpectedInflightDuration);
2779 } else if (mIsConstrainedHighSpeedConfiguration && mInFlightMap.size() >
2780 kInFlightWarnLimitHighSpeed) {
2781 CLOGW("In-flight list too large for high speed configuration: %zu,"
2782 "total inflight duration %" PRIu64,
2783 mInFlightMap.size(), mExpectedInflightDuration);
2784 }
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08002785 }
2786}
2787
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002788void Camera3Device::onInflightMapFlushedLocked() {
2789 mExpectedInflightDuration = 0;
2790}
2791
2792void Camera3Device::removeInFlightMapEntryLocked(int idx) {
2793 ATRACE_CALL();
2794 nsecs_t duration = mInFlightMap.valueAt(idx).maxExpectedDuration;
2795 mInFlightMap.removeItemsAt(idx, 1);
2796
2797 onInflightEntryRemovedLocked(duration);
2798}
2799
2800
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07002801void Camera3Device::flushInflightRequests() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07002802 ATRACE_CALL();
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07002803 sp<NotificationListener> listener;
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07002804 {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002805 std::lock_guard<std::mutex> l(mOutputLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07002806 listener = mListener.promote();
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07002807 }
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002808
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002809 FlushInflightReqStates states {
2810 mId, mInFlightLock, mInFlightMap, mUseHalBufManager,
2811 listener, *this, *mInterface, *this};
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07002812
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002813 camera3::flushInflightRequests(states);
Eino-Ville Talvala17543512014-08-06 14:32:02 -07002814}
2815
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002816CameraMetadata Camera3Device::getLatestRequestLocked() {
Igor Murashkin1e479c02013-09-06 16:55:14 -07002817 ALOGV("%s", __FUNCTION__);
2818
Igor Murashkin1e479c02013-09-06 16:55:14 -07002819 CameraMetadata retVal;
2820
2821 if (mRequestThread != NULL) {
2822 retVal = mRequestThread->getLatestRequest();
2823 }
2824
Igor Murashkin1e479c02013-09-06 16:55:14 -07002825 return retVal;
2826}
2827
Eino-Ville Talvala4d453832016-07-15 11:56:53 -07002828void Camera3Device::monitorMetadata(TagMonitor::eventSource source,
Shuzhen Wangc2cba122018-05-17 18:10:24 -07002829 int64_t frameNumber, nsecs_t timestamp, const CameraMetadata& metadata,
2830 const std::unordered_map<std::string, CameraMetadata>& physicalMetadata) {
2831
2832 mTagMonitor.monitorMetadata(source, frameNumber, timestamp, metadata,
2833 physicalMetadata);
Eino-Ville Talvala4d453832016-07-15 11:56:53 -07002834}
2835
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002836/**
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002837 * HalInterface inner class methods
2838 */
2839
Yifan Hongf79b5542017-04-11 14:44:25 -07002840Camera3Device::HalInterface::HalInterface(
2841 sp<ICameraDeviceSession> &session,
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08002842 std::shared_ptr<RequestMetadataQueue> queue,
Yin-Chia Yehb978c382019-10-30 00:22:37 -07002843 bool useHalBufManager, bool supportOfflineProcessing) :
Yifan Hongf79b5542017-04-11 14:44:25 -07002844 mHidlSession(session),
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08002845 mRequestMetadataQueue(queue),
Emilian Peev4ec17882019-01-24 17:16:58 -08002846 mUseHalBufManager(useHalBufManager),
Yin-Chia Yehb978c382019-10-30 00:22:37 -07002847 mIsReconfigurationQuerySupported(true),
2848 mSupportOfflineProcessing(supportOfflineProcessing) {
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002849 // Check with hardware service manager if we can downcast these interfaces
2850 // Somewhat expensive, so cache the results at startup
Yin-Chia Yehb978c382019-10-30 00:22:37 -07002851 auto castResult_3_6 = device::V3_6::ICameraDeviceSession::castFrom(mHidlSession);
2852 if (castResult_3_6.isOk()) {
2853 mHidlSession_3_6 = castResult_3_6;
2854 }
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07002855 auto castResult_3_5 = device::V3_5::ICameraDeviceSession::castFrom(mHidlSession);
2856 if (castResult_3_5.isOk()) {
2857 mHidlSession_3_5 = castResult_3_5;
2858 }
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002859 auto castResult_3_4 = device::V3_4::ICameraDeviceSession::castFrom(mHidlSession);
2860 if (castResult_3_4.isOk()) {
2861 mHidlSession_3_4 = castResult_3_4;
2862 }
2863 auto castResult_3_3 = device::V3_3::ICameraDeviceSession::castFrom(mHidlSession);
2864 if (castResult_3_3.isOk()) {
2865 mHidlSession_3_3 = castResult_3_3;
2866 }
2867}
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002868
Yin-Chia Yehb978c382019-10-30 00:22:37 -07002869Camera3Device::HalInterface::HalInterface() :
2870 mUseHalBufManager(false),
2871 mSupportOfflineProcessing(false) {}
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002872
2873Camera3Device::HalInterface::HalInterface(const HalInterface& other) :
Yifan Hongf79b5542017-04-11 14:44:25 -07002874 mHidlSession(other.mHidlSession),
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08002875 mRequestMetadataQueue(other.mRequestMetadataQueue),
Yin-Chia Yehb978c382019-10-30 00:22:37 -07002876 mUseHalBufManager(other.mUseHalBufManager),
2877 mSupportOfflineProcessing(other.mSupportOfflineProcessing) {}
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002878
2879bool Camera3Device::HalInterface::valid() {
Emilian Peev31abd0a2017-05-11 18:37:46 +01002880 return (mHidlSession != nullptr);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002881}
2882
2883void Camera3Device::HalInterface::clear() {
Yin-Chia Yehb978c382019-10-30 00:22:37 -07002884 mHidlSession_3_6.clear();
Emilian Peev644a3e12018-11-23 13:52:39 +00002885 mHidlSession_3_5.clear();
Emilian Peev9e740b02018-01-30 18:28:03 +00002886 mHidlSession_3_4.clear();
2887 mHidlSession_3_3.clear();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002888 mHidlSession.clear();
2889}
2890
2891status_t Camera3Device::HalInterface::constructDefaultRequestSettings(
2892 camera3_request_template_t templateId,
2893 /*out*/ camera_metadata_t **requestTemplate) {
2894 ATRACE_NAME("CameraHal::constructDefaultRequestSettings");
2895 if (!valid()) return INVALID_OPERATION;
2896 status_t res = OK;
2897
Emilian Peev31abd0a2017-05-11 18:37:46 +01002898 common::V1_0::Status status;
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002899
2900 auto requestCallback = [&status, &requestTemplate]
Emilian Peev31abd0a2017-05-11 18:37:46 +01002901 (common::V1_0::Status s, const device::V3_2::CameraMetadata& request) {
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002902 status = s;
2903 if (status == common::V1_0::Status::OK) {
2904 const camera_metadata *r =
2905 reinterpret_cast<const camera_metadata_t*>(request.data());
2906 size_t expectedSize = request.size();
2907 int ret = validate_camera_metadata_structure(r, &expectedSize);
2908 if (ret == OK || ret == CAMERA_METADATA_VALIDATION_SHIFTED) {
2909 *requestTemplate = clone_camera_metadata(r);
2910 if (*requestTemplate == nullptr) {
2911 ALOGE("%s: Unable to clone camera metadata received from HAL",
2912 __FUNCTION__);
Emilian Peev31abd0a2017-05-11 18:37:46 +01002913 status = common::V1_0::Status::INTERNAL_ERROR;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002914 }
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002915 } else {
2916 ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
2917 status = common::V1_0::Status::INTERNAL_ERROR;
Emilian Peev31abd0a2017-05-11 18:37:46 +01002918 }
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002919 }
2920 };
2921 hardware::Return<void> err;
Eino-Ville Talvala96441462018-02-06 11:41:55 -08002922 RequestTemplate id;
2923 switch (templateId) {
2924 case CAMERA3_TEMPLATE_PREVIEW:
2925 id = RequestTemplate::PREVIEW;
2926 break;
2927 case CAMERA3_TEMPLATE_STILL_CAPTURE:
2928 id = RequestTemplate::STILL_CAPTURE;
2929 break;
2930 case CAMERA3_TEMPLATE_VIDEO_RECORD:
2931 id = RequestTemplate::VIDEO_RECORD;
2932 break;
2933 case CAMERA3_TEMPLATE_VIDEO_SNAPSHOT:
2934 id = RequestTemplate::VIDEO_SNAPSHOT;
2935 break;
2936 case CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG:
2937 id = RequestTemplate::ZERO_SHUTTER_LAG;
2938 break;
2939 case CAMERA3_TEMPLATE_MANUAL:
2940 id = RequestTemplate::MANUAL;
2941 break;
2942 default:
2943 // Unknown template ID, or this HAL is too old to support it
2944 return BAD_VALUE;
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002945 }
Eino-Ville Talvala96441462018-02-06 11:41:55 -08002946 err = mHidlSession->constructDefaultRequestSettings(id, requestCallback);
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002947
Emilian Peev31abd0a2017-05-11 18:37:46 +01002948 if (!err.isOk()) {
2949 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
2950 res = DEAD_OBJECT;
2951 } else {
2952 res = CameraProviderManager::mapToStatusT(status);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002953 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01002954
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002955 return res;
2956}
2957
Emilian Peev4ec17882019-01-24 17:16:58 -08002958bool Camera3Device::HalInterface::isReconfigurationRequired(CameraMetadata& oldSessionParams,
2959 CameraMetadata& newSessionParams) {
2960 // We do reconfiguration by default;
2961 bool ret = true;
2962 if ((mHidlSession_3_5 != nullptr) && mIsReconfigurationQuerySupported) {
2963 android::hardware::hidl_vec<uint8_t> oldParams, newParams;
2964 camera_metadata_t* oldSessioMeta = const_cast<camera_metadata_t*>(
2965 oldSessionParams.getAndLock());
2966 camera_metadata_t* newSessioMeta = const_cast<camera_metadata_t*>(
2967 newSessionParams.getAndLock());
2968 oldParams.setToExternal(reinterpret_cast<uint8_t*>(oldSessioMeta),
2969 get_camera_metadata_size(oldSessioMeta));
2970 newParams.setToExternal(reinterpret_cast<uint8_t*>(newSessioMeta),
2971 get_camera_metadata_size(newSessioMeta));
2972 hardware::camera::common::V1_0::Status callStatus;
2973 bool required;
2974 auto hidlCb = [&callStatus, &required] (hardware::camera::common::V1_0::Status s,
2975 bool requiredFlag) {
2976 callStatus = s;
2977 required = requiredFlag;
2978 };
2979 auto err = mHidlSession_3_5->isReconfigurationRequired(oldParams, newParams, hidlCb);
2980 oldSessionParams.unlock(oldSessioMeta);
2981 newSessionParams.unlock(newSessioMeta);
2982 if (err.isOk()) {
2983 switch (callStatus) {
2984 case hardware::camera::common::V1_0::Status::OK:
2985 ret = required;
2986 break;
2987 case hardware::camera::common::V1_0::Status::METHOD_NOT_SUPPORTED:
2988 mIsReconfigurationQuerySupported = false;
2989 ret = true;
2990 break;
2991 default:
2992 ALOGV("%s: Reconfiguration query failed: %d", __FUNCTION__, callStatus);
2993 ret = true;
2994 }
2995 } else {
2996 ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, err.description().c_str());
2997 ret = true;
2998 }
2999 }
3000
3001 return ret;
3002}
3003
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01003004status_t Camera3Device::HalInterface::configureStreams(const camera_metadata_t *sessionParams,
Emilian Peev192ee832018-01-31 14:46:47 +00003005 camera3_stream_configuration *config, const std::vector<uint32_t>& bufferSizes) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003006 ATRACE_NAME("CameraHal::configureStreams");
3007 if (!valid()) return INVALID_OPERATION;
3008 status_t res = OK;
3009
Emilian Peev31abd0a2017-05-11 18:37:46 +01003010 // Convert stream config to HIDL
3011 std::set<int> activeStreams;
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003012 device::V3_2::StreamConfiguration requestedConfiguration3_2;
3013 device::V3_4::StreamConfiguration requestedConfiguration3_4;
3014 requestedConfiguration3_2.streams.resize(config->num_streams);
3015 requestedConfiguration3_4.streams.resize(config->num_streams);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003016 for (size_t i = 0; i < config->num_streams; i++) {
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003017 device::V3_2::Stream &dst3_2 = requestedConfiguration3_2.streams[i];
3018 device::V3_4::Stream &dst3_4 = requestedConfiguration3_4.streams[i];
Emilian Peev31abd0a2017-05-11 18:37:46 +01003019 camera3_stream_t *src = config->streams[i];
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003020
Emilian Peev31abd0a2017-05-11 18:37:46 +01003021 Camera3Stream* cam3stream = Camera3Stream::cast(src);
3022 cam3stream->setBufferFreedListener(this);
3023 int streamId = cam3stream->getId();
3024 StreamType streamType;
3025 switch (src->stream_type) {
3026 case CAMERA3_STREAM_OUTPUT:
3027 streamType = StreamType::OUTPUT;
3028 break;
3029 case CAMERA3_STREAM_INPUT:
3030 streamType = StreamType::INPUT;
3031 break;
3032 default:
3033 ALOGE("%s: Stream %d: Unsupported stream type %d",
3034 __FUNCTION__, streamId, config->streams[i]->stream_type);
3035 return BAD_VALUE;
3036 }
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003037 dst3_2.id = streamId;
3038 dst3_2.streamType = streamType;
3039 dst3_2.width = src->width;
3040 dst3_2.height = src->height;
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003041 dst3_2.usage = mapToConsumerUsage(cam3stream->getUsage());
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003042 dst3_2.rotation = mapToStreamRotation((camera3_stream_rotation_t) src->rotation);
Shuzhen Wang92653952019-05-07 15:11:43 -07003043 // For HidlSession version 3.5 or newer, the format and dataSpace sent
3044 // to HAL are original, not the overriden ones.
3045 if (mHidlSession_3_5 != nullptr) {
3046 dst3_2.format = mapToPixelFormat(cam3stream->isFormatOverridden() ?
3047 cam3stream->getOriginalFormat() : src->format);
3048 dst3_2.dataSpace = mapToHidlDataspace(cam3stream->isDataSpaceOverridden() ?
3049 cam3stream->getOriginalDataSpace() : src->data_space);
3050 } else {
3051 dst3_2.format = mapToPixelFormat(src->format);
3052 dst3_2.dataSpace = mapToHidlDataspace(src->data_space);
3053 }
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003054 dst3_4.v3_2 = dst3_2;
Emilian Peev192ee832018-01-31 14:46:47 +00003055 dst3_4.bufferSize = bufferSizes[i];
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003056 if (src->physical_camera_id != nullptr) {
3057 dst3_4.physicalCameraId = src->physical_camera_id;
3058 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003059
3060 activeStreams.insert(streamId);
3061 // Create Buffer ID map if necessary
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003062 mBufferRecords.tryCreateBufferCache(streamId);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003063 }
3064 // remove BufferIdMap for deleted streams
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003065 mBufferRecords.removeInactiveBufferCaches(activeStreams);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003066
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003067 StreamConfigurationMode operationMode;
Emilian Peev31abd0a2017-05-11 18:37:46 +01003068 res = mapToStreamConfigurationMode(
3069 (camera3_stream_configuration_mode_t) config->operation_mode,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003070 /*out*/ &operationMode);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003071 if (res != OK) {
3072 return res;
3073 }
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003074 requestedConfiguration3_2.operationMode = operationMode;
3075 requestedConfiguration3_4.operationMode = operationMode;
3076 requestedConfiguration3_4.sessionParams.setToExternal(
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01003077 reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams)),
3078 get_camera_metadata_size(sessionParams));
3079
Emilian Peev31abd0a2017-05-11 18:37:46 +01003080 // Invoke configureStreams
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003081 device::V3_3::HalStreamConfiguration finalConfiguration;
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003082 device::V3_4::HalStreamConfiguration finalConfiguration3_4;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003083 device::V3_6::HalStreamConfiguration finalConfiguration3_6;
Emilian Peev31abd0a2017-05-11 18:37:46 +01003084 common::V1_0::Status status;
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003085
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003086 auto configStream34Cb = [&status, &finalConfiguration3_4]
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003087 (common::V1_0::Status s, const device::V3_4::HalStreamConfiguration& halConfiguration) {
3088 finalConfiguration3_4 = halConfiguration;
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01003089 status = s;
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003090 };
3091
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003092 auto configStream36Cb = [&status, &finalConfiguration3_6]
3093 (common::V1_0::Status s, const device::V3_6::HalStreamConfiguration& halConfiguration) {
3094 finalConfiguration3_6 = halConfiguration;
3095 status = s;
3096 };
3097
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003098 auto postprocConfigStream34 = [&finalConfiguration, &finalConfiguration3_4]
3099 (hardware::Return<void>& err) -> status_t {
3100 if (!err.isOk()) {
3101 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3102 return DEAD_OBJECT;
3103 }
3104 finalConfiguration.streams.resize(finalConfiguration3_4.streams.size());
3105 for (size_t i = 0; i < finalConfiguration3_4.streams.size(); i++) {
3106 finalConfiguration.streams[i] = finalConfiguration3_4.streams[i].v3_3;
3107 }
3108 return OK;
3109 };
3110
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003111 auto postprocConfigStream36 = [&finalConfiguration, &finalConfiguration3_6]
3112 (hardware::Return<void>& err) -> status_t {
3113 if (!err.isOk()) {
3114 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3115 return DEAD_OBJECT;
3116 }
3117 finalConfiguration.streams.resize(finalConfiguration3_6.streams.size());
3118 for (size_t i = 0; i < finalConfiguration3_6.streams.size(); i++) {
3119 finalConfiguration.streams[i] = finalConfiguration3_6.streams[i].v3_4.v3_3;
3120 }
3121 return OK;
3122 };
3123
Shuzhen Wang92653952019-05-07 15:11:43 -07003124 // See which version of HAL we have
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003125 if (mHidlSession_3_6 != nullptr) {
3126 ALOGV("%s: v3.6 device found", __FUNCTION__);
3127 device::V3_5::StreamConfiguration requestedConfiguration3_5;
3128 requestedConfiguration3_5.v3_4 = requestedConfiguration3_4;
3129 requestedConfiguration3_5.streamConfigCounter = mNextStreamConfigCounter++;
3130 auto err = mHidlSession_3_6->configureStreams_3_6(
3131 requestedConfiguration3_5, configStream36Cb);
3132 res = postprocConfigStream36(err);
3133 if (res != OK) {
3134 return res;
3135 }
3136 } else if (mHidlSession_3_5 != nullptr) {
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003137 ALOGV("%s: v3.5 device found", __FUNCTION__);
3138 device::V3_5::StreamConfiguration requestedConfiguration3_5;
3139 requestedConfiguration3_5.v3_4 = requestedConfiguration3_4;
3140 requestedConfiguration3_5.streamConfigCounter = mNextStreamConfigCounter++;
3141 auto err = mHidlSession_3_5->configureStreams_3_5(
3142 requestedConfiguration3_5, configStream34Cb);
3143 res = postprocConfigStream34(err);
3144 if (res != OK) {
3145 return res;
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01003146 }
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003147 } else if (mHidlSession_3_4 != nullptr) {
3148 // We do; use v3.4 for the call
3149 ALOGV("%s: v3.4 device found", __FUNCTION__);
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003150 auto err = mHidlSession_3_4->configureStreams_3_4(
3151 requestedConfiguration3_4, configStream34Cb);
3152 res = postprocConfigStream34(err);
3153 if (res != OK) {
3154 return res;
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003155 }
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08003156 } else if (mHidlSession_3_3 != nullptr) {
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003157 // We do; use v3.3 for the call
3158 ALOGV("%s: v3.3 device found", __FUNCTION__);
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08003159 auto err = mHidlSession_3_3->configureStreams_3_3(requestedConfiguration3_2,
Emilian Peev31abd0a2017-05-11 18:37:46 +01003160 [&status, &finalConfiguration]
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003161 (common::V1_0::Status s, const device::V3_3::HalStreamConfiguration& halConfiguration) {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003162 finalConfiguration = halConfiguration;
3163 status = s;
3164 });
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003165 if (!err.isOk()) {
3166 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3167 return DEAD_OBJECT;
3168 }
3169 } else {
3170 // We don't; use v3.2 call and construct a v3.3 HalStreamConfiguration
3171 ALOGV("%s: v3.2 device found", __FUNCTION__);
3172 HalStreamConfiguration finalConfiguration_3_2;
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003173 auto err = mHidlSession->configureStreams(requestedConfiguration3_2,
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003174 [&status, &finalConfiguration_3_2]
3175 (common::V1_0::Status s, const HalStreamConfiguration& halConfiguration) {
3176 finalConfiguration_3_2 = halConfiguration;
3177 status = s;
3178 });
3179 if (!err.isOk()) {
3180 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3181 return DEAD_OBJECT;
3182 }
3183 finalConfiguration.streams.resize(finalConfiguration_3_2.streams.size());
3184 for (size_t i = 0; i < finalConfiguration_3_2.streams.size(); i++) {
3185 finalConfiguration.streams[i].v3_2 = finalConfiguration_3_2.streams[i];
3186 finalConfiguration.streams[i].overrideDataSpace =
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003187 requestedConfiguration3_2.streams[i].dataSpace;
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003188 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003189 }
3190
3191 if (status != common::V1_0::Status::OK ) {
3192 return CameraProviderManager::mapToStatusT(status);
3193 }
3194
3195 // And convert output stream configuration from HIDL
3196
3197 for (size_t i = 0; i < config->num_streams; i++) {
3198 camera3_stream_t *dst = config->streams[i];
3199 int streamId = Camera3Stream::cast(dst)->getId();
3200
3201 // Start scan at i, with the assumption that the stream order matches
3202 size_t realIdx = i;
3203 bool found = false;
Eino-Ville Talvala370875f2019-04-12 12:40:27 -07003204 size_t halStreamCount = finalConfiguration.streams.size();
3205 for (size_t idx = 0; idx < halStreamCount; idx++) {
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003206 if (finalConfiguration.streams[realIdx].v3_2.id == streamId) {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003207 found = true;
3208 break;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003209 }
Eino-Ville Talvala370875f2019-04-12 12:40:27 -07003210 realIdx = (realIdx >= halStreamCount - 1) ? 0 : realIdx + 1;
Emilian Peev31abd0a2017-05-11 18:37:46 +01003211 }
3212 if (!found) {
3213 ALOGE("%s: Stream %d not found in stream configuration response from HAL",
3214 __FUNCTION__, streamId);
3215 return INVALID_OPERATION;
3216 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003217 device::V3_3::HalStream &src = finalConfiguration.streams[realIdx];
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003218 device::V3_6::HalStream &src_36 = finalConfiguration3_6.streams[realIdx];
Yin-Chia Yeh77327052017-01-09 18:23:07 -08003219
Emilian Peev710c1422017-08-30 11:19:38 +01003220 Camera3Stream* dstStream = Camera3Stream::cast(dst);
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003221 int overrideFormat = mapToFrameworkFormat(src.v3_2.overrideFormat);
3222 android_dataspace overrideDataSpace = mapToFrameworkDataspace(src.overrideDataSpace);
3223
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003224 if (mHidlSession_3_6 != nullptr) {
3225 dstStream->setOfflineProcessingSupport(src_36.supportOffline);
3226 }
3227
Yin-Chia Yeh90667662019-07-01 15:45:00 -07003228 if (dstStream->getOriginalFormat() != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
Shuzhen Wang92653952019-05-07 15:11:43 -07003229 dstStream->setFormatOverride(false);
3230 dstStream->setDataSpaceOverride(false);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003231 if (dst->format != overrideFormat) {
3232 ALOGE("%s: Stream %d: Format override not allowed for format 0x%x", __FUNCTION__,
3233 streamId, dst->format);
Yin-Chia Yeh77327052017-01-09 18:23:07 -08003234 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003235 if (dst->data_space != overrideDataSpace) {
3236 ALOGE("%s: Stream %d: DataSpace override not allowed for format 0x%x", __FUNCTION__,
3237 streamId, dst->format);
3238 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003239 } else {
Shuzhen Wang92653952019-05-07 15:11:43 -07003240 bool needFormatOverride =
3241 requestedConfiguration3_2.streams[i].format != src.v3_2.overrideFormat;
3242 bool needDataspaceOverride =
3243 requestedConfiguration3_2.streams[i].dataSpace != src.overrideDataSpace;
Emilian Peev31abd0a2017-05-11 18:37:46 +01003244 // Override allowed with IMPLEMENTATION_DEFINED
Shuzhen Wang92653952019-05-07 15:11:43 -07003245 dstStream->setFormatOverride(needFormatOverride);
3246 dstStream->setDataSpaceOverride(needDataspaceOverride);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003247 dst->format = overrideFormat;
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003248 dst->data_space = overrideDataSpace;
Yin-Chia Yeh77327052017-01-09 18:23:07 -08003249 }
3250
Emilian Peev31abd0a2017-05-11 18:37:46 +01003251 if (dst->stream_type == CAMERA3_STREAM_INPUT) {
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003252 if (src.v3_2.producerUsage != 0) {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003253 ALOGE("%s: Stream %d: INPUT streams must have 0 for producer usage",
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003254 __FUNCTION__, streamId);
3255 return INVALID_OPERATION;
3256 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003257 dstStream->setUsage(
3258 mapConsumerToFrameworkUsage(src.v3_2.consumerUsage));
Emilian Peev31abd0a2017-05-11 18:37:46 +01003259 } else {
3260 // OUTPUT
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003261 if (src.v3_2.consumerUsage != 0) {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003262 ALOGE("%s: Stream %d: OUTPUT streams must have 0 for consumer usage",
3263 __FUNCTION__, streamId);
3264 return INVALID_OPERATION;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003265 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003266 dstStream->setUsage(
3267 mapProducerToFrameworkUsage(src.v3_2.producerUsage));
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003268 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003269 dst->max_buffers = src.v3_2.maxBuffers;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003270 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003271
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003272 return res;
3273}
3274
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003275status_t Camera3Device::HalInterface::wrapAsHidlRequest(camera3_capture_request_t* request,
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003276 /*out*/device::V3_2::CaptureRequest* captureRequest,
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003277 /*out*/std::vector<native_handle_t*>* handlesCreated,
3278 /*out*/std::vector<std::pair<int32_t, int32_t>>* inflightBuffers) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003279 ATRACE_CALL();
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003280 if (captureRequest == nullptr || handlesCreated == nullptr || inflightBuffers == nullptr) {
3281 ALOGE("%s: captureRequest (%p), handlesCreated (%p), and inflightBuffers(%p) "
3282 "must not be null", __FUNCTION__, captureRequest, handlesCreated, inflightBuffers);
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003283 return BAD_VALUE;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003284 }
3285
3286 captureRequest->frameNumber = request->frame_number;
Yifan Hongf79b5542017-04-11 14:44:25 -07003287
3288 captureRequest->fmqSettingsSize = 0;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003289
3290 {
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003291 if (request->input_buffer != nullptr) {
3292 int32_t streamId = Camera3Stream::cast(request->input_buffer->stream)->getId();
3293 buffer_handle_t buf = *(request->input_buffer->buffer);
3294 auto pair = getBufferId(buf, streamId);
3295 bool isNewBuffer = pair.first;
3296 uint64_t bufferId = pair.second;
3297 captureRequest->inputBuffer.streamId = streamId;
3298 captureRequest->inputBuffer.bufferId = bufferId;
3299 captureRequest->inputBuffer.buffer = (isNewBuffer) ? buf : nullptr;
3300 captureRequest->inputBuffer.status = BufferStatus::OK;
3301 native_handle_t *acquireFence = nullptr;
3302 if (request->input_buffer->acquire_fence != -1) {
3303 acquireFence = native_handle_create(1,0);
3304 acquireFence->data[0] = request->input_buffer->acquire_fence;
3305 handlesCreated->push_back(acquireFence);
3306 }
3307 captureRequest->inputBuffer.acquireFence = acquireFence;
3308 captureRequest->inputBuffer.releaseFence = nullptr;
3309
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003310 mBufferRecords.pushInflightBuffer(captureRequest->frameNumber, streamId,
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003311 request->input_buffer->buffer);
3312 inflightBuffers->push_back(std::make_pair(captureRequest->frameNumber, streamId));
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003313 } else {
3314 captureRequest->inputBuffer.streamId = -1;
3315 captureRequest->inputBuffer.bufferId = BUFFER_ID_NO_BUFFER;
3316 }
3317
3318 captureRequest->outputBuffers.resize(request->num_output_buffers);
3319 for (size_t i = 0; i < request->num_output_buffers; i++) {
3320 const camera3_stream_buffer_t *src = request->output_buffers + i;
3321 StreamBuffer &dst = captureRequest->outputBuffers[i];
3322 int32_t streamId = Camera3Stream::cast(src->stream)->getId();
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003323 if (src->buffer != nullptr) {
3324 buffer_handle_t buf = *(src->buffer);
3325 auto pair = getBufferId(buf, streamId);
3326 bool isNewBuffer = pair.first;
3327 dst.bufferId = pair.second;
3328 dst.buffer = isNewBuffer ? buf : nullptr;
3329 native_handle_t *acquireFence = nullptr;
3330 if (src->acquire_fence != -1) {
3331 acquireFence = native_handle_create(1,0);
3332 acquireFence->data[0] = src->acquire_fence;
3333 handlesCreated->push_back(acquireFence);
3334 }
3335 dst.acquireFence = acquireFence;
3336 } else if (mUseHalBufManager) {
3337 // HAL buffer management path
3338 dst.bufferId = BUFFER_ID_NO_BUFFER;
3339 dst.buffer = nullptr;
3340 dst.acquireFence = nullptr;
3341 } else {
3342 ALOGE("%s: cannot send a null buffer in capture request!", __FUNCTION__);
3343 return BAD_VALUE;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003344 }
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003345 dst.streamId = streamId;
3346 dst.status = BufferStatus::OK;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003347 dst.releaseFence = nullptr;
3348
Yin-Chia Yeh5f840f82019-03-05 11:59:04 -08003349 // Output buffers are empty when using HAL buffer manager
3350 if (!mUseHalBufManager) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003351 mBufferRecords.pushInflightBuffer(
3352 captureRequest->frameNumber, streamId, src->buffer);
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003353 inflightBuffers->push_back(std::make_pair(captureRequest->frameNumber, streamId));
Yin-Chia Yeh5f840f82019-03-05 11:59:04 -08003354 }
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003355 }
3356 }
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003357 return OK;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003358}
3359
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003360void Camera3Device::HalInterface::cleanupNativeHandles(
3361 std::vector<native_handle_t*> *handles, bool closeFd) {
3362 if (handles == nullptr) {
3363 return;
3364 }
3365 if (closeFd) {
3366 for (auto& handle : *handles) {
3367 native_handle_close(handle);
3368 }
3369 }
3370 for (auto& handle : *handles) {
3371 native_handle_delete(handle);
3372 }
3373 handles->clear();
3374 return;
3375}
3376
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003377status_t Camera3Device::HalInterface::processBatchCaptureRequests(
3378 std::vector<camera3_capture_request_t*>& requests,/*out*/uint32_t* numRequestProcessed) {
3379 ATRACE_NAME("CameraHal::processBatchCaptureRequests");
3380 if (!valid()) return INVALID_OPERATION;
3381
Emilian Peevaebbe412018-01-15 13:53:24 +00003382 sp<device::V3_4::ICameraDeviceSession> hidlSession_3_4;
3383 auto castResult_3_4 = device::V3_4::ICameraDeviceSession::castFrom(mHidlSession);
3384 if (castResult_3_4.isOk()) {
3385 hidlSession_3_4 = castResult_3_4;
3386 }
3387
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003388 hardware::hidl_vec<device::V3_2::CaptureRequest> captureRequests;
Emilian Peevaebbe412018-01-15 13:53:24 +00003389 hardware::hidl_vec<device::V3_4::CaptureRequest> captureRequests_3_4;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003390 size_t batchSize = requests.size();
Emilian Peevaebbe412018-01-15 13:53:24 +00003391 if (hidlSession_3_4 != nullptr) {
3392 captureRequests_3_4.resize(batchSize);
3393 } else {
3394 captureRequests.resize(batchSize);
3395 }
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003396 std::vector<native_handle_t*> handlesCreated;
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003397 std::vector<std::pair<int32_t, int32_t>> inflightBuffers;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003398
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003399 status_t res = OK;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003400 for (size_t i = 0; i < batchSize; i++) {
Emilian Peevaebbe412018-01-15 13:53:24 +00003401 if (hidlSession_3_4 != nullptr) {
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003402 res = wrapAsHidlRequest(requests[i], /*out*/&captureRequests_3_4[i].v3_2,
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003403 /*out*/&handlesCreated, /*out*/&inflightBuffers);
Emilian Peevaebbe412018-01-15 13:53:24 +00003404 } else {
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003405 res = wrapAsHidlRequest(requests[i], /*out*/&captureRequests[i],
3406 /*out*/&handlesCreated, /*out*/&inflightBuffers);
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003407 }
3408 if (res != OK) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003409 mBufferRecords.popInflightBuffers(inflightBuffers);
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003410 cleanupNativeHandles(&handlesCreated);
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003411 return res;
Emilian Peevaebbe412018-01-15 13:53:24 +00003412 }
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003413 }
3414
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003415 std::vector<device::V3_2::BufferCache> cachesToRemove;
3416 {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003417 std::lock_guard<std::mutex> lock(mFreedBuffersLock);
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003418 for (auto& pair : mFreedBuffers) {
3419 // The stream might have been removed since onBufferFreed
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003420 if (mBufferRecords.isStreamCached(pair.first)) {
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003421 cachesToRemove.push_back({pair.first, pair.second});
3422 }
3423 }
3424 mFreedBuffers.clear();
3425 }
3426
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003427 common::V1_0::Status status = common::V1_0::Status::INTERNAL_ERROR;
3428 *numRequestProcessed = 0;
Yifan Hongf79b5542017-04-11 14:44:25 -07003429
3430 // Write metadata to FMQ.
3431 for (size_t i = 0; i < batchSize; i++) {
3432 camera3_capture_request_t* request = requests[i];
Emilian Peevaebbe412018-01-15 13:53:24 +00003433 device::V3_2::CaptureRequest* captureRequest;
3434 if (hidlSession_3_4 != nullptr) {
3435 captureRequest = &captureRequests_3_4[i].v3_2;
3436 } else {
3437 captureRequest = &captureRequests[i];
3438 }
Yifan Hongf79b5542017-04-11 14:44:25 -07003439
3440 if (request->settings != nullptr) {
3441 size_t settingsSize = get_camera_metadata_size(request->settings);
3442 if (mRequestMetadataQueue != nullptr && mRequestMetadataQueue->write(
3443 reinterpret_cast<const uint8_t*>(request->settings), settingsSize)) {
3444 captureRequest->settings.resize(0);
3445 captureRequest->fmqSettingsSize = settingsSize;
3446 } else {
3447 if (mRequestMetadataQueue != nullptr) {
3448 ALOGW("%s: couldn't utilize fmq, fallback to hwbinder", __FUNCTION__);
3449 }
3450 captureRequest->settings.setToExternal(
3451 reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(request->settings)),
3452 get_camera_metadata_size(request->settings));
3453 captureRequest->fmqSettingsSize = 0u;
3454 }
3455 } else {
3456 // A null request settings maps to a size-0 CameraMetadata
3457 captureRequest->settings.resize(0);
3458 captureRequest->fmqSettingsSize = 0u;
3459 }
Emilian Peevaebbe412018-01-15 13:53:24 +00003460
3461 if (hidlSession_3_4 != nullptr) {
3462 captureRequests_3_4[i].physicalCameraSettings.resize(request->num_physcam_settings);
3463 for (size_t j = 0; j < request->num_physcam_settings; j++) {
Emilian Peev00420d22018-02-05 21:33:13 +00003464 if (request->physcam_settings != nullptr) {
3465 size_t settingsSize = get_camera_metadata_size(request->physcam_settings[j]);
3466 if (mRequestMetadataQueue != nullptr && mRequestMetadataQueue->write(
3467 reinterpret_cast<const uint8_t*>(request->physcam_settings[j]),
3468 settingsSize)) {
3469 captureRequests_3_4[i].physicalCameraSettings[j].settings.resize(0);
3470 captureRequests_3_4[i].physicalCameraSettings[j].fmqSettingsSize =
3471 settingsSize;
3472 } else {
3473 if (mRequestMetadataQueue != nullptr) {
3474 ALOGW("%s: couldn't utilize fmq, fallback to hwbinder", __FUNCTION__);
3475 }
3476 captureRequests_3_4[i].physicalCameraSettings[j].settings.setToExternal(
3477 reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(
3478 request->physcam_settings[j])),
3479 get_camera_metadata_size(request->physcam_settings[j]));
3480 captureRequests_3_4[i].physicalCameraSettings[j].fmqSettingsSize = 0u;
Emilian Peevaebbe412018-01-15 13:53:24 +00003481 }
Emilian Peev00420d22018-02-05 21:33:13 +00003482 } else {
Emilian Peevaebbe412018-01-15 13:53:24 +00003483 captureRequests_3_4[i].physicalCameraSettings[j].fmqSettingsSize = 0u;
Emilian Peev00420d22018-02-05 21:33:13 +00003484 captureRequests_3_4[i].physicalCameraSettings[j].settings.resize(0);
Emilian Peevaebbe412018-01-15 13:53:24 +00003485 }
3486 captureRequests_3_4[i].physicalCameraSettings[j].physicalCameraId =
3487 request->physcam_id[j];
3488 }
3489 }
Yifan Hongf79b5542017-04-11 14:44:25 -07003490 }
Emilian Peevaebbe412018-01-15 13:53:24 +00003491
3492 hardware::details::return_status err;
Jayant Chowdharyc8d581e2018-07-16 14:46:23 -07003493 auto resultCallback =
3494 [&status, &numRequestProcessed] (auto s, uint32_t n) {
3495 status = s;
3496 *numRequestProcessed = n;
3497 };
Emilian Peevaebbe412018-01-15 13:53:24 +00003498 if (hidlSession_3_4 != nullptr) {
3499 err = hidlSession_3_4->processCaptureRequest_3_4(captureRequests_3_4, cachesToRemove,
Jayant Chowdharyc8d581e2018-07-16 14:46:23 -07003500 resultCallback);
Emilian Peevaebbe412018-01-15 13:53:24 +00003501 } else {
3502 err = mHidlSession->processCaptureRequest(captureRequests, cachesToRemove,
Jayant Chowdharyc8d581e2018-07-16 14:46:23 -07003503 resultCallback);
Emilian Peevaebbe412018-01-15 13:53:24 +00003504 }
Eino-Ville Talvalac5cbb872017-04-27 12:48:33 -07003505 if (!err.isOk()) {
3506 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003507 status = common::V1_0::Status::CAMERA_DISCONNECTED;
Eino-Ville Talvalac5cbb872017-04-27 12:48:33 -07003508 }
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003509
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003510 if (status == common::V1_0::Status::OK && *numRequestProcessed != batchSize) {
3511 ALOGE("%s: processCaptureRequest returns OK but processed %d/%zu requests",
3512 __FUNCTION__, *numRequestProcessed, batchSize);
3513 status = common::V1_0::Status::INTERNAL_ERROR;
3514 }
3515
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003516 res = CameraProviderManager::mapToStatusT(status);
3517 if (res == OK) {
3518 if (mHidlSession->isRemote()) {
3519 // Only close acquire fence FDs when the HIDL transaction succeeds (so the FDs have been
3520 // sent to camera HAL processes)
3521 cleanupNativeHandles(&handlesCreated, /*closeFd*/true);
3522 } else {
3523 // In passthrough mode the FDs are now owned by HAL
3524 cleanupNativeHandles(&handlesCreated);
3525 }
3526 } else {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003527 mBufferRecords.popInflightBuffers(inflightBuffers);
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003528 cleanupNativeHandles(&handlesCreated);
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003529 }
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003530 return res;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003531}
3532
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003533status_t Camera3Device::HalInterface::flush() {
3534 ATRACE_NAME("CameraHal::flush");
3535 if (!valid()) return INVALID_OPERATION;
3536 status_t res = OK;
3537
Emilian Peev31abd0a2017-05-11 18:37:46 +01003538 auto err = mHidlSession->flush();
3539 if (!err.isOk()) {
3540 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3541 res = DEAD_OBJECT;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003542 } else {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003543 res = CameraProviderManager::mapToStatusT(err);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003544 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003545
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003546 return res;
3547}
3548
Emilian Peev31abd0a2017-05-11 18:37:46 +01003549status_t Camera3Device::HalInterface::dump(int /*fd*/) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003550 ATRACE_NAME("CameraHal::dump");
3551 if (!valid()) return INVALID_OPERATION;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003552
Emilian Peev31abd0a2017-05-11 18:37:46 +01003553 // Handled by CameraProviderManager::dump
3554
3555 return OK;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003556}
3557
3558status_t Camera3Device::HalInterface::close() {
3559 ATRACE_NAME("CameraHal::close()");
3560 if (!valid()) return INVALID_OPERATION;
3561 status_t res = OK;
3562
Emilian Peev31abd0a2017-05-11 18:37:46 +01003563 auto err = mHidlSession->close();
3564 // Interface will be dead shortly anyway, so don't log errors
3565 if (!err.isOk()) {
3566 res = DEAD_OBJECT;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003567 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003568
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003569 return res;
3570}
3571
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003572void Camera3Device::HalInterface::signalPipelineDrain(const std::vector<int>& streamIds) {
3573 ATRACE_NAME("CameraHal::signalPipelineDrain");
3574 if (!valid() || mHidlSession_3_5 == nullptr) {
3575 ALOGE("%s called on invalid camera!", __FUNCTION__);
3576 return;
3577 }
3578
Yin-Chia Yehc300a072019-02-13 14:56:57 -08003579 auto err = mHidlSession_3_5->signalStreamFlush(streamIds, mNextStreamConfigCounter - 1);
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003580 if (!err.isOk()) {
3581 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3582 return;
3583 }
3584}
3585
Yin-Chia Yehb978c382019-10-30 00:22:37 -07003586status_t Camera3Device::HalInterface::switchToOffline(
3587 const std::vector<int32_t>& streamsToKeep,
3588 /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003589 /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
3590 /*out*/camera3::BufferRecords* bufferRecords) {
Yin-Chia Yehb978c382019-10-30 00:22:37 -07003591 ATRACE_NAME("CameraHal::switchToOffline");
3592 if (!valid() || mHidlSession_3_6 == nullptr) {
3593 ALOGE("%s called on invalid camera!", __FUNCTION__);
3594 return INVALID_OPERATION;
3595 }
3596
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003597 if (offlineSessionInfo == nullptr || offlineSession == nullptr || bufferRecords == nullptr) {
3598 ALOGE("%s: output arguments must not be null!", __FUNCTION__);
Yin-Chia Yehb978c382019-10-30 00:22:37 -07003599 return INVALID_OPERATION;
3600 }
3601
3602 common::V1_0::Status status = common::V1_0::Status::INTERNAL_ERROR;
Yin-Chia Yehb978c382019-10-30 00:22:37 -07003603 auto resultCallback =
3604 [&status, &offlineSessionInfo, &offlineSession] (auto s, auto info, auto session) {
3605 status = s;
3606 *offlineSessionInfo = info;
3607 *offlineSession = session;
3608 };
3609 auto err = mHidlSession_3_6->switchToOffline(streamsToKeep, resultCallback);
3610
3611 if (!err.isOk()) {
3612 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3613 return DEAD_OBJECT;
3614 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003615
3616 status_t ret = CameraProviderManager::mapToStatusT(status);
3617 if (ret != OK) {
3618 return ret;
3619 }
3620
3621 // TODO: assert no ongoing requestBuffer/returnBuffer call here
3622 // TODO: update RequestBufferStateMachine to block requestBuffer/returnBuffer once HAL
3623 // returns from switchToOffline.
3624
3625
3626 // Validate buffer caches
3627 std::vector<int32_t> streams;
3628 streams.reserve(offlineSessionInfo->offlineStreams.size());
3629 for (auto offlineStream : offlineSessionInfo->offlineStreams) {
3630 int32_t id = offlineStream.id;
3631 streams.push_back(id);
3632 // Verify buffer caches
3633 std::vector<uint64_t> bufIds(offlineStream.circulatingBufferIds.begin(),
3634 offlineStream.circulatingBufferIds.end());
3635 if (!verifyBufferIds(id, bufIds)) {
3636 ALOGE("%s: stream ID %d buffer cache records mismatch!", __FUNCTION__, id);
3637 return UNKNOWN_ERROR;
3638 }
3639 }
3640
3641 // Move buffer records
3642 bufferRecords->takeBufferCaches(mBufferRecords, streams);
3643 bufferRecords->takeInflightBufferMap(mBufferRecords);
3644 bufferRecords->takeRequestedBufferMap(mBufferRecords);
3645 return ret;
Yin-Chia Yehb978c382019-10-30 00:22:37 -07003646}
3647
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07003648void Camera3Device::HalInterface::getInflightBufferKeys(
3649 std::vector<std::pair<int32_t, int32_t>>* out) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003650 mBufferRecords.getInflightBufferKeys(out);
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07003651 return;
3652}
3653
Yin-Chia Yeh84be5782019-03-01 11:47:02 -08003654void Camera3Device::HalInterface::getInflightRequestBufferKeys(
3655 std::vector<uint64_t>* out) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003656 mBufferRecords.getInflightRequestBufferKeys(out);
Yin-Chia Yeh84be5782019-03-01 11:47:02 -08003657 return;
3658}
3659
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003660bool Camera3Device::HalInterface::verifyBufferIds(
3661 int32_t streamId, std::vector<uint64_t>& bufIds) {
3662 return mBufferRecords.verifyBufferIds(streamId, bufIds);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003663}
3664
3665status_t Camera3Device::HalInterface::popInflightBuffer(
Yin-Chia Yehf4650602017-01-10 13:13:39 -08003666 int32_t frameNumber, int32_t streamId,
3667 /*out*/ buffer_handle_t **buffer) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003668 return mBufferRecords.popInflightBuffer(frameNumber, streamId, buffer);
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003669}
3670
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07003671status_t Camera3Device::HalInterface::pushInflightRequestBuffer(
Yin-Chia Yeh84be5782019-03-01 11:47:02 -08003672 uint64_t bufferId, buffer_handle_t* buf, int32_t streamId) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003673 return mBufferRecords.pushInflightRequestBuffer(bufferId, buf, streamId);
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07003674}
3675
3676// Find and pop a buffer_handle_t based on bufferId
3677status_t Camera3Device::HalInterface::popInflightRequestBuffer(
Yin-Chia Yeh84be5782019-03-01 11:47:02 -08003678 uint64_t bufferId,
3679 /*out*/ buffer_handle_t** buffer,
3680 /*optional out*/ int32_t* streamId) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003681 return mBufferRecords.popInflightRequestBuffer(bufferId, buffer, streamId);
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07003682}
3683
Yin-Chia Yeh77327052017-01-09 18:23:07 -08003684std::pair<bool, uint64_t> Camera3Device::HalInterface::getBufferId(
3685 const buffer_handle_t& buf, int streamId) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003686 return mBufferRecords.getBufferId(buf, streamId);
Yin-Chia Yeh77327052017-01-09 18:23:07 -08003687}
3688
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003689void Camera3Device::HalInterface::onBufferFreed(
3690 int streamId, const native_handle_t* handle) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003691 uint32_t bufferId = mBufferRecords.removeOneBufferCache(streamId, handle);
3692 std::lock_guard<std::mutex> lock(mFreedBuffersLock);
3693 if (bufferId != BUFFER_ID_NO_BUFFER) {
3694 mFreedBuffers.push_back(std::make_pair(streamId, bufferId));
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003695 }
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003696}
3697
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07003698void Camera3Device::HalInterface::onStreamReConfigured(int streamId) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003699 std::vector<uint64_t> bufIds = mBufferRecords.clearBufferCaches(streamId);
3700 std::lock_guard<std::mutex> lock(mFreedBuffersLock);
3701 for (auto bufferId : bufIds) {
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07003702 mFreedBuffers.push_back(std::make_pair(streamId, bufferId));
3703 }
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07003704}
3705
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003706/**
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003707 * RequestThread inner class methods
3708 */
3709
3710Camera3Device::RequestThread::RequestThread(wp<Camera3Device> parent,
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07003711 sp<StatusTracker> statusTracker,
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07003712 sp<HalInterface> interface, const Vector<int32_t>& sessionParamKeys,
3713 bool useHalBufManager) :
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07003714 Thread(/*canCallJava*/false),
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003715 mParent(parent),
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07003716 mStatusTracker(statusTracker),
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003717 mInterface(interface),
Eino-Ville Talvala77c1a352016-06-13 12:32:43 -07003718 mListener(nullptr),
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07003719 mId(getId(parent)),
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003720 mReconfigured(false),
3721 mDoPause(false),
3722 mPaused(true),
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003723 mNotifyPipelineDrain(false),
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003724 mFrameNumber(0),
Jianing Weicb0652e2014-03-12 18:29:36 -07003725 mLatestRequestId(NAME_NOT_FOUND),
Yin-Chia Yehc00a25c2014-08-21 14:27:44 -07003726 mCurrentAfTriggerId(0),
3727 mCurrentPreCaptureTriggerId(0),
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003728 mRepeatingLastFrameNumber(
3729 hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES),
Shuzhen Wang686f6442017-06-20 16:16:04 -07003730 mPrepareVideoStream(false),
Emilian Peeva14b4dd2018-05-15 11:00:31 +01003731 mConstrainedMode(false),
Emilian Peevac3ce6c2017-12-12 15:27:02 +00003732 mRequestLatency(kRequestLatencyBinSize),
3733 mSessionParamKeys(sessionParamKeys),
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07003734 mLatestSessionParams(sessionParamKeys.size()),
3735 mUseHalBufManager(useHalBufManager) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07003736 mStatusId = statusTracker->addComponent();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003737}
3738
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003739Camera3Device::RequestThread::~RequestThread() {}
3740
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07003741void Camera3Device::RequestThread::setNotificationListener(
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07003742 wp<NotificationListener> listener) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003743 ATRACE_CALL();
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003744 Mutex::Autolock l(mRequestLock);
3745 mListener = listener;
3746}
3747
Emilian Peevac3ce6c2017-12-12 15:27:02 +00003748void Camera3Device::RequestThread::configurationComplete(bool isConstrainedHighSpeed,
3749 const CameraMetadata& sessionParams) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003750 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003751 Mutex::Autolock l(mRequestLock);
3752 mReconfigured = true;
Emilian Peevac3ce6c2017-12-12 15:27:02 +00003753 mLatestSessionParams = sessionParams;
Chien-Yu Chenc66969b2016-05-19 16:37:51 -07003754 // Prepare video stream for high speed recording.
3755 mPrepareVideoStream = isConstrainedHighSpeed;
Emilian Peeva14b4dd2018-05-15 11:00:31 +01003756 mConstrainedMode = isConstrainedHighSpeed;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003757}
3758
Jianing Wei90e59c92014-03-12 18:29:36 -07003759status_t Camera3Device::RequestThread::queueRequestList(
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003760 List<sp<CaptureRequest> > &requests,
3761 /*out*/
3762 int64_t *lastFrameNumber) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003763 ATRACE_CALL();
Jianing Wei90e59c92014-03-12 18:29:36 -07003764 Mutex::Autolock l(mRequestLock);
3765 for (List<sp<CaptureRequest> >::iterator it = requests.begin(); it != requests.end();
3766 ++it) {
3767 mRequestQueue.push_back(*it);
3768 }
3769
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003770 if (lastFrameNumber != NULL) {
3771 *lastFrameNumber = mFrameNumber + mRequestQueue.size() - 1;
3772 ALOGV("%s: requestId %d, mFrameNumber %" PRId32 ", lastFrameNumber %" PRId64 ".",
3773 __FUNCTION__, (*(requests.begin()))->mResultExtras.requestId, mFrameNumber,
3774 *lastFrameNumber);
3775 }
Jianing Weicb0652e2014-03-12 18:29:36 -07003776
Jianing Wei90e59c92014-03-12 18:29:36 -07003777 unpauseForNewRequests();
3778
3779 return OK;
3780}
3781
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003782
3783status_t Camera3Device::RequestThread::queueTrigger(
3784 RequestTrigger trigger[],
3785 size_t count) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003786 ATRACE_CALL();
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003787 Mutex::Autolock l(mTriggerMutex);
3788 status_t ret;
3789
3790 for (size_t i = 0; i < count; ++i) {
3791 ret = queueTriggerLocked(trigger[i]);
3792
3793 if (ret != OK) {
3794 return ret;
3795 }
3796 }
3797
3798 return OK;
3799}
3800
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003801const String8& Camera3Device::RequestThread::getId(const wp<Camera3Device> &device) {
3802 static String8 deadId("<DeadDevice>");
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07003803 sp<Camera3Device> d = device.promote();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003804 if (d != nullptr) return d->mId;
3805 return deadId;
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07003806}
3807
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003808status_t Camera3Device::RequestThread::queueTriggerLocked(
3809 RequestTrigger trigger) {
3810
3811 uint32_t tag = trigger.metadataTag;
3812 ssize_t index = mTriggerMap.indexOfKey(tag);
3813
3814 switch (trigger.getTagType()) {
3815 case TYPE_BYTE:
3816 // fall-through
3817 case TYPE_INT32:
3818 break;
3819 default:
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07003820 ALOGE("%s: Type not supported: 0x%x", __FUNCTION__,
3821 trigger.getTagType());
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003822 return INVALID_OPERATION;
3823 }
3824
3825 /**
3826 * Collect only the latest trigger, since we only have 1 field
3827 * in the request settings per trigger tag, and can't send more than 1
3828 * trigger per request.
3829 */
3830 if (index != NAME_NOT_FOUND) {
3831 mTriggerMap.editValueAt(index) = trigger;
3832 } else {
3833 mTriggerMap.add(tag, trigger);
3834 }
3835
3836 return OK;
3837}
3838
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003839status_t Camera3Device::RequestThread::setRepeatingRequests(
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003840 const RequestList &requests,
3841 /*out*/
3842 int64_t *lastFrameNumber) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003843 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003844 Mutex::Autolock l(mRequestLock);
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003845 if (lastFrameNumber != NULL) {
3846 *lastFrameNumber = mRepeatingLastFrameNumber;
3847 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003848 mRepeatingRequests.clear();
3849 mRepeatingRequests.insert(mRepeatingRequests.begin(),
3850 requests.begin(), requests.end());
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07003851
3852 unpauseForNewRequests();
3853
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003854 mRepeatingLastFrameNumber = hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003855 return OK;
3856}
3857
Chih-Hung Hsieh8b0b9712016-08-09 14:25:53 -07003858bool Camera3Device::RequestThread::isRepeatingRequestLocked(const sp<CaptureRequest>& requestIn) {
Yin-Chia Yeh8684b7f2014-06-13 14:53:05 -07003859 if (mRepeatingRequests.empty()) {
3860 return false;
3861 }
3862 int32_t requestId = requestIn->mResultExtras.requestId;
3863 const RequestList &repeatRequests = mRepeatingRequests;
3864 // All repeating requests are guaranteed to have same id so only check first quest
3865 const sp<CaptureRequest> firstRequest = *repeatRequests.begin();
3866 return (firstRequest->mResultExtras.requestId == requestId);
3867}
3868
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003869status_t Camera3Device::RequestThread::clearRepeatingRequests(/*out*/int64_t *lastFrameNumber) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003870 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003871 Mutex::Autolock l(mRequestLock);
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07003872 return clearRepeatingRequestsLocked(lastFrameNumber);
3873
3874}
3875
3876status_t Camera3Device::RequestThread::clearRepeatingRequestsLocked(/*out*/int64_t *lastFrameNumber) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003877 mRepeatingRequests.clear();
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003878 if (lastFrameNumber != NULL) {
3879 *lastFrameNumber = mRepeatingLastFrameNumber;
3880 }
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003881 mRepeatingLastFrameNumber = hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003882 return OK;
3883}
3884
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003885status_t Camera3Device::RequestThread::clear(
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003886 /*out*/int64_t *lastFrameNumber) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003887 ATRACE_CALL();
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07003888 Mutex::Autolock l(mRequestLock);
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003889 ALOGV("RequestThread::%s:", __FUNCTION__);
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003890
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07003891 mRepeatingRequests.clear();
Yin-Chia Yeh8684b7f2014-06-13 14:53:05 -07003892
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003893 // Send errors for all requests pending in the request queue, including
3894 // pending repeating requests
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07003895 sp<NotificationListener> listener = mListener.promote();
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003896 if (listener != NULL) {
3897 for (RequestList::iterator it = mRequestQueue.begin();
3898 it != mRequestQueue.end(); ++it) {
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07003899 // Abort the input buffers for reprocess requests.
3900 if ((*it)->mInputStream != NULL) {
3901 camera3_stream_buffer_t inputBuffer;
Eino-Ville Talvalaba435252017-06-21 16:07:25 -07003902 status_t res = (*it)->mInputStream->getInputBuffer(&inputBuffer,
3903 /*respectHalLimit*/ false);
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07003904 if (res != OK) {
3905 ALOGW("%s: %d: couldn't get input buffer while clearing the request "
3906 "list: %s (%d)", __FUNCTION__, __LINE__, strerror(-res), res);
3907 } else {
Shuzhen Wang0cf01cb2019-09-05 13:33:06 -07003908 inputBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07003909 res = (*it)->mInputStream->returnInputBuffer(inputBuffer);
3910 if (res != OK) {
3911 ALOGE("%s: %d: couldn't return input buffer while clearing the request "
3912 "list: %s (%d)", __FUNCTION__, __LINE__, strerror(-res), res);
3913 }
3914 }
3915 }
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003916 // Set the frame number this request would have had, if it
3917 // had been submitted; this frame number will not be reused.
3918 // The requestId and burstId fields were set when the request was
3919 // submitted originally (in convertMetadataListToRequestListLocked)
3920 (*it)->mResultExtras.frameNumber = mFrameNumber++;
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003921 listener->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003922 (*it)->mResultExtras);
Yin-Chia Yeh8684b7f2014-06-13 14:53:05 -07003923 }
3924 }
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07003925 mRequestQueue.clear();
Jinguang Dongb26e7a02016-11-14 16:04:02 +08003926
3927 Mutex::Autolock al(mTriggerMutex);
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07003928 mTriggerMap.clear();
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003929 if (lastFrameNumber != NULL) {
3930 *lastFrameNumber = mRepeatingLastFrameNumber;
3931 }
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003932 mRepeatingLastFrameNumber = hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES;
Emilian Peev8dae54c2019-12-02 15:17:17 -08003933 mRequestSignal.signal();
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07003934 return OK;
3935}
3936
Chien-Yu Chen85a64552015-08-28 15:46:12 -07003937status_t Camera3Device::RequestThread::flush() {
3938 ATRACE_CALL();
3939 Mutex::Autolock l(mFlushLock);
3940
Emilian Peev08dd2452017-04-06 16:55:14 +01003941 return mInterface->flush();
Chien-Yu Chen85a64552015-08-28 15:46:12 -07003942}
3943
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003944void Camera3Device::RequestThread::setPaused(bool paused) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003945 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003946 Mutex::Autolock l(mPauseLock);
3947 mDoPause = paused;
3948 mDoPauseSignal.signal();
3949}
3950
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003951status_t Camera3Device::RequestThread::waitUntilRequestProcessed(
3952 int32_t requestId, nsecs_t timeout) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003953 ATRACE_CALL();
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003954 Mutex::Autolock l(mLatestRequestMutex);
3955 status_t res;
3956 while (mLatestRequestId != requestId) {
3957 nsecs_t startTime = systemTime();
3958
3959 res = mLatestRequestSignal.waitRelative(mLatestRequestMutex, timeout);
3960 if (res != OK) return res;
3961
3962 timeout -= (systemTime() - startTime);
3963 }
3964
3965 return OK;
3966}
3967
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07003968void Camera3Device::RequestThread::requestExit() {
3969 // Call parent to set up shutdown
3970 Thread::requestExit();
3971 // The exit from any possible waits
3972 mDoPauseSignal.signal();
3973 mRequestSignal.signal();
Shuzhen Wang686f6442017-06-20 16:16:04 -07003974
3975 mRequestLatency.log("ProcessCaptureRequest latency histogram");
3976 mRequestLatency.reset();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07003977}
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003978
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07003979void Camera3Device::RequestThread::checkAndStopRepeatingRequest() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003980 ATRACE_CALL();
Yin-Chia Yeh473fad92016-05-23 15:54:41 -07003981 bool surfaceAbandoned = false;
3982 int64_t lastFrameNumber = 0;
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07003983 sp<NotificationListener> listener;
Yin-Chia Yeh473fad92016-05-23 15:54:41 -07003984 {
3985 Mutex::Autolock l(mRequestLock);
3986 // Check all streams needed by repeating requests are still valid. Otherwise, stop
3987 // repeating requests.
3988 for (const auto& request : mRepeatingRequests) {
3989 for (const auto& s : request->mOutputStreams) {
3990 if (s->isAbandoned()) {
3991 surfaceAbandoned = true;
3992 clearRepeatingRequestsLocked(&lastFrameNumber);
3993 break;
3994 }
3995 }
3996 if (surfaceAbandoned) {
3997 break;
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07003998 }
3999 }
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07004000 listener = mListener.promote();
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07004001 }
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07004002
4003 if (listener != NULL && surfaceAbandoned) {
4004 listener->notifyRepeatingRequestError(lastFrameNumber);
Yin-Chia Yeh473fad92016-05-23 15:54:41 -07004005 }
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07004006}
4007
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004008bool Camera3Device::RequestThread::sendRequestsBatch() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004009 ATRACE_CALL();
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004010 status_t res;
4011 size_t batchSize = mNextRequests.size();
4012 std::vector<camera3_capture_request_t*> requests(batchSize);
4013 uint32_t numRequestProcessed = 0;
4014 for (size_t i = 0; i < batchSize; i++) {
4015 requests[i] = &mNextRequests.editItemAt(i).halRequest;
Yin-Chia Yeh885691c2018-05-01 15:54:24 -07004016 ATRACE_ASYNC_BEGIN("frame capture", mNextRequests[i].halRequest.frame_number);
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004017 }
4018
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004019 res = mInterface->processBatchCaptureRequests(requests, &numRequestProcessed);
4020
4021 bool triggerRemoveFailed = false;
4022 NextRequest& triggerFailedRequest = mNextRequests.editItemAt(0);
4023 for (size_t i = 0; i < numRequestProcessed; i++) {
4024 NextRequest& nextRequest = mNextRequests.editItemAt(i);
4025 nextRequest.submitted = true;
4026
Shuzhen Wangc2cba122018-05-17 18:10:24 -07004027 updateNextRequest(nextRequest);
Emilian Peevaebbe412018-01-15 13:53:24 +00004028
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004029 if (!triggerRemoveFailed) {
4030 // Remove any previously queued triggers (after unlock)
4031 status_t removeTriggerRes = removeTriggers(mPrevRequest);
4032 if (removeTriggerRes != OK) {
4033 triggerRemoveFailed = true;
4034 triggerFailedRequest = nextRequest;
4035 }
4036 }
4037 }
4038
4039 if (triggerRemoveFailed) {
4040 SET_ERR("RequestThread: Unable to remove triggers "
4041 "(capture request %d, HAL device: %s (%d)",
4042 triggerFailedRequest.halRequest.frame_number, strerror(-res), res);
4043 cleanUpFailedRequests(/*sendRequestError*/ false);
4044 return false;
4045 }
4046
4047 if (res != OK) {
4048 // Should only get a failure here for malformed requests or device-level
4049 // errors, so consider all errors fatal. Bad metadata failures should
4050 // come through notify.
4051 SET_ERR("RequestThread: Unable to submit capture request %d to HAL device: %s (%d)",
4052 mNextRequests[numRequestProcessed].halRequest.frame_number,
4053 strerror(-res), res);
4054 cleanUpFailedRequests(/*sendRequestError*/ false);
4055 return false;
4056 }
4057 return true;
4058}
4059
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07004060nsecs_t Camera3Device::RequestThread::calculateMaxExpectedDuration(const camera_metadata_t *request) {
4061 nsecs_t maxExpectedDuration = kDefaultExpectedDuration;
4062 camera_metadata_ro_entry_t e = camera_metadata_ro_entry_t();
4063 find_camera_metadata_ro_entry(request,
4064 ANDROID_CONTROL_AE_MODE,
4065 &e);
4066 if (e.count == 0) return maxExpectedDuration;
4067
4068 switch (e.data.u8[0]) {
4069 case ANDROID_CONTROL_AE_MODE_OFF:
4070 find_camera_metadata_ro_entry(request,
4071 ANDROID_SENSOR_EXPOSURE_TIME,
4072 &e);
4073 if (e.count > 0) {
4074 maxExpectedDuration = e.data.i64[0];
4075 }
4076 find_camera_metadata_ro_entry(request,
4077 ANDROID_SENSOR_FRAME_DURATION,
4078 &e);
4079 if (e.count > 0) {
4080 maxExpectedDuration = std::max(e.data.i64[0], maxExpectedDuration);
4081 }
4082 break;
4083 default:
4084 find_camera_metadata_ro_entry(request,
4085 ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
4086 &e);
4087 if (e.count > 1) {
4088 maxExpectedDuration = 1e9 / e.data.u8[0];
4089 }
4090 break;
4091 }
4092
4093 return maxExpectedDuration;
4094}
4095
Emilian Peeva14b4dd2018-05-15 11:00:31 +01004096bool Camera3Device::RequestThread::skipHFRTargetFPSUpdate(int32_t tag,
4097 const camera_metadata_ro_entry_t& newEntry, const camera_metadata_entry_t& currentEntry) {
4098 if (mConstrainedMode && (ANDROID_CONTROL_AE_TARGET_FPS_RANGE == tag) &&
4099 (newEntry.count == currentEntry.count) && (currentEntry.count == 2) &&
4100 (currentEntry.data.i32[1] == newEntry.data.i32[1])) {
4101 return true;
4102 }
4103
4104 return false;
4105}
4106
Shuzhen Wangc2cba122018-05-17 18:10:24 -07004107void Camera3Device::RequestThread::updateNextRequest(NextRequest& nextRequest) {
4108 // Update the latest request sent to HAL
4109 if (nextRequest.halRequest.settings != NULL) { // Don't update if they were unchanged
4110 Mutex::Autolock al(mLatestRequestMutex);
4111
4112 camera_metadata_t* cloned = clone_camera_metadata(nextRequest.halRequest.settings);
4113 mLatestRequest.acquire(cloned);
4114
4115 mLatestPhysicalRequest.clear();
4116 for (uint32_t i = 0; i < nextRequest.halRequest.num_physcam_settings; i++) {
4117 cloned = clone_camera_metadata(nextRequest.halRequest.physcam_settings[i]);
4118 mLatestPhysicalRequest.emplace(nextRequest.halRequest.physcam_id[i],
4119 CameraMetadata(cloned));
4120 }
4121
4122 sp<Camera3Device> parent = mParent.promote();
4123 if (parent != NULL) {
4124 parent->monitorMetadata(TagMonitor::REQUEST,
4125 nextRequest.halRequest.frame_number,
4126 0, mLatestRequest, mLatestPhysicalRequest);
4127 }
4128 }
4129
4130 if (nextRequest.halRequest.settings != NULL) {
4131 nextRequest.captureRequest->mSettingsList.begin()->metadata.unlock(
4132 nextRequest.halRequest.settings);
4133 }
4134
4135 cleanupPhysicalSettings(nextRequest.captureRequest, &nextRequest.halRequest);
4136}
4137
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004138bool Camera3Device::RequestThread::updateSessionParameters(const CameraMetadata& settings) {
4139 ATRACE_CALL();
4140 bool updatesDetected = false;
4141
Emilian Peev4ec17882019-01-24 17:16:58 -08004142 CameraMetadata updatedParams(mLatestSessionParams);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004143 for (auto tag : mSessionParamKeys) {
4144 camera_metadata_ro_entry entry = settings.find(tag);
Emilian Peev4ec17882019-01-24 17:16:58 -08004145 camera_metadata_entry lastEntry = updatedParams.find(tag);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004146
4147 if (entry.count > 0) {
4148 bool isDifferent = false;
4149 if (lastEntry.count > 0) {
4150 // Have a last value, compare to see if changed
4151 if (lastEntry.type == entry.type &&
4152 lastEntry.count == entry.count) {
4153 // Same type and count, compare values
4154 size_t bytesPerValue = camera_metadata_type_size[lastEntry.type];
4155 size_t entryBytes = bytesPerValue * lastEntry.count;
4156 int cmp = memcmp(entry.data.u8, lastEntry.data.u8, entryBytes);
4157 if (cmp != 0) {
4158 isDifferent = true;
4159 }
4160 } else {
4161 // Count or type has changed
4162 isDifferent = true;
4163 }
4164 } else {
4165 // No last entry, so always consider to be different
4166 isDifferent = true;
4167 }
4168
4169 if (isDifferent) {
4170 ALOGV("%s: Session parameter tag id %d changed", __FUNCTION__, tag);
Emilian Peeva14b4dd2018-05-15 11:00:31 +01004171 if (!skipHFRTargetFPSUpdate(tag, entry, lastEntry)) {
4172 updatesDetected = true;
4173 }
Emilian Peev4ec17882019-01-24 17:16:58 -08004174 updatedParams.update(entry);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004175 }
4176 } else if (lastEntry.count > 0) {
4177 // Value has been removed
4178 ALOGV("%s: Session parameter tag id %d removed", __FUNCTION__, tag);
Emilian Peev4ec17882019-01-24 17:16:58 -08004179 updatedParams.erase(tag);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004180 updatesDetected = true;
4181 }
4182 }
4183
Emilian Peev4ec17882019-01-24 17:16:58 -08004184 bool reconfigureRequired;
4185 if (updatesDetected) {
4186 reconfigureRequired = mInterface->isReconfigurationRequired(mLatestSessionParams,
4187 updatedParams);
4188 mLatestSessionParams = updatedParams;
4189 } else {
4190 reconfigureRequired = false;
4191 }
4192
4193 return reconfigureRequired;
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004194}
4195
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004196bool Camera3Device::RequestThread::threadLoop() {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004197 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004198 status_t res;
Jayant Chowdhary37eca242019-11-18 08:55:56 -08004199 // Any function called from threadLoop() must not hold mInterfaceLock since
4200 // it could lead to deadlocks (disconnect() -> hold mInterfaceMutex -> wait for request thread
4201 // to finish -> request thread waits on mInterfaceMutex) http://b/143513518
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004202
4203 // Handle paused state.
4204 if (waitIfPaused()) {
4205 return true;
4206 }
4207
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004208 // Wait for the next batch of requests.
4209 waitForNextRequestBatch();
4210 if (mNextRequests.size() == 0) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004211 return true;
4212 }
4213
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004214 // Get the latest request ID, if any
4215 int latestRequestId;
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004216 camera_metadata_entry_t requestIdEntry = mNextRequests[mNextRequests.size() - 1].
Emilian Peevaebbe412018-01-15 13:53:24 +00004217 captureRequest->mSettingsList.begin()->metadata.find(ANDROID_REQUEST_ID);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004218 if (requestIdEntry.count > 0) {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004219 latestRequestId = requestIdEntry.data.i32[0];
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004220 } else {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004221 ALOGW("%s: Did not have android.request.id set in the request.", __FUNCTION__);
4222 latestRequestId = NAME_NOT_FOUND;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004223 }
4224
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004225 // 'mNextRequests' will at this point contain either a set of HFR batched requests
4226 // or a single request from streaming or burst. In either case the first element
4227 // should contain the latest camera settings that we need to check for any session
4228 // parameter updates.
Emilian Peevaebbe412018-01-15 13:53:24 +00004229 if (updateSessionParameters(mNextRequests[0].captureRequest->mSettingsList.begin()->metadata)) {
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004230 res = OK;
4231
4232 //Input stream buffers are already acquired at this point so an input stream
4233 //will not be able to move to idle state unless we force it.
4234 if (mNextRequests[0].captureRequest->mInputStream != nullptr) {
4235 res = mNextRequests[0].captureRequest->mInputStream->forceToIdle();
4236 if (res != OK) {
4237 ALOGE("%s: Failed to force idle input stream: %d", __FUNCTION__, res);
4238 cleanUpFailedRequests(/*sendRequestError*/ false);
4239 return false;
4240 }
4241 }
4242
4243 if (res == OK) {
4244 sp<StatusTracker> statusTracker = mStatusTracker.promote();
4245 if (statusTracker != 0) {
Eino-Ville Talvala002001b2018-01-23 16:53:50 -08004246 sp<Camera3Device> parent = mParent.promote();
4247 if (parent != nullptr) {
4248 parent->pauseStateNotify(true);
4249 }
4250
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004251 statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);
4252
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004253 if (parent != nullptr) {
4254 mReconfigured |= parent->reconfigureCamera(mLatestSessionParams);
4255 }
4256
4257 statusTracker->markComponentActive(mStatusId);
4258 setPaused(false);
4259 }
4260
4261 if (mNextRequests[0].captureRequest->mInputStream != nullptr) {
4262 mNextRequests[0].captureRequest->mInputStream->restoreConfiguredState();
4263 if (res != OK) {
4264 ALOGE("%s: Failed to restore configured input stream: %d", __FUNCTION__, res);
4265 cleanUpFailedRequests(/*sendRequestError*/ false);
4266 return false;
4267 }
4268 }
4269 }
4270 }
4271
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004272 // Prepare a batch of HAL requests and output buffers.
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004273 res = prepareHalRequests();
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004274 if (res == TIMED_OUT) {
4275 // Not a fatal error if getting output buffers time out.
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004276 cleanUpFailedRequests(/*sendRequestError*/ true);
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07004277 // Check if any stream is abandoned.
4278 checkAndStopRepeatingRequest();
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004279 return true;
4280 } else if (res != OK) {
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004281 cleanUpFailedRequests(/*sendRequestError*/ false);
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07004282 return false;
4283 }
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004284
Zhijun Hecc27e112013-10-03 16:12:43 -07004285 // Inform waitUntilRequestProcessed thread of a new request ID
4286 {
4287 Mutex::Autolock al(mLatestRequestMutex);
4288
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004289 mLatestRequestId = latestRequestId;
Zhijun Hecc27e112013-10-03 16:12:43 -07004290 mLatestRequestSignal.signal();
4291 }
4292
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004293 // Submit a batch of requests to HAL.
4294 // Use flush lock only when submitting multilple requests in a batch.
4295 // TODO: The problem with flush lock is flush() will be blocked by process_capture_request()
4296 // which may take a long time to finish so synchronizing flush() and
4297 // process_capture_request() defeats the purpose of cancelling requests ASAP with flush().
4298 // For now, only synchronize for high speed recording and we should figure something out for
4299 // removing the synchronization.
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004300 bool useFlushLock = mNextRequests.size() > 1;
Eino-Ville Talvala17a61ad2013-06-03 16:53:32 -07004301
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004302 if (useFlushLock) {
4303 mFlushLock.lock();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004304 }
4305
Zhijun Hef0645c12016-08-02 00:58:11 -07004306 ALOGVV("%s: %d: submitting %zu requests in a batch.", __FUNCTION__, __LINE__,
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004307 mNextRequests.size());
Igor Murashkin1e479c02013-09-06 16:55:14 -07004308
Yin-Chia Yehcd333fe2019-02-08 13:45:41 -08004309 sp<Camera3Device> parent = mParent.promote();
4310 if (parent != nullptr) {
4311 parent->mRequestBufferSM.onSubmittingRequest();
4312 }
4313
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004314 bool submitRequestSuccess = false;
Shuzhen Wang686f6442017-06-20 16:16:04 -07004315 nsecs_t tRequestStart = systemTime(SYSTEM_TIME_MONOTONIC);
Yin-Chia Yeh11648852019-05-16 10:42:54 -07004316 submitRequestSuccess = sendRequestsBatch();
4317
Shuzhen Wang686f6442017-06-20 16:16:04 -07004318 nsecs_t tRequestEnd = systemTime(SYSTEM_TIME_MONOTONIC);
4319 mRequestLatency.add(tRequestStart, tRequestEnd);
Igor Murashkin1e479c02013-09-06 16:55:14 -07004320
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004321 if (useFlushLock) {
4322 mFlushLock.unlock();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004323 }
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004324
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004325 // Unset as current request
4326 {
4327 Mutex::Autolock l(mRequestLock);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004328 mNextRequests.clear();
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004329 }
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004330 mRequestSubmittedSignal.signal();
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004331
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004332 return submitRequestSuccess;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004333}
4334
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004335status_t Camera3Device::RequestThread::prepareHalRequests() {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004336 ATRACE_CALL();
4337
Yin-Chia Yehd07b11e2018-06-01 12:50:02 -07004338 bool batchedRequest = mNextRequests[0].captureRequest->mBatchSize > 1;
Shuzhen Wang4a472662017-02-26 23:29:04 -08004339 for (size_t i = 0; i < mNextRequests.size(); i++) {
4340 auto& nextRequest = mNextRequests.editItemAt(i);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004341 sp<CaptureRequest> captureRequest = nextRequest.captureRequest;
4342 camera3_capture_request_t* halRequest = &nextRequest.halRequest;
4343 Vector<camera3_stream_buffer_t>* outputBuffers = &nextRequest.outputBuffers;
4344
4345 // Prepare a request to HAL
4346 halRequest->frame_number = captureRequest->mResultExtras.frameNumber;
4347
4348 // Insert any queued triggers (before metadata is locked)
4349 status_t res = insertTriggers(captureRequest);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004350 if (res < 0) {
4351 SET_ERR("RequestThread: Unable to insert triggers "
4352 "(capture request %d, HAL device: %s (%d)",
4353 halRequest->frame_number, strerror(-res), res);
4354 return INVALID_OPERATION;
4355 }
Eino-Ville Talvala7b8a1fd2018-05-22 15:30:35 -07004356
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004357 int triggerCount = res;
4358 bool triggersMixedIn = (triggerCount > 0 || mPrevTriggers > 0);
4359 mPrevTriggers = triggerCount;
4360
4361 // If the request is the same as last, or we had triggers last time
Yin-Chia Yehd07b11e2018-06-01 12:50:02 -07004362 bool newRequest = (mPrevRequest != captureRequest || triggersMixedIn) &&
4363 // Request settings are all the same within one batch, so only treat the first
4364 // request in a batch as new
Zhijun He54c36822018-07-18 09:33:39 -07004365 !(batchedRequest && i > 0);
Emilian Peev00420d22018-02-05 21:33:13 +00004366 if (newRequest) {
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08004367 std::set<std::string> cameraIdsWithZoom;
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004368 /**
4369 * HAL workaround:
4370 * Insert a dummy trigger ID if a trigger is set but no trigger ID is
4371 */
4372 res = addDummyTriggerIds(captureRequest);
4373 if (res != OK) {
4374 SET_ERR("RequestThread: Unable to insert dummy trigger IDs "
4375 "(capture request %d, HAL device: %s (%d)",
4376 halRequest->frame_number, strerror(-res), res);
4377 return INVALID_OPERATION;
4378 }
4379
Eino-Ville Talvala7b8a1fd2018-05-22 15:30:35 -07004380 {
4381 // Correct metadata regions for distortion correction if enabled
4382 sp<Camera3Device> parent = mParent.promote();
4383 if (parent != nullptr) {
Shuzhen Wang4f6fa9d2019-03-29 10:40:35 -07004384 List<PhysicalCameraSettings>::iterator it;
4385 for (it = captureRequest->mSettingsList.begin();
4386 it != captureRequest->mSettingsList.end(); it++) {
4387 if (parent->mDistortionMappers.find(it->cameraId) ==
4388 parent->mDistortionMappers.end()) {
4389 continue;
4390 }
4391 res = parent->mDistortionMappers[it->cameraId].correctCaptureRequest(
4392 &(it->metadata));
4393 if (res != OK) {
4394 SET_ERR("RequestThread: Unable to correct capture requests "
4395 "for lens distortion for request %d: %s (%d)",
4396 halRequest->frame_number, strerror(-res), res);
4397 return INVALID_OPERATION;
4398 }
Eino-Ville Talvala7b8a1fd2018-05-22 15:30:35 -07004399 }
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08004400
4401 for (it = captureRequest->mSettingsList.begin();
4402 it != captureRequest->mSettingsList.end(); it++) {
4403 if (parent->mZoomRatioMappers.find(it->cameraId) ==
4404 parent->mZoomRatioMappers.end()) {
4405 continue;
4406 }
4407
4408 camera_metadata_entry_t e = it->metadata.find(ANDROID_CONTROL_ZOOM_RATIO);
4409 if (e.count > 0 && e.data.f[0] != 1.0f) {
4410 cameraIdsWithZoom.insert(it->cameraId);
4411 }
4412
4413 res = parent->mZoomRatioMappers[it->cameraId].updateCaptureRequest(
4414 &(it->metadata));
4415 if (res != OK) {
4416 SET_ERR("RequestThread: Unable to correct capture requests "
4417 "for zoom ratio for request %d: %s (%d)",
4418 halRequest->frame_number, strerror(-res), res);
4419 return INVALID_OPERATION;
4420 }
4421 }
Eino-Ville Talvala7b8a1fd2018-05-22 15:30:35 -07004422 }
4423 }
4424
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004425 /**
4426 * The request should be presorted so accesses in HAL
4427 * are O(logn). Sidenote, sorting a sorted metadata is nop.
4428 */
Emilian Peevaebbe412018-01-15 13:53:24 +00004429 captureRequest->mSettingsList.begin()->metadata.sort();
4430 halRequest->settings = captureRequest->mSettingsList.begin()->metadata.getAndLock();
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004431 mPrevRequest = captureRequest;
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08004432 mPrevCameraIdsWithZoom = cameraIdsWithZoom;
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004433 ALOGVV("%s: Request settings are NEW", __FUNCTION__);
4434
4435 IF_ALOGV() {
4436 camera_metadata_ro_entry_t e = camera_metadata_ro_entry_t();
4437 find_camera_metadata_ro_entry(
4438 halRequest->settings,
4439 ANDROID_CONTROL_AF_TRIGGER,
4440 &e
4441 );
4442 if (e.count > 0) {
4443 ALOGV("%s: Request (frame num %d) had AF trigger 0x%x",
4444 __FUNCTION__,
4445 halRequest->frame_number,
4446 e.data.u8[0]);
4447 }
4448 }
4449 } else {
4450 // leave request.settings NULL to indicate 'reuse latest given'
4451 ALOGVV("%s: Request settings are REUSED",
4452 __FUNCTION__);
4453 }
4454
Emilian Peevaebbe412018-01-15 13:53:24 +00004455 if (captureRequest->mSettingsList.size() > 1) {
4456 halRequest->num_physcam_settings = captureRequest->mSettingsList.size() - 1;
4457 halRequest->physcam_id = new const char* [halRequest->num_physcam_settings];
Emilian Peev00420d22018-02-05 21:33:13 +00004458 if (newRequest) {
4459 halRequest->physcam_settings =
4460 new const camera_metadata* [halRequest->num_physcam_settings];
4461 } else {
4462 halRequest->physcam_settings = nullptr;
4463 }
Emilian Peevaebbe412018-01-15 13:53:24 +00004464 auto it = ++captureRequest->mSettingsList.begin();
4465 size_t i = 0;
4466 for (; it != captureRequest->mSettingsList.end(); it++, i++) {
4467 halRequest->physcam_id[i] = it->cameraId.c_str();
Emilian Peev00420d22018-02-05 21:33:13 +00004468 if (newRequest) {
4469 it->metadata.sort();
4470 halRequest->physcam_settings[i] = it->metadata.getAndLock();
4471 }
Emilian Peevaebbe412018-01-15 13:53:24 +00004472 }
4473 }
4474
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004475 uint32_t totalNumBuffers = 0;
4476
4477 // Fill in buffers
4478 if (captureRequest->mInputStream != NULL) {
4479 halRequest->input_buffer = &captureRequest->mInputBuffer;
4480 totalNumBuffers += 1;
4481 } else {
4482 halRequest->input_buffer = NULL;
4483 }
4484
4485 outputBuffers->insertAt(camera3_stream_buffer_t(), 0,
4486 captureRequest->mOutputStreams.size());
4487 halRequest->output_buffers = outputBuffers->array();
Shuzhen Wang5c22c152017-12-31 17:12:25 -08004488 std::set<String8> requestedPhysicalCameras;
Yin-Chia Yehb3a80b12018-09-04 12:13:05 -07004489
4490 sp<Camera3Device> parent = mParent.promote();
4491 if (parent == NULL) {
4492 // Should not happen, and nowhere to send errors to, so just log it
4493 CLOGE("RequestThread: Parent is gone");
4494 return INVALID_OPERATION;
4495 }
4496 nsecs_t waitDuration = kBaseGetBufferWait + parent->getExpectedInFlightDuration();
4497
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004498 SurfaceMap uniqueSurfaceIdMap;
Shuzhen Wang4a472662017-02-26 23:29:04 -08004499 for (size_t j = 0; j < captureRequest->mOutputStreams.size(); j++) {
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004500 sp<Camera3OutputStreamInterface> outputStream =
4501 captureRequest->mOutputStreams.editItemAt(j);
4502 int streamId = outputStream->getId();
Chien-Yu Chenc66969b2016-05-19 16:37:51 -07004503
4504 // Prepare video buffers for high speed recording on the first video request.
4505 if (mPrepareVideoStream && outputStream->isVideoStream()) {
4506 // Only try to prepare video stream on the first video request.
4507 mPrepareVideoStream = false;
4508
Shuzhen Wangb3a0fb52018-09-13 17:24:08 -07004509 res = outputStream->startPrepare(Camera3StreamInterface::ALLOCATE_PIPELINE_MAX,
4510 false /*blockRequest*/);
Chien-Yu Chenc66969b2016-05-19 16:37:51 -07004511 while (res == NOT_ENOUGH_DATA) {
4512 res = outputStream->prepareNextBuffer();
4513 }
4514 if (res != OK) {
4515 ALOGW("%s: Preparing video buffers for high speed failed: %s (%d)",
4516 __FUNCTION__, strerror(-res), res);
4517 outputStream->cancelPrepare();
4518 }
4519 }
4520
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004521 std::vector<size_t> uniqueSurfaceIds;
4522 res = outputStream->getUniqueSurfaceIds(
4523 captureRequest->mOutputSurfaces[streamId],
4524 &uniqueSurfaceIds);
4525 // INVALID_OPERATION is normal output for streams not supporting surfaceIds
4526 if (res != OK && res != INVALID_OPERATION) {
4527 ALOGE("%s: failed to query stream %d unique surface IDs",
4528 __FUNCTION__, streamId);
4529 return res;
4530 }
4531 if (res == OK) {
4532 uniqueSurfaceIdMap.insert({streamId, std::move(uniqueSurfaceIds)});
4533 }
4534
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07004535 if (mUseHalBufManager) {
Yin-Chia Yeh110342b2018-11-19 11:47:46 -08004536 if (outputStream->isAbandoned()) {
Yin-Chia Yeha1b56c82019-03-27 15:50:39 -07004537 ALOGV("%s: stream %d is abandoned, skipping request", __FUNCTION__, streamId);
Yin-Chia Yeh110342b2018-11-19 11:47:46 -08004538 return TIMED_OUT;
4539 }
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07004540 // HAL will request buffer through requestStreamBuffer API
4541 camera3_stream_buffer_t& buffer = outputBuffers->editItemAt(j);
4542 buffer.stream = outputStream->asHalStream();
4543 buffer.buffer = nullptr;
4544 buffer.status = CAMERA3_BUFFER_STATUS_OK;
4545 buffer.acquire_fence = -1;
4546 buffer.release_fence = -1;
4547 } else {
4548 res = outputStream->getBuffer(&outputBuffers->editItemAt(j),
4549 waitDuration,
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004550 captureRequest->mOutputSurfaces[streamId]);
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07004551 if (res != OK) {
4552 // Can't get output buffer from gralloc queue - this could be due to
4553 // abandoned queue or other consumer misbehavior, so not a fatal
4554 // error
Yin-Chia Yeha1b56c82019-03-27 15:50:39 -07004555 ALOGV("RequestThread: Can't get output buffer, skipping request:"
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07004556 " %s (%d)", strerror(-res), res);
4557
4558 return TIMED_OUT;
4559 }
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004560 }
Shuzhen Wang68ac7ad2019-01-30 14:03:28 -08004561
4562 {
4563 sp<Camera3Device> parent = mParent.promote();
4564 if (parent != nullptr) {
4565 const String8& streamCameraId = outputStream->getPhysicalCameraId();
4566 for (const auto& settings : captureRequest->mSettingsList) {
4567 if ((streamCameraId.isEmpty() &&
4568 parent->getId() == settings.cameraId.c_str()) ||
4569 streamCameraId == settings.cameraId.c_str()) {
4570 outputStream->fireBufferRequestForFrameNumber(
4571 captureRequest->mResultExtras.frameNumber,
4572 settings.metadata);
4573 }
4574 }
4575 }
4576 }
Shuzhen Wang0129d522016-10-30 22:43:41 -07004577
Shuzhen Wang5c22c152017-12-31 17:12:25 -08004578 String8 physicalCameraId = outputStream->getPhysicalCameraId();
4579
4580 if (!physicalCameraId.isEmpty()) {
4581 // Physical stream isn't supported for input request.
4582 if (halRequest->input_buffer) {
4583 CLOGE("Physical stream is not supported for input request");
4584 return INVALID_OPERATION;
4585 }
4586 requestedPhysicalCameras.insert(physicalCameraId);
4587 }
4588 halRequest->num_output_buffers++;
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004589 }
4590 totalNumBuffers += halRequest->num_output_buffers;
4591
4592 // Log request in the in-flight queue
Shuzhen Wang4a472662017-02-26 23:29:04 -08004593 // If this request list is for constrained high speed recording (not
4594 // preview), and the current request is not the last one in the batch,
4595 // do not send callback to the app.
4596 bool hasCallback = true;
Yin-Chia Yehd07b11e2018-06-01 12:50:02 -07004597 if (batchedRequest && i != mNextRequests.size()-1) {
Shuzhen Wang4a472662017-02-26 23:29:04 -08004598 hasCallback = false;
4599 }
Emilian Peev9dd21f42018-08-03 13:39:29 +01004600 bool isStillCapture = false;
Shuzhen Wang26abaf42018-08-28 15:41:20 -07004601 bool isZslCapture = false;
Emilian Peev9dd21f42018-08-03 13:39:29 +01004602 if (!mNextRequests[0].captureRequest->mSettingsList.begin()->metadata.isEmpty()) {
4603 camera_metadata_ro_entry_t e = camera_metadata_ro_entry_t();
4604 find_camera_metadata_ro_entry(halRequest->settings, ANDROID_CONTROL_CAPTURE_INTENT, &e);
4605 if ((e.count > 0) && (e.data.u8[0] == ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE)) {
4606 isStillCapture = true;
4607 ATRACE_ASYNC_BEGIN("still capture", mNextRequests[i].halRequest.frame_number);
4608 }
Shuzhen Wang26abaf42018-08-28 15:41:20 -07004609
4610 find_camera_metadata_ro_entry(halRequest->settings, ANDROID_CONTROL_ENABLE_ZSL, &e);
4611 if ((e.count > 0) && (e.data.u8[0] == ANDROID_CONTROL_ENABLE_ZSL_TRUE)) {
4612 isZslCapture = true;
4613 }
Emilian Peev9dd21f42018-08-03 13:39:29 +01004614 }
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004615 res = parent->registerInFlight(halRequest->frame_number,
4616 totalNumBuffers, captureRequest->mResultExtras,
4617 /*hasInput*/halRequest->input_buffer != NULL,
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07004618 hasCallback,
Shuzhen Wang5c22c152017-12-31 17:12:25 -08004619 calculateMaxExpectedDuration(halRequest->settings),
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08004620 requestedPhysicalCameras, isStillCapture, isZslCapture, mPrevCameraIdsWithZoom,
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004621 (mUseHalBufManager) ? uniqueSurfaceIdMap :
4622 SurfaceMap{});
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004623 ALOGVV("%s: registered in flight requestId = %" PRId32 ", frameNumber = %" PRId64
4624 ", burstId = %" PRId32 ".",
4625 __FUNCTION__,
4626 captureRequest->mResultExtras.requestId, captureRequest->mResultExtras.frameNumber,
4627 captureRequest->mResultExtras.burstId);
4628 if (res != OK) {
4629 SET_ERR("RequestThread: Unable to register new in-flight request:"
4630 " %s (%d)", strerror(-res), res);
4631 return INVALID_OPERATION;
4632 }
4633 }
4634
4635 return OK;
4636}
4637
Igor Murashkin1e479c02013-09-06 16:55:14 -07004638CameraMetadata Camera3Device::RequestThread::getLatestRequest() const {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004639 ATRACE_CALL();
Igor Murashkin1e479c02013-09-06 16:55:14 -07004640 Mutex::Autolock al(mLatestRequestMutex);
4641
4642 ALOGV("RequestThread::%s", __FUNCTION__);
4643
4644 return mLatestRequest;
4645}
4646
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07004647bool Camera3Device::RequestThread::isStreamPending(
4648 sp<Camera3StreamInterface>& stream) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004649 ATRACE_CALL();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07004650 Mutex::Autolock l(mRequestLock);
4651
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004652 for (const auto& nextRequest : mNextRequests) {
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004653 if (!nextRequest.submitted) {
4654 for (const auto& s : nextRequest.captureRequest->mOutputStreams) {
4655 if (stream == s) return true;
4656 }
4657 if (stream == nextRequest.captureRequest->mInputStream) return true;
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004658 }
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004659 }
4660
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07004661 for (const auto& request : mRequestQueue) {
4662 for (const auto& s : request->mOutputStreams) {
4663 if (stream == s) return true;
4664 }
4665 if (stream == request->mInputStream) return true;
4666 }
4667
4668 for (const auto& request : mRepeatingRequests) {
4669 for (const auto& s : request->mOutputStreams) {
4670 if (stream == s) return true;
4671 }
4672 if (stream == request->mInputStream) return true;
4673 }
4674
4675 return false;
4676}
Jianing Weicb0652e2014-03-12 18:29:36 -07004677
Emilian Peev40ead602017-09-26 15:46:36 +01004678bool Camera3Device::RequestThread::isOutputSurfacePending(int streamId, size_t surfaceId) {
4679 ATRACE_CALL();
4680 Mutex::Autolock l(mRequestLock);
4681
4682 for (const auto& nextRequest : mNextRequests) {
4683 for (const auto& s : nextRequest.captureRequest->mOutputSurfaces) {
4684 if (s.first == streamId) {
4685 const auto &it = std::find(s.second.begin(), s.second.end(), surfaceId);
4686 if (it != s.second.end()) {
4687 return true;
4688 }
4689 }
4690 }
4691 }
4692
4693 for (const auto& request : mRequestQueue) {
4694 for (const auto& s : request->mOutputSurfaces) {
4695 if (s.first == streamId) {
4696 const auto &it = std::find(s.second.begin(), s.second.end(), surfaceId);
4697 if (it != s.second.end()) {
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004698 return true;
Emilian Peev40ead602017-09-26 15:46:36 +01004699 }
4700 }
4701 }
4702 }
4703
4704 for (const auto& request : mRepeatingRequests) {
4705 for (const auto& s : request->mOutputSurfaces) {
4706 if (s.first == streamId) {
4707 const auto &it = std::find(s.second.begin(), s.second.end(), surfaceId);
4708 if (it != s.second.end()) {
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004709 return true;
Emilian Peev40ead602017-09-26 15:46:36 +01004710 }
4711 }
4712 }
4713 }
4714
4715 return false;
4716}
4717
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07004718void Camera3Device::RequestThread::signalPipelineDrain(const std::vector<int>& streamIds) {
4719 if (!mUseHalBufManager) {
4720 ALOGE("%s called for camera device not supporting HAL buffer management", __FUNCTION__);
4721 return;
4722 }
4723
4724 Mutex::Autolock pl(mPauseLock);
4725 if (mPaused) {
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07004726 mInterface->signalPipelineDrain(streamIds);
4727 return;
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07004728 }
4729 // If request thread is still busy, wait until paused then notify HAL
4730 mNotifyPipelineDrain = true;
4731 mStreamIdsToBeDrained = streamIds;
4732}
4733
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004734status_t Camera3Device::RequestThread::switchToOffline(
4735 const std::vector<int32_t>& streamsToKeep,
4736 /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004737 /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
4738 /*out*/camera3::BufferRecords* bufferRecords) {
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004739 Mutex::Autolock l(mRequestLock);
4740 clearRepeatingRequestsLocked(/*lastFrameNumber*/nullptr);
4741
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004742 // Wait until request thread is fully stopped
4743 // TBD: check if request thread is being paused by other APIs (shouldn't be)
4744
4745 // We could also check for mRepeatingRequests.empty(), but the API interface
4746 // is serialized by Camera3Device::mInterfaceLock so no one should be able to submit any
4747 // new requests during the call; hence skip that check.
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004748 bool queueEmpty = mNextRequests.empty() && mRequestQueue.empty();
4749 while (!queueEmpty) {
4750 status_t res = mRequestSubmittedSignal.waitRelative(mRequestLock, kRequestSubmitTimeout);
4751 if (res == TIMED_OUT) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004752 ALOGE("%s: request thread failed to submit one request within timeout!", __FUNCTION__);
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004753 return res;
4754 } else if (res != OK) {
4755 ALOGE("%s: request thread failed to submit a request: %s (%d)!",
4756 __FUNCTION__, strerror(-res), res);
4757 return res;
4758 }
4759 queueEmpty = mNextRequests.empty() && mRequestQueue.empty();
4760 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004761
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004762 return mInterface->switchToOffline(
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004763 streamsToKeep, offlineSessionInfo, offlineSession, bufferRecords);
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004764}
4765
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07004766nsecs_t Camera3Device::getExpectedInFlightDuration() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004767 ATRACE_CALL();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004768 std::lock_guard<std::mutex> l(mInFlightLock);
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07004769 return mExpectedInflightDuration > kMinInflightDuration ?
4770 mExpectedInflightDuration : kMinInflightDuration;
4771}
4772
Emilian Peevaebbe412018-01-15 13:53:24 +00004773void Camera3Device::RequestThread::cleanupPhysicalSettings(sp<CaptureRequest> request,
4774 camera3_capture_request_t *halRequest) {
4775 if ((request == nullptr) || (halRequest == nullptr)) {
4776 ALOGE("%s: Invalid request!", __FUNCTION__);
4777 return;
4778 }
4779
4780 if (halRequest->num_physcam_settings > 0) {
4781 if (halRequest->physcam_id != nullptr) {
4782 delete [] halRequest->physcam_id;
4783 halRequest->physcam_id = nullptr;
4784 }
4785 if (halRequest->physcam_settings != nullptr) {
4786 auto it = ++(request->mSettingsList.begin());
4787 size_t i = 0;
4788 for (; it != request->mSettingsList.end(); it++, i++) {
4789 it->metadata.unlock(halRequest->physcam_settings[i]);
4790 }
4791 delete [] halRequest->physcam_settings;
4792 halRequest->physcam_settings = nullptr;
4793 }
4794 }
4795}
4796
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004797void Camera3Device::RequestThread::cleanUpFailedRequests(bool sendRequestError) {
4798 if (mNextRequests.empty()) {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004799 return;
4800 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004801
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004802 for (auto& nextRequest : mNextRequests) {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004803 // Skip the ones that have been submitted successfully.
4804 if (nextRequest.submitted) {
4805 continue;
4806 }
4807
4808 sp<CaptureRequest> captureRequest = nextRequest.captureRequest;
4809 camera3_capture_request_t* halRequest = &nextRequest.halRequest;
4810 Vector<camera3_stream_buffer_t>* outputBuffers = &nextRequest.outputBuffers;
4811
4812 if (halRequest->settings != NULL) {
Emilian Peevaebbe412018-01-15 13:53:24 +00004813 captureRequest->mSettingsList.begin()->metadata.unlock(halRequest->settings);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004814 }
4815
Emilian Peevaebbe412018-01-15 13:53:24 +00004816 cleanupPhysicalSettings(captureRequest, halRequest);
4817
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004818 if (captureRequest->mInputStream != NULL) {
4819 captureRequest->mInputBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
4820 captureRequest->mInputStream->returnInputBuffer(captureRequest->mInputBuffer);
4821 }
4822
Yin-Chia Yeh21cb47b2019-01-18 15:08:17 -08004823 // No output buffer can be returned when using HAL buffer manager
4824 if (!mUseHalBufManager) {
4825 for (size_t i = 0; i < halRequest->num_output_buffers; i++) {
4826 //Buffers that failed processing could still have
4827 //valid acquire fence.
4828 int acquireFence = (*outputBuffers)[i].acquire_fence;
4829 if (0 <= acquireFence) {
4830 close(acquireFence);
4831 outputBuffers->editItemAt(i).acquire_fence = -1;
4832 }
4833 outputBuffers->editItemAt(i).status = CAMERA3_BUFFER_STATUS_ERROR;
4834 captureRequest->mOutputStreams.editItemAt(i)->returnBuffer((*outputBuffers)[i], 0,
4835 /*timestampIncreasing*/true, std::vector<size_t> (),
4836 captureRequest->mResultExtras.frameNumber);
Emilian Peevc58cf4c2017-05-11 17:23:41 +01004837 }
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004838 }
4839
4840 if (sendRequestError) {
4841 Mutex::Autolock l(mRequestLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07004842 sp<NotificationListener> listener = mListener.promote();
4843 if (listener != NULL) {
4844 listener->notifyError(
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08004845 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004846 captureRequest->mResultExtras);
4847 }
4848 }
Shuzhen Wangcadb3302016-11-04 14:17:56 -07004849
4850 // Remove yet-to-be submitted inflight request from inflightMap
4851 {
4852 sp<Camera3Device> parent = mParent.promote();
4853 if (parent != NULL) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004854 std::lock_guard<std::mutex> l(parent->mInFlightLock);
Shuzhen Wangcadb3302016-11-04 14:17:56 -07004855 ssize_t idx = parent->mInFlightMap.indexOfKey(captureRequest->mResultExtras.frameNumber);
4856 if (idx >= 0) {
4857 ALOGV("%s: Remove inflight request from queue: frameNumber %" PRId64,
4858 __FUNCTION__, captureRequest->mResultExtras.frameNumber);
4859 parent->removeInFlightMapEntryLocked(idx);
4860 }
4861 }
4862 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004863 }
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004864
4865 Mutex::Autolock l(mRequestLock);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004866 mNextRequests.clear();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004867}
4868
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004869void Camera3Device::RequestThread::waitForNextRequestBatch() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004870 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004871 // Optimized a bit for the simple steady-state case (single repeating
4872 // request), to avoid putting that request in the queue temporarily.
4873 Mutex::Autolock l(mRequestLock);
4874
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004875 assert(mNextRequests.empty());
4876
4877 NextRequest nextRequest;
4878 nextRequest.captureRequest = waitForNextRequestLocked();
4879 if (nextRequest.captureRequest == nullptr) {
4880 return;
4881 }
4882
4883 nextRequest.halRequest = camera3_capture_request_t();
4884 nextRequest.submitted = false;
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004885 mNextRequests.add(nextRequest);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004886
4887 // Wait for additional requests
4888 const size_t batchSize = nextRequest.captureRequest->mBatchSize;
4889
4890 for (size_t i = 1; i < batchSize; i++) {
4891 NextRequest additionalRequest;
4892 additionalRequest.captureRequest = waitForNextRequestLocked();
4893 if (additionalRequest.captureRequest == nullptr) {
4894 break;
4895 }
4896
4897 additionalRequest.halRequest = camera3_capture_request_t();
4898 additionalRequest.submitted = false;
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004899 mNextRequests.add(additionalRequest);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004900 }
4901
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004902 if (mNextRequests.size() < batchSize) {
Eino-Ville Talvalad309fb92015-11-25 12:12:45 -08004903 ALOGE("RequestThread: only get %zu out of %zu requests. Skipping requests.",
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004904 mNextRequests.size(), batchSize);
4905 cleanUpFailedRequests(/*sendRequestError*/true);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004906 }
4907
4908 return;
4909}
4910
4911sp<Camera3Device::CaptureRequest>
4912 Camera3Device::RequestThread::waitForNextRequestLocked() {
4913 status_t res;
4914 sp<CaptureRequest> nextRequest;
4915
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004916 while (mRequestQueue.empty()) {
4917 if (!mRepeatingRequests.empty()) {
4918 // Always atomically enqueue all requests in a repeating request
4919 // list. Guarantees a complete in-sequence set of captures to
4920 // application.
4921 const RequestList &requests = mRepeatingRequests;
4922 RequestList::const_iterator firstRequest =
4923 requests.begin();
4924 nextRequest = *firstRequest;
4925 mRequestQueue.insert(mRequestQueue.end(),
4926 ++firstRequest,
4927 requests.end());
4928 // No need to wait any longer
Jianing Weicb0652e2014-03-12 18:29:36 -07004929
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07004930 mRepeatingLastFrameNumber = mFrameNumber + requests.size() - 1;
Jianing Weicb0652e2014-03-12 18:29:36 -07004931
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004932 break;
4933 }
4934
4935 res = mRequestSignal.waitRelative(mRequestLock, kRequestTimeout);
4936
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004937 if ((mRequestQueue.empty() && mRepeatingRequests.empty()) ||
4938 exitPending()) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004939 Mutex::Autolock pl(mPauseLock);
4940 if (mPaused == false) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004941 ALOGV("%s: RequestThread: Going idle", __FUNCTION__);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004942 mPaused = true;
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07004943 if (mNotifyPipelineDrain) {
4944 mInterface->signalPipelineDrain(mStreamIdsToBeDrained);
4945 mNotifyPipelineDrain = false;
4946 mStreamIdsToBeDrained.clear();
4947 }
Yin-Chia Yehc300a072019-02-13 14:56:57 -08004948 // Let the tracker know
4949 sp<StatusTracker> statusTracker = mStatusTracker.promote();
4950 if (statusTracker != 0) {
4951 statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);
4952 }
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07004953 sp<Camera3Device> parent = mParent.promote();
4954 if (parent != nullptr) {
4955 parent->mRequestBufferSM.onRequestThreadPaused();
4956 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004957 }
4958 // Stop waiting for now and let thread management happen
4959 return NULL;
4960 }
4961 }
4962
4963 if (nextRequest == NULL) {
4964 // Don't have a repeating request already in hand, so queue
4965 // must have an entry now.
4966 RequestList::iterator firstRequest =
4967 mRequestQueue.begin();
4968 nextRequest = *firstRequest;
4969 mRequestQueue.erase(firstRequest);
Shuzhen Wang9d066012016-09-30 11:30:20 -07004970 if (mRequestQueue.empty() && !nextRequest->mRepeating) {
4971 sp<NotificationListener> listener = mListener.promote();
4972 if (listener != NULL) {
4973 listener->notifyRequestQueueEmpty();
4974 }
4975 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004976 }
4977
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07004978 // In case we've been unpaused by setPaused clearing mDoPause, need to
4979 // update internal pause state (capture/setRepeatingRequest unpause
4980 // directly).
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004981 Mutex::Autolock pl(mPauseLock);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004982 if (mPaused) {
4983 ALOGV("%s: RequestThread: Unpaused", __FUNCTION__);
4984 sp<StatusTracker> statusTracker = mStatusTracker.promote();
4985 if (statusTracker != 0) {
4986 statusTracker->markComponentActive(mStatusId);
4987 }
4988 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004989 mPaused = false;
4990
4991 // Check if we've reconfigured since last time, and reset the preview
4992 // request if so. Can't use 'NULL request == repeat' across configure calls.
4993 if (mReconfigured) {
4994 mPrevRequest.clear();
4995 mReconfigured = false;
4996 }
4997
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07004998 if (nextRequest != NULL) {
4999 nextRequest->mResultExtras.frameNumber = mFrameNumber++;
Yin-Chia Yehc00a25c2014-08-21 14:27:44 -07005000 nextRequest->mResultExtras.afTriggerId = mCurrentAfTriggerId;
5001 nextRequest->mResultExtras.precaptureTriggerId = mCurrentPreCaptureTriggerId;
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07005002
5003 // Since RequestThread::clear() removes buffers from the input stream,
5004 // get the right buffer here before unlocking mRequestLock
5005 if (nextRequest->mInputStream != NULL) {
5006 res = nextRequest->mInputStream->getInputBuffer(&nextRequest->mInputBuffer);
5007 if (res != OK) {
5008 // Can't get input buffer from gralloc queue - this could be due to
5009 // disconnected queue or other producer misbehavior, so not a fatal
5010 // error
5011 ALOGE("%s: Can't get input buffer, skipping request:"
5012 " %s (%d)", __FUNCTION__, strerror(-res), res);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005013
5014 sp<NotificationListener> listener = mListener.promote();
5015 if (listener != NULL) {
5016 listener->notifyError(
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08005017 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07005018 nextRequest->mResultExtras);
5019 }
5020 return NULL;
5021 }
5022 }
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07005023 }
Chien-Yu Chend196d612015-06-22 19:49:01 -07005024
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005025 return nextRequest;
5026}
5027
5028bool Camera3Device::RequestThread::waitIfPaused() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005029 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005030 status_t res;
5031 Mutex::Autolock l(mPauseLock);
5032 while (mDoPause) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005033 if (mPaused == false) {
5034 mPaused = true;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005035 ALOGV("%s: RequestThread: Paused", __FUNCTION__);
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07005036 if (mNotifyPipelineDrain) {
5037 mInterface->signalPipelineDrain(mStreamIdsToBeDrained);
5038 mNotifyPipelineDrain = false;
5039 mStreamIdsToBeDrained.clear();
5040 }
Yin-Chia Yehc300a072019-02-13 14:56:57 -08005041 // Let the tracker know
5042 sp<StatusTracker> statusTracker = mStatusTracker.promote();
5043 if (statusTracker != 0) {
5044 statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);
5045 }
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005046 sp<Camera3Device> parent = mParent.promote();
5047 if (parent != nullptr) {
5048 parent->mRequestBufferSM.onRequestThreadPaused();
5049 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005050 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005051
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005052 res = mDoPauseSignal.waitRelative(mPauseLock, kRequestTimeout);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005053 if (res == TIMED_OUT || exitPending()) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005054 return true;
5055 }
5056 }
5057 // We don't set mPaused to false here, because waitForNextRequest needs
5058 // to further manage the paused state in case of starvation.
5059 return false;
5060}
5061
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07005062void Camera3Device::RequestThread::unpauseForNewRequests() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005063 ATRACE_CALL();
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07005064 // With work to do, mark thread as unpaused.
5065 // If paused by request (setPaused), don't resume, to avoid
5066 // extra signaling/waiting overhead to waitUntilPaused
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005067 mRequestSignal.signal();
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07005068 Mutex::Autolock p(mPauseLock);
5069 if (!mDoPause) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005070 ALOGV("%s: RequestThread: Going active", __FUNCTION__);
5071 if (mPaused) {
5072 sp<StatusTracker> statusTracker = mStatusTracker.promote();
5073 if (statusTracker != 0) {
5074 statusTracker->markComponentActive(mStatusId);
5075 }
5076 }
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07005077 mPaused = false;
5078 }
5079}
5080
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07005081void Camera3Device::RequestThread::setErrorState(const char *fmt, ...) {
5082 sp<Camera3Device> parent = mParent.promote();
5083 if (parent != NULL) {
5084 va_list args;
5085 va_start(args, fmt);
5086
5087 parent->setErrorStateV(fmt, args);
5088
5089 va_end(args);
5090 }
5091}
5092
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005093status_t Camera3Device::RequestThread::insertTriggers(
5094 const sp<CaptureRequest> &request) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005095 ATRACE_CALL();
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005096 Mutex::Autolock al(mTriggerMutex);
5097
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07005098 sp<Camera3Device> parent = mParent.promote();
5099 if (parent == NULL) {
5100 CLOGE("RequestThread: Parent is gone");
5101 return DEAD_OBJECT;
5102 }
5103
Emilian Peevaebbe412018-01-15 13:53:24 +00005104 CameraMetadata &metadata = request->mSettingsList.begin()->metadata;
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005105 size_t count = mTriggerMap.size();
5106
5107 for (size_t i = 0; i < count; ++i) {
5108 RequestTrigger trigger = mTriggerMap.valueAt(i);
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005109 uint32_t tag = trigger.metadataTag;
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07005110
5111 if (tag == ANDROID_CONTROL_AF_TRIGGER_ID || tag == ANDROID_CONTROL_AE_PRECAPTURE_ID) {
5112 bool isAeTrigger = (trigger.metadataTag == ANDROID_CONTROL_AE_PRECAPTURE_ID);
5113 uint32_t triggerId = static_cast<uint32_t>(trigger.entryValue);
Yin-Chia Yehc00a25c2014-08-21 14:27:44 -07005114 if (isAeTrigger) {
5115 request->mResultExtras.precaptureTriggerId = triggerId;
5116 mCurrentPreCaptureTriggerId = triggerId;
5117 } else {
5118 request->mResultExtras.afTriggerId = triggerId;
5119 mCurrentAfTriggerId = triggerId;
5120 }
Emilian Peev7e25e5e2017-04-07 15:48:49 +01005121 continue;
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07005122 }
5123
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005124 camera_metadata_entry entry = metadata.find(tag);
5125
5126 if (entry.count > 0) {
5127 /**
5128 * Already has an entry for this trigger in the request.
5129 * Rewrite it with our requested trigger value.
5130 */
5131 RequestTrigger oldTrigger = trigger;
5132
5133 oldTrigger.entryValue = entry.data.u8[0];
5134
5135 mTriggerReplacedMap.add(tag, oldTrigger);
5136 } else {
5137 /**
5138 * More typical, no trigger entry, so we just add it
5139 */
5140 mTriggerRemovedMap.add(tag, trigger);
5141 }
5142
5143 status_t res;
5144
5145 switch (trigger.getTagType()) {
5146 case TYPE_BYTE: {
5147 uint8_t entryValue = static_cast<uint8_t>(trigger.entryValue);
5148 res = metadata.update(tag,
5149 &entryValue,
5150 /*count*/1);
5151 break;
5152 }
5153 case TYPE_INT32:
5154 res = metadata.update(tag,
5155 &trigger.entryValue,
5156 /*count*/1);
5157 break;
5158 default:
5159 ALOGE("%s: Type not supported: 0x%x",
5160 __FUNCTION__,
5161 trigger.getTagType());
5162 return INVALID_OPERATION;
5163 }
5164
5165 if (res != OK) {
5166 ALOGE("%s: Failed to update request metadata with trigger tag %s"
5167 ", value %d", __FUNCTION__, trigger.getTagName(),
5168 trigger.entryValue);
5169 return res;
5170 }
5171
5172 ALOGV("%s: Mixed in trigger %s, value %d", __FUNCTION__,
5173 trigger.getTagName(),
5174 trigger.entryValue);
5175 }
5176
5177 mTriggerMap.clear();
5178
5179 return count;
5180}
5181
5182status_t Camera3Device::RequestThread::removeTriggers(
5183 const sp<CaptureRequest> &request) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005184 ATRACE_CALL();
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005185 Mutex::Autolock al(mTriggerMutex);
5186
Emilian Peevaebbe412018-01-15 13:53:24 +00005187 CameraMetadata &metadata = request->mSettingsList.begin()->metadata;
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005188
5189 /**
5190 * Replace all old entries with their old values.
5191 */
5192 for (size_t i = 0; i < mTriggerReplacedMap.size(); ++i) {
5193 RequestTrigger trigger = mTriggerReplacedMap.valueAt(i);
5194
5195 status_t res;
5196
5197 uint32_t tag = trigger.metadataTag;
5198 switch (trigger.getTagType()) {
5199 case TYPE_BYTE: {
5200 uint8_t entryValue = static_cast<uint8_t>(trigger.entryValue);
5201 res = metadata.update(tag,
5202 &entryValue,
5203 /*count*/1);
5204 break;
5205 }
5206 case TYPE_INT32:
5207 res = metadata.update(tag,
5208 &trigger.entryValue,
5209 /*count*/1);
5210 break;
5211 default:
5212 ALOGE("%s: Type not supported: 0x%x",
5213 __FUNCTION__,
5214 trigger.getTagType());
5215 return INVALID_OPERATION;
5216 }
5217
5218 if (res != OK) {
5219 ALOGE("%s: Failed to restore request metadata with trigger tag %s"
5220 ", trigger value %d", __FUNCTION__,
5221 trigger.getTagName(), trigger.entryValue);
5222 return res;
5223 }
5224 }
5225 mTriggerReplacedMap.clear();
5226
5227 /**
5228 * Remove all new entries.
5229 */
5230 for (size_t i = 0; i < mTriggerRemovedMap.size(); ++i) {
5231 RequestTrigger trigger = mTriggerRemovedMap.valueAt(i);
5232 status_t res = metadata.erase(trigger.metadataTag);
5233
5234 if (res != OK) {
5235 ALOGE("%s: Failed to erase metadata with trigger tag %s"
5236 ", trigger value %d", __FUNCTION__,
5237 trigger.getTagName(), trigger.entryValue);
5238 return res;
5239 }
5240 }
5241 mTriggerRemovedMap.clear();
5242
5243 return OK;
5244}
5245
Eino-Ville Talvala2f876f92013-09-13 11:39:24 -07005246status_t Camera3Device::RequestThread::addDummyTriggerIds(
5247 const sp<CaptureRequest> &request) {
Eino-Ville Talvalad309fb92015-11-25 12:12:45 -08005248 // Trigger ID 0 had special meaning in the HAL2 spec, so avoid it here
Eino-Ville Talvala2f876f92013-09-13 11:39:24 -07005249 static const int32_t dummyTriggerId = 1;
5250 status_t res;
5251
Emilian Peevaebbe412018-01-15 13:53:24 +00005252 CameraMetadata &metadata = request->mSettingsList.begin()->metadata;
Eino-Ville Talvala2f876f92013-09-13 11:39:24 -07005253
5254 // If AF trigger is active, insert a dummy AF trigger ID if none already
5255 // exists
5256 camera_metadata_entry afTrigger = metadata.find(ANDROID_CONTROL_AF_TRIGGER);
5257 camera_metadata_entry afId = metadata.find(ANDROID_CONTROL_AF_TRIGGER_ID);
5258 if (afTrigger.count > 0 &&
5259 afTrigger.data.u8[0] != ANDROID_CONTROL_AF_TRIGGER_IDLE &&
5260 afId.count == 0) {
5261 res = metadata.update(ANDROID_CONTROL_AF_TRIGGER_ID, &dummyTriggerId, 1);
5262 if (res != OK) return res;
5263 }
5264
5265 // If AE precapture trigger is active, insert a dummy precapture trigger ID
5266 // if none already exists
5267 camera_metadata_entry pcTrigger =
5268 metadata.find(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER);
5269 camera_metadata_entry pcId = metadata.find(ANDROID_CONTROL_AE_PRECAPTURE_ID);
5270 if (pcTrigger.count > 0 &&
5271 pcTrigger.data.u8[0] != ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE &&
5272 pcId.count == 0) {
5273 res = metadata.update(ANDROID_CONTROL_AE_PRECAPTURE_ID,
5274 &dummyTriggerId, 1);
5275 if (res != OK) return res;
5276 }
5277
5278 return OK;
5279}
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005280
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005281/**
5282 * PreparerThread inner class methods
5283 */
5284
5285Camera3Device::PreparerThread::PreparerThread() :
Eino-Ville Talvala77c1a352016-06-13 12:32:43 -07005286 Thread(/*canCallJava*/false), mListener(nullptr),
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005287 mActive(false), mCancelNow(false), mCurrentMaxCount(0), mCurrentPrepareComplete(false) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005288}
5289
5290Camera3Device::PreparerThread::~PreparerThread() {
5291 Thread::requestExitAndWait();
5292 if (mCurrentStream != nullptr) {
5293 mCurrentStream->cancelPrepare();
5294 ATRACE_ASYNC_END("stream prepare", mCurrentStream->getId());
5295 mCurrentStream.clear();
5296 }
5297 clear();
5298}
5299
Ruben Brunkc78ac262015-08-13 17:58:46 -07005300status_t Camera3Device::PreparerThread::prepare(int maxCount, sp<Camera3StreamInterface>& stream) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005301 ATRACE_CALL();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005302 status_t res;
5303
5304 Mutex::Autolock l(mLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005305 sp<NotificationListener> listener = mListener.promote();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005306
Shuzhen Wangb3a0fb52018-09-13 17:24:08 -07005307 res = stream->startPrepare(maxCount, true /*blockRequest*/);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005308 if (res == OK) {
5309 // No preparation needed, fire listener right off
5310 ALOGV("%s: Stream %d already prepared", __FUNCTION__, stream->getId());
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005311 if (listener != NULL) {
5312 listener->notifyPrepared(stream->getId());
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005313 }
5314 return OK;
5315 } else if (res != NOT_ENOUGH_DATA) {
5316 return res;
5317 }
5318
5319 // Need to prepare, start up thread if necessary
5320 if (!mActive) {
5321 // mRunning will change to false before the thread fully shuts down, so wait to be sure it
5322 // isn't running
5323 Thread::requestExitAndWait();
5324 res = Thread::run("C3PrepThread", PRIORITY_BACKGROUND);
5325 if (res != OK) {
5326 ALOGE("%s: Unable to start preparer stream: %d (%s)", __FUNCTION__, res, strerror(-res));
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005327 if (listener != NULL) {
5328 listener->notifyPrepared(stream->getId());
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005329 }
5330 return res;
5331 }
5332 mCancelNow = false;
5333 mActive = true;
5334 ALOGV("%s: Preparer stream started", __FUNCTION__);
5335 }
5336
5337 // queue up the work
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005338 mPendingStreams.emplace(maxCount, stream);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005339 ALOGV("%s: Stream %d queued for preparing", __FUNCTION__, stream->getId());
5340
5341 return OK;
5342}
5343
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005344void Camera3Device::PreparerThread::pause() {
5345 ATRACE_CALL();
5346
5347 Mutex::Autolock l(mLock);
5348
5349 std::unordered_map<int, sp<camera3::Camera3StreamInterface> > pendingStreams;
5350 pendingStreams.insert(mPendingStreams.begin(), mPendingStreams.end());
5351 sp<camera3::Camera3StreamInterface> currentStream = mCurrentStream;
5352 int currentMaxCount = mCurrentMaxCount;
5353 mPendingStreams.clear();
5354 mCancelNow = true;
5355 while (mActive) {
5356 auto res = mThreadActiveSignal.waitRelative(mLock, kActiveTimeout);
5357 if (res == TIMED_OUT) {
5358 ALOGE("%s: Timed out waiting on prepare thread!", __FUNCTION__);
5359 return;
5360 } else if (res != OK) {
5361 ALOGE("%s: Encountered an error: %d waiting on prepare thread!", __FUNCTION__, res);
5362 return;
5363 }
5364 }
5365
5366 //Check whether the prepare thread was able to complete the current
5367 //stream. In case work is still pending emplace it along with the rest
5368 //of the streams in the pending list.
5369 if (currentStream != nullptr) {
5370 if (!mCurrentPrepareComplete) {
5371 pendingStreams.emplace(currentMaxCount, currentStream);
5372 }
5373 }
5374
5375 mPendingStreams.insert(pendingStreams.begin(), pendingStreams.end());
5376 for (const auto& it : mPendingStreams) {
5377 it.second->cancelPrepare();
5378 }
5379}
5380
5381status_t Camera3Device::PreparerThread::resume() {
5382 ATRACE_CALL();
5383 status_t res;
5384
5385 Mutex::Autolock l(mLock);
5386 sp<NotificationListener> listener = mListener.promote();
5387
5388 if (mActive) {
5389 ALOGE("%s: Trying to resume an already active prepare thread!", __FUNCTION__);
5390 return NO_INIT;
5391 }
5392
5393 auto it = mPendingStreams.begin();
5394 for (; it != mPendingStreams.end();) {
Shuzhen Wangb3a0fb52018-09-13 17:24:08 -07005395 res = it->second->startPrepare(it->first, true /*blockRequest*/);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005396 if (res == OK) {
5397 if (listener != NULL) {
5398 listener->notifyPrepared(it->second->getId());
5399 }
5400 it = mPendingStreams.erase(it);
5401 } else if (res != NOT_ENOUGH_DATA) {
5402 ALOGE("%s: Unable to start preparer stream: %d (%s)", __FUNCTION__,
5403 res, strerror(-res));
5404 it = mPendingStreams.erase(it);
5405 } else {
5406 it++;
5407 }
5408 }
5409
5410 if (mPendingStreams.empty()) {
5411 return OK;
5412 }
5413
5414 res = Thread::run("C3PrepThread", PRIORITY_BACKGROUND);
5415 if (res != OK) {
5416 ALOGE("%s: Unable to start preparer stream: %d (%s)",
5417 __FUNCTION__, res, strerror(-res));
5418 return res;
5419 }
5420 mCancelNow = false;
5421 mActive = true;
5422 ALOGV("%s: Preparer stream started", __FUNCTION__);
5423
5424 return OK;
5425}
5426
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005427status_t Camera3Device::PreparerThread::clear() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005428 ATRACE_CALL();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005429 Mutex::Autolock l(mLock);
5430
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005431 for (const auto& it : mPendingStreams) {
5432 it.second->cancelPrepare();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005433 }
5434 mPendingStreams.clear();
5435 mCancelNow = true;
5436
5437 return OK;
5438}
5439
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005440void Camera3Device::PreparerThread::setNotificationListener(wp<NotificationListener> listener) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005441 ATRACE_CALL();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005442 Mutex::Autolock l(mLock);
5443 mListener = listener;
5444}
5445
5446bool Camera3Device::PreparerThread::threadLoop() {
5447 status_t res;
5448 {
5449 Mutex::Autolock l(mLock);
5450 if (mCurrentStream == nullptr) {
5451 // End thread if done with work
5452 if (mPendingStreams.empty()) {
5453 ALOGV("%s: Preparer stream out of work", __FUNCTION__);
5454 // threadLoop _must not_ re-acquire mLock after it sets mActive to false; would
5455 // cause deadlock with prepare()'s requestExitAndWait triggered by !mActive.
5456 mActive = false;
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005457 mThreadActiveSignal.signal();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005458 return false;
5459 }
5460
5461 // Get next stream to prepare
5462 auto it = mPendingStreams.begin();
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005463 mCurrentStream = it->second;
5464 mCurrentMaxCount = it->first;
5465 mCurrentPrepareComplete = false;
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005466 mPendingStreams.erase(it);
5467 ATRACE_ASYNC_BEGIN("stream prepare", mCurrentStream->getId());
5468 ALOGV("%s: Preparing stream %d", __FUNCTION__, mCurrentStream->getId());
5469 } else if (mCancelNow) {
5470 mCurrentStream->cancelPrepare();
5471 ATRACE_ASYNC_END("stream prepare", mCurrentStream->getId());
5472 ALOGV("%s: Cancelling stream %d prepare", __FUNCTION__, mCurrentStream->getId());
5473 mCurrentStream.clear();
5474 mCancelNow = false;
5475 return true;
5476 }
5477 }
5478
5479 res = mCurrentStream->prepareNextBuffer();
5480 if (res == NOT_ENOUGH_DATA) return true;
5481 if (res != OK) {
5482 // Something bad happened; try to recover by cancelling prepare and
5483 // signalling listener anyway
5484 ALOGE("%s: Stream %d returned error %d (%s) during prepare", __FUNCTION__,
5485 mCurrentStream->getId(), res, strerror(-res));
5486 mCurrentStream->cancelPrepare();
5487 }
5488
5489 // This stream has finished, notify listener
5490 Mutex::Autolock l(mLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005491 sp<NotificationListener> listener = mListener.promote();
5492 if (listener != NULL) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005493 ALOGV("%s: Stream %d prepare done, signaling listener", __FUNCTION__,
5494 mCurrentStream->getId());
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005495 listener->notifyPrepared(mCurrentStream->getId());
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005496 }
5497
5498 ATRACE_ASYNC_END("stream prepare", mCurrentStream->getId());
5499 mCurrentStream.clear();
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005500 mCurrentPrepareComplete = true;
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005501
5502 return true;
5503}
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005504
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005505status_t Camera3Device::RequestBufferStateMachine::initialize(
5506 sp<camera3::StatusTracker> statusTracker) {
5507 if (statusTracker == nullptr) {
5508 ALOGE("%s: statusTracker is null", __FUNCTION__);
5509 return BAD_VALUE;
5510 }
5511
5512 std::lock_guard<std::mutex> lock(mLock);
5513 mStatusTracker = statusTracker;
5514 mRequestBufferStatusId = statusTracker->addComponent();
5515 return OK;
5516}
5517
5518bool Camera3Device::RequestBufferStateMachine::startRequestBuffer() {
5519 std::lock_guard<std::mutex> lock(mLock);
Yin-Chia Yeh8a4ccb02018-11-16 15:43:36 -08005520 if (mStatus == RB_STATUS_READY || mStatus == RB_STATUS_PENDING_STOP) {
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005521 mRequestBufferOngoing = true;
Yin-Chia Yeh8a4ccb02018-11-16 15:43:36 -08005522 notifyTrackerLocked(/*active*/true);
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005523 return true;
5524 }
5525 return false;
5526}
5527
5528void Camera3Device::RequestBufferStateMachine::endRequestBuffer() {
5529 std::lock_guard<std::mutex> lock(mLock);
5530 if (!mRequestBufferOngoing) {
5531 ALOGE("%s called without a successful startRequestBuffer call first!", __FUNCTION__);
5532 return;
5533 }
5534 mRequestBufferOngoing = false;
5535 if (mStatus == RB_STATUS_PENDING_STOP) {
5536 checkSwitchToStopLocked();
5537 }
Yin-Chia Yeh8a4ccb02018-11-16 15:43:36 -08005538 notifyTrackerLocked(/*active*/false);
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005539}
5540
5541void Camera3Device::RequestBufferStateMachine::onStreamsConfigured() {
5542 std::lock_guard<std::mutex> lock(mLock);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005543 mSwitchedToOffline = false;
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005544 mStatus = RB_STATUS_READY;
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005545 return;
5546}
5547
Yin-Chia Yehcd333fe2019-02-08 13:45:41 -08005548void Camera3Device::RequestBufferStateMachine::onSubmittingRequest() {
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005549 std::lock_guard<std::mutex> lock(mLock);
5550 mRequestThreadPaused = false;
Yin-Chia Yehcd333fe2019-02-08 13:45:41 -08005551 // inflight map register actually happens in prepareHalRequest now, but it is close enough
5552 // approximation.
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005553 mInflightMapEmpty = false;
5554 if (mStatus == RB_STATUS_STOPPED) {
5555 mStatus = RB_STATUS_READY;
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005556 }
5557 return;
5558}
5559
5560void Camera3Device::RequestBufferStateMachine::onRequestThreadPaused() {
5561 std::lock_guard<std::mutex> lock(mLock);
5562 mRequestThreadPaused = true;
5563 if (mStatus == RB_STATUS_PENDING_STOP) {
5564 checkSwitchToStopLocked();
5565 }
5566 return;
5567}
5568
5569void Camera3Device::RequestBufferStateMachine::onInflightMapEmpty() {
5570 std::lock_guard<std::mutex> lock(mLock);
5571 mInflightMapEmpty = true;
5572 if (mStatus == RB_STATUS_PENDING_STOP) {
5573 checkSwitchToStopLocked();
5574 }
5575 return;
5576}
5577
5578void Camera3Device::RequestBufferStateMachine::onWaitUntilIdle() {
5579 std::lock_guard<std::mutex> lock(mLock);
5580 if (!checkSwitchToStopLocked()) {
5581 mStatus = RB_STATUS_PENDING_STOP;
5582 }
5583 return;
5584}
5585
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005586bool Camera3Device::RequestBufferStateMachine::onSwitchToOfflineSuccess() {
5587 std::lock_guard<std::mutex> lock(mLock);
5588 if (mRequestBufferOngoing) {
5589 ALOGE("%s: HAL must not be requesting buffer after HAL returns switchToOffline!",
5590 __FUNCTION__);
5591 return false;
5592 }
5593 mSwitchedToOffline = true;
5594 mInflightMapEmpty = true;
5595 mRequestThreadPaused = true;
5596 mStatus = RB_STATUS_STOPPED;
5597 return true;
5598}
5599
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005600void Camera3Device::RequestBufferStateMachine::notifyTrackerLocked(bool active) {
5601 sp<StatusTracker> statusTracker = mStatusTracker.promote();
5602 if (statusTracker != nullptr) {
5603 if (active) {
5604 statusTracker->markComponentActive(mRequestBufferStatusId);
5605 } else {
5606 statusTracker->markComponentIdle(mRequestBufferStatusId, Fence::NO_FENCE);
5607 }
5608 }
5609}
5610
5611bool Camera3Device::RequestBufferStateMachine::checkSwitchToStopLocked() {
5612 if (mInflightMapEmpty && mRequestThreadPaused && !mRequestBufferOngoing) {
5613 mStatus = RB_STATUS_STOPPED;
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005614 return true;
5615 }
5616 return false;
5617}
5618
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005619bool Camera3Device::startRequestBuffer() {
5620 return mRequestBufferSM.startRequestBuffer();
5621}
Shuzhen Wang268a1362018-10-16 16:32:59 -07005622
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005623void Camera3Device::endRequestBuffer() {
5624 mRequestBufferSM.endRequestBuffer();
5625}
Shuzhen Wang268a1362018-10-16 16:32:59 -07005626
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005627nsecs_t Camera3Device::getWaitDuration() {
5628 return kBaseGetBufferWait + getExpectedInFlightDuration();
5629}
Shuzhen Wang268a1362018-10-16 16:32:59 -07005630
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005631void Camera3Device::getInflightBufferKeys(std::vector<std::pair<int32_t, int32_t>>* out) {
5632 mInterface->getInflightBufferKeys(out);
5633}
Shuzhen Wang268a1362018-10-16 16:32:59 -07005634
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005635void Camera3Device::getInflightRequestBufferKeys(std::vector<uint64_t>* out) {
5636 mInterface->getInflightRequestBufferKeys(out);
5637}
Shuzhen Wang268a1362018-10-16 16:32:59 -07005638
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005639std::vector<sp<Camera3StreamInterface>> Camera3Device::getAllStreams() {
5640 std::vector<sp<Camera3StreamInterface>> ret;
5641 bool hasInputStream = mInputStream != nullptr;
5642 ret.reserve(mOutputStreams.size() + mDeletedStreams.size() + ((hasInputStream) ? 1 : 0));
5643 if (hasInputStream) {
5644 ret.push_back(mInputStream);
Shuzhen Wang268a1362018-10-16 16:32:59 -07005645 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005646 for (size_t i = 0; i < mOutputStreams.size(); i++) {
5647 ret.push_back(mOutputStreams[i]);
5648 }
5649 for (size_t i = 0; i < mDeletedStreams.size(); i++) {
5650 ret.push_back(mDeletedStreams[i]);
5651 }
5652 return ret;
Shuzhen Wang268a1362018-10-16 16:32:59 -07005653}
5654
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005655status_t Camera3Device::switchToOffline(
5656 const std::vector<int32_t>& streamsToKeep,
5657 /*out*/ sp<CameraOfflineSessionBase>* session) {
5658 ATRACE_CALL();
5659 if (session == nullptr) {
5660 ALOGE("%s: session must not be null", __FUNCTION__);
5661 return BAD_VALUE;
5662 }
5663
5664 Mutex::Autolock il(mInterfaceLock);
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005665
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005666 bool hasInputStream = mInputStream != nullptr;
5667 int32_t inputStreamId = hasInputStream ? mInputStream->getId() : -1;
5668 bool inputStreamSupportsOffline = hasInputStream ?
5669 mInputStream->getOfflineProcessingSupport() : false;
5670 auto outputStreamIds = mOutputStreams.getStreamIds();
5671 auto streamIds = outputStreamIds;
5672 if (hasInputStream) {
5673 streamIds.push_back(mInputStream->getId());
5674 }
5675
5676 // Check all streams in streamsToKeep supports offline mode
5677 for (auto id : streamsToKeep) {
5678 if (std::find(streamIds.begin(), streamIds.end(), id) == streamIds.end()) {
5679 ALOGE("%s: Unknown stream ID %d", __FUNCTION__, id);
5680 return BAD_VALUE;
5681 } else if (id == inputStreamId) {
5682 if (!inputStreamSupportsOffline) {
5683 ALOGE("%s: input stream %d cannot be switched to offline",
5684 __FUNCTION__, id);
5685 return BAD_VALUE;
5686 }
5687 } else {
5688 sp<camera3::Camera3OutputStreamInterface> stream = mOutputStreams.get(id);
5689 if (!stream->getOfflineProcessingSupport()) {
5690 ALOGE("%s: output stream %d cannot be switched to offline",
5691 __FUNCTION__, id);
5692 return BAD_VALUE;
5693 }
5694 }
5695 }
5696
5697 // TODO: block surface sharing and surface group streams until we can support them
5698
5699 // Stop repeating request, wait until all remaining requests are submitted, then call into
5700 // HAL switchToOffline
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005701 hardware::camera::device::V3_6::CameraOfflineSessionInfo offlineSessionInfo;
5702 sp<hardware::camera::device::V3_6::ICameraOfflineSession> offlineSession;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005703 camera3::BufferRecords bufferRecords;
5704 status_t ret = mRequestThread->switchToOffline(
5705 streamsToKeep, &offlineSessionInfo, &offlineSession, &bufferRecords);
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005706
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005707 if (ret != OK) {
5708 SET_ERR("Switch to offline failed: %s (%d)", strerror(-ret), ret);
5709 return ret;
5710 }
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005711
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005712 bool succ = mRequestBufferSM.onSwitchToOfflineSuccess();
5713 if (!succ) {
5714 SET_ERR("HAL must not be calling requestStreamBuffers call");
5715 // TODO: block ALL callbacks from HAL till app configured new streams?
5716 return UNKNOWN_ERROR;
5717 }
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005718
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005719 // Verify offlineSessionInfo
5720 std::vector<int32_t> offlineStreamIds;
5721 offlineStreamIds.reserve(offlineSessionInfo.offlineStreams.size());
5722 for (auto offlineStream : offlineSessionInfo.offlineStreams) {
5723 // verify stream IDs
5724 int32_t id = offlineStream.id;
5725 if (std::find(streamIds.begin(), streamIds.end(), id) == streamIds.end()) {
5726 SET_ERR("stream ID %d not found!", id);
5727 return UNKNOWN_ERROR;
5728 }
5729
5730 // When not using HAL buf manager, only allow streams requested by app to be preserved
5731 if (!mUseHalBufManager) {
5732 if (std::find(streamsToKeep.begin(), streamsToKeep.end(), id) == streamsToKeep.end()) {
5733 SET_ERR("stream ID %d must not be switched to offline!", id);
5734 return UNKNOWN_ERROR;
5735 }
5736 }
5737
5738 offlineStreamIds.push_back(id);
5739 sp<Camera3StreamInterface> stream = (id == inputStreamId) ?
5740 static_cast<sp<Camera3StreamInterface>>(mInputStream) :
5741 static_cast<sp<Camera3StreamInterface>>(mOutputStreams.get(id));
5742 // Verify number of outstanding buffers
5743 if (stream->getOutstandingBuffersCount() != offlineStream.numOutstandingBuffers) {
5744 SET_ERR("Offline stream %d # of remaining buffer mismatch: (%zu,%d) (service/HAL)",
5745 id, stream->getOutstandingBuffersCount(), offlineStream.numOutstandingBuffers);
5746 return UNKNOWN_ERROR;
5747 }
5748 }
5749
5750 // Verify all streams to be deleted don't have any outstanding buffers
5751 if (hasInputStream && std::find(offlineStreamIds.begin(), offlineStreamIds.end(),
5752 inputStreamId) == offlineStreamIds.end()) {
5753 if (mInputStream->hasOutstandingBuffers()) {
5754 SET_ERR("Input stream %d still has %zu outstanding buffer!",
5755 inputStreamId, mInputStream->getOutstandingBuffersCount());
5756 return UNKNOWN_ERROR;
5757 }
5758 }
5759
5760 for (const auto& outStreamId : outputStreamIds) {
5761 if (std::find(offlineStreamIds.begin(), offlineStreamIds.end(),
5762 outStreamId) == offlineStreamIds.end()) {
5763 auto outStream = mOutputStreams.get(outStreamId);
5764 if (outStream->hasOutstandingBuffers()) {
5765 SET_ERR("Output stream %d still has %zu outstanding buffer!",
5766 outStreamId, outStream->getOutstandingBuffersCount());
5767 return UNKNOWN_ERROR;
5768 }
5769 }
5770 }
5771
5772 InFlightRequestMap offlineReqs;
5773 // Verify inflight requests and their pending buffers
5774 {
5775 std::lock_guard<std::mutex> l(mInFlightLock);
5776 for (auto offlineReq : offlineSessionInfo.offlineRequests) {
5777 int idx = mInFlightMap.indexOfKey(offlineReq.frameNumber);
5778 if (idx == NAME_NOT_FOUND) {
5779 SET_ERR("Offline request frame number %d not found!", offlineReq.frameNumber);
5780 return UNKNOWN_ERROR;
5781 }
5782
5783 const auto& inflightReq = mInFlightMap.valueAt(idx);
5784 // TODO: check specific stream IDs
5785 size_t numBuffersLeft = static_cast<size_t>(inflightReq.numBuffersLeft);
5786 if (numBuffersLeft != offlineReq.pendingStreams.size()) {
5787 SET_ERR("Offline request # of remaining buffer mismatch: (%d,%d) (service/HAL)",
5788 inflightReq.numBuffersLeft, offlineReq.pendingStreams.size());
5789 return UNKNOWN_ERROR;
5790 }
5791 offlineReqs.add(offlineReq.frameNumber, inflightReq);
5792 }
5793 }
5794
5795 // Create Camera3OfflineSession and transfer object ownership
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005796 // (streams, inflight requests, buffer caches)
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005797 camera3::StreamSet offlineStreamSet;
5798 sp<camera3::Camera3Stream> inputStream;
5799 for (auto offlineStream : offlineSessionInfo.offlineStreams) {
5800 int32_t id = offlineStream.id;
5801 if (mInputStream != nullptr && id == mInputStream->getId()) {
5802 inputStream = mInputStream;
5803 } else {
5804 offlineStreamSet.add(id, mOutputStreams.get(id));
5805 }
5806 }
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005807
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005808 // TODO: check if we need to lock before copying states
5809 // though technically no other thread should be talking to Camera3Device at this point
5810 Camera3OfflineStates offlineStates(
5811 mTagMonitor, mVendorTagId, mUseHalBufManager, mNeedFixupMonochromeTags,
5812 mUsePartialResult, mNumPartialResults, mNextResultFrameNumber,
5813 mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
5814 mNextShutterFrameNumber, mNextReprocessShutterFrameNumber,
5815 mNextZslStillShutterFrameNumber, mDeviceInfo, mPhysicalDeviceInfoMap,
5816 mDistortionMappers, mZoomRatioMappers);
5817
5818 *session = new Camera3OfflineSession(mId, inputStream, offlineStreamSet,
5819 std::move(bufferRecords), offlineReqs, offlineStates, offlineSession);
5820
5821 // Delete all streams that has been transferred to offline session
5822 Mutex::Autolock l(mLock);
5823 for (auto offlineStream : offlineSessionInfo.offlineStreams) {
5824 int32_t id = offlineStream.id;
5825 if (mInputStream != nullptr && id == mInputStream->getId()) {
5826 mInputStream.clear();
5827 } else {
5828 mOutputStreams.remove(id);
5829 }
5830 }
5831
5832 // disconnect all other streams and switch to UNCONFIGURED state
5833 if (mInputStream != nullptr) {
5834 ret = mInputStream->disconnect();
5835 if (ret != OK) {
5836 SET_ERR_L("disconnect input stream failed!");
5837 return UNKNOWN_ERROR;
5838 }
5839 }
5840
5841 for (auto streamId : mOutputStreams.getStreamIds()) {
5842 sp<Camera3StreamInterface> stream = mOutputStreams.get(streamId);
5843 ret = stream->disconnect();
5844 if (ret != OK) {
5845 SET_ERR_L("disconnect output stream %d failed!", streamId);
5846 return UNKNOWN_ERROR;
5847 }
5848 }
5849
5850 mInputStream.clear();
5851 mOutputStreams.clear();
5852 mNeedConfig = true;
5853 internalUpdateStatusLocked(STATUS_UNCONFIGURED);
5854 mOperatingMode = NO_MODE;
5855 mIsConstrainedHighSpeedConfiguration = false;
5856
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005857 return OK;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005858 // TO be done by CameraDeviceClient/Camera3OfflineSession
5859 // register the offline client to camera service
5860 // Setup result passthing threads etc
5861 // Initialize offline session so HAL can start sending callback to it (result Fmq)
5862 // TODO: check how many onIdle callback will be sent
5863 // Java side to make sure the CameraCaptureSession is properly closed
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005864}
5865
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08005866}; // namespace android