blob: deeec7e8c13da41f1fd6bd5ed2d495856c05768f [file] [log] [blame]
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001/*
Shuzhen Wangc28189a2017-11-27 23:05:10 -08002 * Copyright (C) 2013-2018 The Android Open Source Project
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "Camera3-Device"
18#define ATRACE_TAG ATRACE_TAG_CAMERA
19//#define LOG_NDEBUG 0
20//#define LOG_NNDEBUG 0 // Per-frame verbose logging
21
22#ifdef LOG_NNDEBUG
23#define ALOGVV(...) ALOGV(__VA_ARGS__)
24#else
25#define ALOGVV(...) ((void)0)
26#endif
27
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -070028// Convenience macro for transient errors
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -080029#define CLOGE(fmt, ...) ALOGE("Camera %s: %s: " fmt, mId.string(), __FUNCTION__, \
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -070030 ##__VA_ARGS__)
31
Yin-Chia Yeh99fd0972019-06-27 14:22:44 -070032#define CLOGW(fmt, ...) ALOGW("Camera %s: %s: " fmt, mId.string(), __FUNCTION__, \
33 ##__VA_ARGS__)
34
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -070035// Convenience macros for transitioning to the error state
36#define SET_ERR(fmt, ...) setErrorState( \
37 "%s: " fmt, __FUNCTION__, \
38 ##__VA_ARGS__)
39#define SET_ERR_L(fmt, ...) setErrorStateLocked( \
40 "%s: " fmt, __FUNCTION__, \
41 ##__VA_ARGS__)
42
Colin Crosse5729fa2014-03-21 15:04:25 -070043#include <inttypes.h>
44
Shuzhen Wang5c22c152017-12-31 17:12:25 -080045#include <utility>
46
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -080047#include <utils/Log.h>
48#include <utils/Trace.h>
49#include <utils/Timers.h>
Zhijun He90f7c372016-08-16 16:19:43 -070050#include <cutils/properties.h>
Eino-Ville Talvala7b82efe2013-07-25 17:12:35 -070051
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -080052#include <android/hardware/camera2/ICameraDeviceUser.h>
53
Igor Murashkinff3e31d2013-10-23 16:40:06 -070054#include "utils/CameraTraces.h"
Eino-Ville Talvalaf99498e2015-09-25 16:52:55 -070055#include "mediautils/SchedulingPolicyService.h"
Eino-Ville Talvala7b82efe2013-07-25 17:12:35 -070056#include "device3/Camera3Device.h"
57#include "device3/Camera3OutputStream.h"
58#include "device3/Camera3InputStream.h"
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -070059#include "device3/Camera3DummyStream.h"
Shuzhen Wang0129d522016-10-30 22:43:41 -070060#include "device3/Camera3SharedOutputStream.h"
Eino-Ville Talvalaf67e23e2014-07-23 17:17:59 -070061#include "CameraService.h"
Jayant Chowdhary12361932018-08-27 14:46:13 -070062#include "utils/CameraThreadState.h"
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -080063
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -080064#include <algorithm>
Yin-Chia Yeh84be5782019-03-01 11:47:02 -080065#include <tuple>
66
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -080067using namespace android::camera3;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -080068using namespace android::hardware::camera;
69using namespace android::hardware::camera::device::V3_2;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -080070
71namespace android {
72
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -080073Camera3Device::Camera3Device(const String8 &id):
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -080074 mId(id),
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -080075 mOperatingMode(NO_MODE),
Eino-Ville Talvala9a179412015-06-09 13:15:16 -070076 mIsConstrainedHighSpeedConfiguration(false),
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -070077 mStatus(STATUS_UNINITIALIZED),
Ruben Brunk183f0562015-08-12 12:55:02 -070078 mStatusWaiters(0),
Zhijun He204e3292014-07-14 17:09:23 -070079 mUsePartialResult(false),
80 mNumPartialResults(1),
Shuzhen Wangc28dccc2016-02-11 23:48:46 -080081 mTimestampOffset(0),
Eino-Ville Talvala42368d92013-04-09 14:13:50 -070082 mNextResultFrameNumber(0),
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -070083 mNextReprocessResultFrameNumber(0),
Shuzhen Wang5ee99842019-04-12 11:55:48 -070084 mNextZslStillResultFrameNumber(0),
Eino-Ville Talvala42368d92013-04-09 14:13:50 -070085 mNextShutterFrameNumber(0),
Chien-Yu Chen3df11ce2015-09-30 14:13:30 -070086 mNextReprocessShutterFrameNumber(0),
Shuzhen Wang5ee99842019-04-12 11:55:48 -070087 mNextZslStillShutterFrameNumber(0),
Emilian Peev71c73a22017-03-21 16:35:51 +000088 mListener(NULL),
Emilian Peev811d2952018-05-25 11:08:40 +010089 mVendorTagId(CAMERA_METADATA_INVALID_VENDOR_ID),
Shuzhen Wang268a1362018-10-16 16:32:59 -070090 mLastTemplateId(-1),
91 mNeedFixupMonochromeTags(false)
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -080092{
93 ATRACE_CALL();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -080094 ALOGV("%s: Created device for camera %s", __FUNCTION__, mId.string());
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -080095}
96
97Camera3Device::~Camera3Device()
98{
99 ATRACE_CALL();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800100 ALOGV("%s: Tearing down for camera id %s", __FUNCTION__, mId.string());
Yin-Chia Yehc5248132018-08-15 12:19:20 -0700101 disconnectImpl();
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800102}
103
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800104const String8& Camera3Device::getId() const {
Igor Murashkin71381052013-03-04 14:53:08 -0800105 return mId;
106}
107
Emilian Peevbd8c5032018-02-14 23:05:40 +0000108status_t Camera3Device::initialize(sp<CameraProviderManager> manager, const String8& monitorTags) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800109 ATRACE_CALL();
110 Mutex::Autolock il(mInterfaceLock);
111 Mutex::Autolock l(mLock);
112
113 ALOGV("%s: Initializing HIDL device for camera %s", __FUNCTION__, mId.string());
114 if (mStatus != STATUS_UNINITIALIZED) {
115 CLOGE("Already initialized!");
116 return INVALID_OPERATION;
117 }
118 if (manager == nullptr) return INVALID_OPERATION;
119
120 sp<ICameraDeviceSession> session;
121 ATRACE_BEGIN("CameraHal::openSession");
Steven Moreland5ff9c912017-03-09 23:13:00 -0800122 status_t res = manager->openSession(mId.string(), this,
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800123 /*out*/ &session);
124 ATRACE_END();
125 if (res != OK) {
126 SET_ERR_L("Could not open camera session: %s (%d)", strerror(-res), res);
127 return res;
128 }
129
Steven Moreland5ff9c912017-03-09 23:13:00 -0800130 res = manager->getCameraCharacteristics(mId.string(), &mDeviceInfo);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800131 if (res != OK) {
Shuzhen Wang2e7f58f2018-07-11 14:00:29 -0700132 SET_ERR_L("Could not retrieve camera characteristics: %s (%d)", strerror(-res), res);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800133 session->close();
134 return res;
135 }
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -0800136 mSupportNativeZoomRatio = manager->supportNativeZoomRatio(mId.string());
Yin-Chia Yeh52778d42016-12-22 18:20:43 -0800137
Shuzhen Wang2e7f58f2018-07-11 14:00:29 -0700138 std::vector<std::string> physicalCameraIds;
Shuzhen Wang03d8cc12018-09-12 14:17:09 -0700139 bool isLogical = manager->isLogicalCamera(mId.string(), &physicalCameraIds);
Shuzhen Wang2e7f58f2018-07-11 14:00:29 -0700140 if (isLogical) {
141 for (auto& physicalId : physicalCameraIds) {
Shuzhen Wang4f6fa9d2019-03-29 10:40:35 -0700142 res = manager->getCameraCharacteristics(
143 physicalId, &mPhysicalDeviceInfoMap[physicalId]);
Shuzhen Wang2e7f58f2018-07-11 14:00:29 -0700144 if (res != OK) {
145 SET_ERR_L("Could not retrieve camera %s characteristics: %s (%d)",
146 physicalId.c_str(), strerror(-res), res);
147 session->close();
148 return res;
149 }
Shuzhen Wang4f6fa9d2019-03-29 10:40:35 -0700150
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -0800151 bool usePrecorrectArray =
152 DistortionMapper::isDistortionSupported(mPhysicalDeviceInfoMap[physicalId]);
153 if (usePrecorrectArray) {
154 res = mDistortionMappers[physicalId].setupStaticInfo(
155 mPhysicalDeviceInfoMap[physicalId]);
Shuzhen Wang4f6fa9d2019-03-29 10:40:35 -0700156 if (res != OK) {
157 SET_ERR_L("Unable to read camera %s's calibration fields for distortion "
158 "correction", physicalId.c_str());
159 session->close();
160 return res;
161 }
162 }
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -0800163
Shuzhen Wang1c834da2019-12-18 11:17:03 -0800164 mZoomRatioMappers[physicalId] = ZoomRatioMapper(
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -0800165 &mPhysicalDeviceInfoMap[physicalId],
166 mSupportNativeZoomRatio, usePrecorrectArray);
Shuzhen Wang2e7f58f2018-07-11 14:00:29 -0700167 }
168 }
169
Yifan Hongf79b5542017-04-11 14:44:25 -0700170 std::shared_ptr<RequestMetadataQueue> queue;
Yifan Honga640c5a2017-04-12 16:30:31 -0700171 auto requestQueueRet = session->getCaptureRequestMetadataQueue(
172 [&queue](const auto& descriptor) {
173 queue = std::make_shared<RequestMetadataQueue>(descriptor);
174 if (!queue->isValid() || queue->availableToWrite() <= 0) {
175 ALOGE("HAL returns empty request metadata fmq, not use it");
176 queue = nullptr;
177 // don't use the queue onwards.
178 }
179 });
180 if (!requestQueueRet.isOk()) {
181 ALOGE("Transaction error when getting request metadata fmq: %s, not use it",
182 requestQueueRet.description().c_str());
Eino-Ville Talvalac5cbb872017-04-27 12:48:33 -0700183 return DEAD_OBJECT;
Yifan Hongf79b5542017-04-11 14:44:25 -0700184 }
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700185
186 std::unique_ptr<ResultMetadataQueue>& resQueue = mResultMetadataQueue;
Yifan Honga640c5a2017-04-12 16:30:31 -0700187 auto resultQueueRet = session->getCaptureResultMetadataQueue(
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700188 [&resQueue](const auto& descriptor) {
189 resQueue = std::make_unique<ResultMetadataQueue>(descriptor);
190 if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
Yifan Honga640c5a2017-04-12 16:30:31 -0700191 ALOGE("HAL returns empty result metadata fmq, not use it");
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700192 resQueue = nullptr;
193 // Don't use the resQueue onwards.
Yifan Honga640c5a2017-04-12 16:30:31 -0700194 }
195 });
196 if (!resultQueueRet.isOk()) {
197 ALOGE("Transaction error when getting result metadata queue from camera session: %s",
198 resultQueueRet.description().c_str());
Eino-Ville Talvalac5cbb872017-04-27 12:48:33 -0700199 return DEAD_OBJECT;
Yifan Honga640c5a2017-04-12 16:30:31 -0700200 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -0700201 IF_ALOGV() {
202 session->interfaceChain([](
203 ::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
204 ALOGV("Session interface chain:");
Chih-Hung Hsieh3ef324d2018-12-11 11:48:12 -0800205 for (const auto& iface : interfaceChain) {
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -0700206 ALOGV(" %s", iface.c_str());
207 }
208 });
209 }
Yifan Hongf79b5542017-04-11 14:44:25 -0700210
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -0800211 camera_metadata_entry bufMgrMode =
212 mDeviceInfo.find(ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION);
213 if (bufMgrMode.count > 0) {
214 mUseHalBufManager = (bufMgrMode.data.u8[0] ==
215 ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5);
216 }
217
Yin-Chia Yehb978c382019-10-30 00:22:37 -0700218 camera_metadata_entry_t capabilities = mDeviceInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
219 for (size_t i = 0; i < capabilities.count; i++) {
220 uint8_t capability = capabilities.data.u8[i];
221 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_OFFLINE_PROCESSING) {
222 mSupportOfflineProcessing = true;
223 }
224 }
225
226 mInterface = new HalInterface(session, queue, mUseHalBufManager, mSupportOfflineProcessing);
Emilian Peev71c73a22017-03-21 16:35:51 +0000227 std::string providerType;
228 mVendorTagId = manager->getProviderTagIdLocked(mId.string());
Emilian Peevbd8c5032018-02-14 23:05:40 +0000229 mTagMonitor.initialize(mVendorTagId);
230 if (!monitorTags.isEmpty()) {
231 mTagMonitor.parseTagsToMonitor(String8(monitorTags));
232 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800233
Shuzhen Wang268a1362018-10-16 16:32:59 -0700234 // Metadata tags needs fixup for monochrome camera device version less
235 // than 3.5.
236 hardware::hidl_version maxVersion{0,0};
237 res = manager->getHighestSupportedVersion(mId.string(), &maxVersion);
238 if (res != OK) {
239 ALOGE("%s: Error in getting camera device version id: %s (%d)",
240 __FUNCTION__, strerror(-res), res);
241 return res;
242 }
243 int deviceVersion = HARDWARE_DEVICE_API_VERSION(
244 maxVersion.get_major(), maxVersion.get_minor());
245
246 bool isMonochrome = false;
Yin-Chia Yehb978c382019-10-30 00:22:37 -0700247 for (size_t i = 0; i < capabilities.count; i++) {
248 uint8_t capability = capabilities.data.u8[i];
Shuzhen Wang268a1362018-10-16 16:32:59 -0700249 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME) {
250 isMonochrome = true;
251 }
252 }
253 mNeedFixupMonochromeTags = (isMonochrome && deviceVersion < CAMERA_DEVICE_API_VERSION_3_5);
254
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800255 return initializeCommonLocked();
256}
257
258status_t Camera3Device::initializeCommonLocked() {
259
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700260 /** Start up status tracker thread */
261 mStatusTracker = new StatusTracker(this);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800262 status_t res = mStatusTracker->run(String8::format("C3Dev-%s-Status", mId.string()).string());
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700263 if (res != OK) {
264 SET_ERR_L("Unable to start status tracking thread: %s (%d)",
265 strerror(-res), res);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800266 mInterface->close();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700267 mStatusTracker.clear();
268 return res;
269 }
270
Eino-Ville Talvala24b366e2016-07-21 12:53:07 -0700271 /** Register in-flight map to the status tracker */
272 mInFlightStatusId = mStatusTracker->addComponent();
273
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -0700274 if (mUseHalBufManager) {
275 res = mRequestBufferSM.initialize(mStatusTracker);
276 if (res != OK) {
277 SET_ERR_L("Unable to start request buffer state machine: %s (%d)",
278 strerror(-res), res);
279 mInterface->close();
280 mStatusTracker.clear();
281 return res;
282 }
283 }
284
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -0800285 /** Create buffer manager */
286 mBufferManager = new Camera3BufferManager();
287
288 Vector<int32_t> sessionParamKeys;
289 camera_metadata_entry_t sessionKeysEntry = mDeviceInfo.find(
290 ANDROID_REQUEST_AVAILABLE_SESSION_KEYS);
291 if (sessionKeysEntry.count > 0) {
292 sessionParamKeys.insertArrayAt(sessionKeysEntry.data.i32, 0, sessionKeysEntry.count);
293 }
294
Chien-Yu Chenab5135b2015-06-30 11:20:58 -0700295 /** Start up request queue thread */
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -0700296 mRequestThread = new RequestThread(
297 this, mStatusTracker, mInterface, sessionParamKeys, mUseHalBufManager);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800298 res = mRequestThread->run(String8::format("C3Dev-%s-ReqQueue", mId.string()).string());
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800299 if (res != OK) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -0700300 SET_ERR_L("Unable to start request queue thread: %s (%d)",
301 strerror(-res), res);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800302 mInterface->close();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800303 mRequestThread.clear();
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800304 return res;
305 }
306
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -0700307 mPreparerThread = new PreparerThread();
308
Ruben Brunk183f0562015-08-12 12:55:02 -0700309 internalUpdateStatusLocked(STATUS_UNCONFIGURED);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800310 mNextStreamId = 0;
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -0700311 mDummyStreamId = NO_STREAM;
Eino-Ville Talvalaea26c772013-06-11 16:04:06 -0700312 mNeedConfig = true;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700313 mPauseStateNotify = false;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800314
Shuzhen Wangc28dccc2016-02-11 23:48:46 -0800315 // Measure the clock domain offset between camera and video/hw_composer
316 camera_metadata_entry timestampSource =
317 mDeviceInfo.find(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE);
318 if (timestampSource.count > 0 && timestampSource.data.u8[0] ==
319 ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME) {
320 mTimestampOffset = getMonoToBoottimeOffset();
321 }
322
Eino-Ville Talvalafd6ecdd2013-10-11 09:51:09 -0700323 // Will the HAL be sending in early partial result metadata?
Emilian Peev08dd2452017-04-06 16:55:14 +0100324 camera_metadata_entry partialResultsCount =
325 mDeviceInfo.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
326 if (partialResultsCount.count > 0) {
327 mNumPartialResults = partialResultsCount.data.i32[0];
328 mUsePartialResult = (mNumPartialResults > 1);
Eino-Ville Talvalafd6ecdd2013-10-11 09:51:09 -0700329 }
330
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700331 camera_metadata_entry configs =
332 mDeviceInfo.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
333 for (uint32_t i = 0; i < configs.count; i += 4) {
334 if (configs.data.i32[i] == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED &&
335 configs.data.i32[i + 3] ==
336 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT) {
337 mSupportedOpaqueInputSizes.add(Size(configs.data.i32[i + 1],
338 configs.data.i32[i + 2]));
339 }
340 }
341
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -0800342 bool usePrecorrectArray = DistortionMapper::isDistortionSupported(mDeviceInfo);
343 if (usePrecorrectArray) {
Shuzhen Wang4f6fa9d2019-03-29 10:40:35 -0700344 res = mDistortionMappers[mId.c_str()].setupStaticInfo(mDeviceInfo);
Eino-Ville Talvala7b8a1fd2018-05-22 15:30:35 -0700345 if (res != OK) {
346 SET_ERR_L("Unable to read necessary calibration fields for distortion correction");
347 return res;
348 }
349 }
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -0800350
Shuzhen Wang1c834da2019-12-18 11:17:03 -0800351 mZoomRatioMappers[mId.c_str()] = ZoomRatioMapper(&mDeviceInfo,
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -0800352 mSupportNativeZoomRatio, usePrecorrectArray);
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -0800353
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -0800354 if (RotateAndCropMapper::isNeeded(&mDeviceInfo)) {
355 mRotateAndCropMappers.emplace(mId.c_str(), &mDeviceInfo);
356 }
357
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800358 return OK;
359}
360
361status_t Camera3Device::disconnect() {
Yin-Chia Yehc5248132018-08-15 12:19:20 -0700362 return disconnectImpl();
363}
364
365status_t Camera3Device::disconnectImpl() {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800366 ATRACE_CALL();
Yin-Chia Yehe1c80632016-08-08 14:48:05 -0700367 ALOGI("%s: E", __FUNCTION__);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800368
Eino-Ville Talvala214a17f2013-06-13 12:20:02 -0700369 status_t res = OK;
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700370 std::vector<wp<Camera3StreamInterface>> streams;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700371 {
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800372 Mutex::Autolock il(mInterfaceLock);
373 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
374 {
375 Mutex::Autolock l(mLock);
376 if (mStatus == STATUS_UNINITIALIZED) return res;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700377
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800378 if (mStatus == STATUS_ACTIVE ||
379 (mStatus == STATUS_ERROR && mRequestThread != NULL)) {
380 res = mRequestThread->clearRepeatingRequests();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700381 if (res != OK) {
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800382 SET_ERR_L("Can't stop streaming");
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700383 // Continue to close device even in case of error
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800384 } else {
385 res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration);
386 if (res != OK) {
387 SET_ERR_L("Timeout waiting for HAL to drain (% " PRIi64 " ns)",
388 maxExpectedDuration);
389 // Continue to close device even in case of error
390 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700391 }
Eino-Ville Talvala214a17f2013-06-13 12:20:02 -0700392 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800393
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800394 if (mStatus == STATUS_ERROR) {
395 CLOGE("Shutting down in an error state");
396 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700397
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800398 if (mStatusTracker != NULL) {
399 mStatusTracker->requestExit();
400 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700401
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800402 if (mRequestThread != NULL) {
403 mRequestThread->requestExit();
404 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700405
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800406 streams.reserve(mOutputStreams.size() + (mInputStream != nullptr ? 1 : 0));
407 for (size_t i = 0; i < mOutputStreams.size(); i++) {
408 streams.push_back(mOutputStreams[i]);
409 }
410 if (mInputStream != nullptr) {
411 streams.push_back(mInputStream);
412 }
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700413 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700414 }
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800415 // Joining done without holding mLock and mInterfaceLock, otherwise deadlocks may ensue
416 // as the threads try to access parent state (b/143513518)
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700417 if (mRequestThread != NULL && mStatus != STATUS_ERROR) {
418 // HAL may be in a bad state, so waiting for request thread
419 // (which may be stuck in the HAL processCaptureRequest call)
420 // could be dangerous.
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800421 // give up mInterfaceLock here and then lock it again. Could this lead
422 // to other deadlocks
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700423 mRequestThread->join();
424 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700425 {
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800426 Mutex::Autolock il(mInterfaceLock);
427 if (mStatusTracker != NULL) {
428 mStatusTracker->join();
429 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800430
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800431 HalInterface* interface;
432 {
433 Mutex::Autolock l(mLock);
434 mRequestThread.clear();
435 Mutex::Autolock stLock(mTrackerLock);
436 mStatusTracker.clear();
437 interface = mInterface.get();
438 }
Eino-Ville Talvalaefff1c42015-08-28 16:27:27 -0700439
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800440 // Call close without internal mutex held, as the HAL close may need to
441 // wait on assorted callbacks,etc, to complete before it can return.
442 interface->close();
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700443
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800444 flushInflightRequests();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800445
Jayant Chowdhary646c31b2020-01-30 13:09:59 -0800446 {
447 Mutex::Autolock l(mLock);
448 mInterface->clear();
449 mOutputStreams.clear();
450 mInputStream.clear();
451 mDeletedStreams.clear();
452 mBufferManager.clear();
453 internalUpdateStatusLocked(STATUS_UNINITIALIZED);
454 }
455
456 for (auto& weakStream : streams) {
457 sp<Camera3StreamInterface> stream = weakStream.promote();
458 if (stream != nullptr) {
459 ALOGE("%s: Stream %d leaked! strong reference (%d)!",
460 __FUNCTION__, stream->getId(), stream->getStrongCount() - 1);
461 }
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700462 }
463 }
Yin-Chia Yehe1c80632016-08-08 14:48:05 -0700464 ALOGI("%s: X", __FUNCTION__);
Eino-Ville Talvala214a17f2013-06-13 12:20:02 -0700465 return res;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800466}
467
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700468// For dumping/debugging only -
469// try to acquire a lock a few times, eventually give up to proceed with
470// debug/dump operations
471bool Camera3Device::tryLockSpinRightRound(Mutex& lock) {
472 bool gotLock = false;
473 for (size_t i = 0; i < kDumpLockAttempts; ++i) {
474 if (lock.tryLock() == NO_ERROR) {
475 gotLock = true;
476 break;
477 } else {
478 usleep(kDumpSleepDuration);
479 }
480 }
481 return gotLock;
482}
483
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700484Camera3Device::Size Camera3Device::getMaxJpegResolution() const {
485 int32_t maxJpegWidth = 0, maxJpegHeight = 0;
Emilian Peev08dd2452017-04-06 16:55:14 +0100486 const int STREAM_CONFIGURATION_SIZE = 4;
487 const int STREAM_FORMAT_OFFSET = 0;
488 const int STREAM_WIDTH_OFFSET = 1;
489 const int STREAM_HEIGHT_OFFSET = 2;
490 const int STREAM_IS_INPUT_OFFSET = 3;
491 camera_metadata_ro_entry_t availableStreamConfigs =
492 mDeviceInfo.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
493 if (availableStreamConfigs.count == 0 ||
494 availableStreamConfigs.count % STREAM_CONFIGURATION_SIZE != 0) {
495 return Size(0, 0);
496 }
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700497
Emilian Peev08dd2452017-04-06 16:55:14 +0100498 // Get max jpeg size (area-wise).
499 for (size_t i=0; i < availableStreamConfigs.count; i+= STREAM_CONFIGURATION_SIZE) {
500 int32_t format = availableStreamConfigs.data.i32[i + STREAM_FORMAT_OFFSET];
501 int32_t width = availableStreamConfigs.data.i32[i + STREAM_WIDTH_OFFSET];
502 int32_t height = availableStreamConfigs.data.i32[i + STREAM_HEIGHT_OFFSET];
503 int32_t isInput = availableStreamConfigs.data.i32[i + STREAM_IS_INPUT_OFFSET];
504 if (isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT
505 && format == HAL_PIXEL_FORMAT_BLOB &&
506 (width * height > maxJpegWidth * maxJpegHeight)) {
507 maxJpegWidth = width;
508 maxJpegHeight = height;
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700509 }
510 }
Emilian Peev08dd2452017-04-06 16:55:14 +0100511
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700512 return Size(maxJpegWidth, maxJpegHeight);
513}
514
Shuzhen Wangc28dccc2016-02-11 23:48:46 -0800515nsecs_t Camera3Device::getMonoToBoottimeOffset() {
516 // try three times to get the clock offset, choose the one
517 // with the minimum gap in measurements.
518 const int tries = 3;
519 nsecs_t bestGap, measured;
520 for (int i = 0; i < tries; ++i) {
521 const nsecs_t tmono = systemTime(SYSTEM_TIME_MONOTONIC);
522 const nsecs_t tbase = systemTime(SYSTEM_TIME_BOOTTIME);
523 const nsecs_t tmono2 = systemTime(SYSTEM_TIME_MONOTONIC);
524 const nsecs_t gap = tmono2 - tmono;
525 if (i == 0 || gap < bestGap) {
526 bestGap = gap;
527 measured = tbase - ((tmono + tmono2) >> 1);
528 }
529 }
530 return measured;
531}
532
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800533hardware::graphics::common::V1_0::PixelFormat Camera3Device::mapToPixelFormat(
534 int frameworkFormat) {
535 return (hardware::graphics::common::V1_0::PixelFormat) frameworkFormat;
536}
537
538DataspaceFlags Camera3Device::mapToHidlDataspace(
539 android_dataspace dataSpace) {
540 return dataSpace;
541}
542
Chia-I Wu67a0c0e2017-04-06 13:37:01 -0700543BufferUsageFlags Camera3Device::mapToConsumerUsage(
Emilian Peev050f5dc2017-05-18 14:43:56 +0100544 uint64_t usage) {
Yin-Chia Yeh47cf8e62017-04-04 13:00:03 -0700545 return usage;
546}
547
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800548StreamRotation Camera3Device::mapToStreamRotation(camera3_stream_rotation_t rotation) {
549 switch (rotation) {
550 case CAMERA3_STREAM_ROTATION_0:
551 return StreamRotation::ROTATION_0;
552 case CAMERA3_STREAM_ROTATION_90:
553 return StreamRotation::ROTATION_90;
554 case CAMERA3_STREAM_ROTATION_180:
555 return StreamRotation::ROTATION_180;
556 case CAMERA3_STREAM_ROTATION_270:
557 return StreamRotation::ROTATION_270;
558 }
559 ALOGE("%s: Unknown stream rotation %d", __FUNCTION__, rotation);
560 return StreamRotation::ROTATION_0;
561}
562
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -0800563status_t Camera3Device::mapToStreamConfigurationMode(
564 camera3_stream_configuration_mode_t operationMode, StreamConfigurationMode *mode) {
565 if (mode == nullptr) return BAD_VALUE;
566 if (operationMode < CAMERA3_VENDOR_STREAM_CONFIGURATION_MODE_START) {
567 switch(operationMode) {
568 case CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE:
569 *mode = StreamConfigurationMode::NORMAL_MODE;
570 break;
571 case CAMERA3_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE:
572 *mode = StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE;
573 break;
574 default:
575 ALOGE("%s: Unknown stream configuration mode %d", __FUNCTION__, operationMode);
576 return BAD_VALUE;
577 }
578 } else {
579 *mode = static_cast<StreamConfigurationMode>(operationMode);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800580 }
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -0800581 return OK;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800582}
583
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800584int Camera3Device::mapToFrameworkFormat(
585 hardware::graphics::common::V1_0::PixelFormat pixelFormat) {
586 return static_cast<uint32_t>(pixelFormat);
587}
588
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -0700589android_dataspace Camera3Device::mapToFrameworkDataspace(
590 DataspaceFlags dataSpace) {
591 return static_cast<android_dataspace>(dataSpace);
592}
593
Emilian Peev050f5dc2017-05-18 14:43:56 +0100594uint64_t Camera3Device::mapConsumerToFrameworkUsage(
Chia-I Wu67a0c0e2017-04-06 13:37:01 -0700595 BufferUsageFlags usage) {
Yin-Chia Yeh47cf8e62017-04-04 13:00:03 -0700596 return usage;
597}
598
Emilian Peev050f5dc2017-05-18 14:43:56 +0100599uint64_t Camera3Device::mapProducerToFrameworkUsage(
Chia-I Wu67a0c0e2017-04-06 13:37:01 -0700600 BufferUsageFlags usage) {
Yin-Chia Yeh47cf8e62017-04-04 13:00:03 -0700601 return usage;
602}
603
Zhijun Hef7da0962014-04-24 13:27:56 -0700604ssize_t Camera3Device::getJpegBufferSize(uint32_t width, uint32_t height) const {
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700605 // Get max jpeg size (area-wise).
606 Size maxJpegResolution = getMaxJpegResolution();
607 if (maxJpegResolution.width == 0) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800608 ALOGE("%s: Camera %s: Can't find valid available jpeg sizes in static metadata!",
609 __FUNCTION__, mId.string());
Zhijun Hef7da0962014-04-24 13:27:56 -0700610 return BAD_VALUE;
611 }
612
Zhijun Hef7da0962014-04-24 13:27:56 -0700613 // Get max jpeg buffer size
614 ssize_t maxJpegBufferSize = 0;
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700615 camera_metadata_ro_entry jpegBufMaxSize = mDeviceInfo.find(ANDROID_JPEG_MAX_SIZE);
616 if (jpegBufMaxSize.count == 0) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800617 ALOGE("%s: Camera %s: Can't find maximum JPEG size in static metadata!", __FUNCTION__,
618 mId.string());
Zhijun Hef7da0962014-04-24 13:27:56 -0700619 return BAD_VALUE;
620 }
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700621 maxJpegBufferSize = jpegBufMaxSize.data.i32[0];
Yin-Chia Yeh0c4e56d2015-01-09 15:21:27 -0800622 assert(kMinJpegBufferSize < maxJpegBufferSize);
Zhijun Hef7da0962014-04-24 13:27:56 -0700623
624 // Calculate final jpeg buffer size for the given resolution.
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700625 float scaleFactor = ((float) (width * height)) /
626 (maxJpegResolution.width * maxJpegResolution.height);
Yin-Chia Yeh0c4e56d2015-01-09 15:21:27 -0800627 ssize_t jpegBufferSize = scaleFactor * (maxJpegBufferSize - kMinJpegBufferSize) +
628 kMinJpegBufferSize;
Zhijun Hef7da0962014-04-24 13:27:56 -0700629 if (jpegBufferSize > maxJpegBufferSize) {
630 jpegBufferSize = maxJpegBufferSize;
Zhijun Hef7da0962014-04-24 13:27:56 -0700631 }
632
633 return jpegBufferSize;
634}
635
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -0700636ssize_t Camera3Device::getPointCloudBufferSize() const {
637 const int FLOATS_PER_POINT=4;
638 camera_metadata_ro_entry maxPointCount = mDeviceInfo.find(ANDROID_DEPTH_MAX_DEPTH_SAMPLES);
639 if (maxPointCount.count == 0) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800640 ALOGE("%s: Camera %s: Can't find maximum depth point cloud size in static metadata!",
641 __FUNCTION__, mId.string());
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -0700642 return BAD_VALUE;
643 }
644 ssize_t maxBytesForPointCloud = sizeof(android_depth_points) +
645 maxPointCount.data.i32[0] * sizeof(float) * FLOATS_PER_POINT;
646 return maxBytesForPointCloud;
647}
648
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800649ssize_t Camera3Device::getRawOpaqueBufferSize(int32_t width, int32_t height) const {
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800650 const int PER_CONFIGURATION_SIZE = 3;
651 const int WIDTH_OFFSET = 0;
652 const int HEIGHT_OFFSET = 1;
653 const int SIZE_OFFSET = 2;
654 camera_metadata_ro_entry rawOpaqueSizes =
655 mDeviceInfo.find(ANDROID_SENSOR_OPAQUE_RAW_SIZE);
Aurimas Liutikasbc57b122016-02-16 09:59:16 -0800656 size_t count = rawOpaqueSizes.count;
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800657 if (count == 0 || (count % PER_CONFIGURATION_SIZE)) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800658 ALOGE("%s: Camera %s: bad opaque RAW size static metadata length(%zu)!",
659 __FUNCTION__, mId.string(), count);
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800660 return BAD_VALUE;
661 }
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -0700662
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800663 for (size_t i = 0; i < count; i += PER_CONFIGURATION_SIZE) {
664 if (width == rawOpaqueSizes.data.i32[i + WIDTH_OFFSET] &&
665 height == rawOpaqueSizes.data.i32[i + HEIGHT_OFFSET]) {
666 return rawOpaqueSizes.data.i32[i + SIZE_OFFSET];
667 }
668 }
669
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800670 ALOGE("%s: Camera %s: cannot find size for %dx%d opaque RAW image!",
671 __FUNCTION__, mId.string(), width, height);
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800672 return BAD_VALUE;
673}
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -0700674
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800675status_t Camera3Device::dump(int fd, const Vector<String16> &args) {
676 ATRACE_CALL();
677 (void)args;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700678
679 // Try to lock, but continue in case of failure (to avoid blocking in
680 // deadlocks)
681 bool gotInterfaceLock = tryLockSpinRightRound(mInterfaceLock);
682 bool gotLock = tryLockSpinRightRound(mLock);
683
684 ALOGW_IF(!gotInterfaceLock,
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800685 "Camera %s: %s: Unable to lock interface lock, proceeding anyway",
686 mId.string(), __FUNCTION__);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700687 ALOGW_IF(!gotLock,
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800688 "Camera %s: %s: Unable to lock main lock, proceeding anyway",
689 mId.string(), __FUNCTION__);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700690
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800691 bool dumpTemplates = false;
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700692
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800693 String16 templatesOption("-t");
694 int n = args.size();
695 for (int i = 0; i < n; i++) {
696 if (args[i] == templatesOption) {
697 dumpTemplates = true;
698 }
Emilian Peevbd8c5032018-02-14 23:05:40 +0000699 if (args[i] == TagMonitor::kMonitorOption) {
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700700 if (i + 1 < n) {
701 String8 monitorTags = String8(args[i + 1]);
702 if (monitorTags == "off") {
703 mTagMonitor.disableMonitoring();
704 } else {
705 mTagMonitor.parseTagsToMonitor(monitorTags);
706 }
707 } else {
708 mTagMonitor.disableMonitoring();
709 }
710 }
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800711 }
712
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800713 String8 lines;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800714
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800715 const char *status =
716 mStatus == STATUS_ERROR ? "ERROR" :
717 mStatus == STATUS_UNINITIALIZED ? "UNINITIALIZED" :
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700718 mStatus == STATUS_UNCONFIGURED ? "UNCONFIGURED" :
719 mStatus == STATUS_CONFIGURED ? "CONFIGURED" :
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800720 mStatus == STATUS_ACTIVE ? "ACTIVE" :
721 "Unknown";
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700722
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800723 lines.appendFormat(" Device status: %s\n", status);
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -0700724 if (mStatus == STATUS_ERROR) {
725 lines.appendFormat(" Error cause: %s\n", mErrorCause.string());
726 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800727 lines.appendFormat(" Stream configuration:\n");
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -0800728 const char *mode =
729 mOperatingMode == static_cast<int>(StreamConfigurationMode::NORMAL_MODE) ? "NORMAL" :
730 mOperatingMode == static_cast<int>(
731 StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE) ? "CONSTRAINED_HIGH_SPEED" :
732 "CUSTOM";
733 lines.appendFormat(" Operation mode: %s (%d) \n", mode, mOperatingMode);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800734
735 if (mInputStream != NULL) {
736 write(fd, lines.string(), lines.size());
737 mInputStream->dump(fd, args);
738 } else {
739 lines.appendFormat(" No input stream.\n");
740 write(fd, lines.string(), lines.size());
741 }
742 for (size_t i = 0; i < mOutputStreams.size(); i++) {
743 mOutputStreams[i]->dump(fd,args);
744 }
745
Zhijun He431503c2016-03-07 17:30:16 -0800746 if (mBufferManager != NULL) {
747 lines = String8(" Camera3 Buffer Manager:\n");
748 write(fd, lines.string(), lines.size());
749 mBufferManager->dump(fd, args);
750 }
Zhijun He125684a2015-12-26 15:07:30 -0800751
Eino-Ville Talvala42368d92013-04-09 14:13:50 -0700752 lines = String8(" In-flight requests:\n");
753 if (mInFlightMap.size() == 0) {
754 lines.append(" None\n");
755 } else {
756 for (size_t i = 0; i < mInFlightMap.size(); i++) {
757 InFlightRequest r = mInFlightMap.valueAt(i);
Colin Crosse5729fa2014-03-21 15:04:25 -0700758 lines.appendFormat(" Frame %d | Timestamp: %" PRId64 ", metadata"
Eino-Ville Talvala42368d92013-04-09 14:13:50 -0700759 " arrived: %s, buffers left: %d\n", mInFlightMap.keyAt(i),
Chien-Yu Chen43e69a62014-11-25 16:38:33 -0800760 r.shutterTimestamp, r.haveResultMetadata ? "true" : "false",
Eino-Ville Talvala42368d92013-04-09 14:13:50 -0700761 r.numBuffersLeft);
762 }
763 }
764 write(fd, lines.string(), lines.size());
765
Shuzhen Wang686f6442017-06-20 16:16:04 -0700766 if (mRequestThread != NULL) {
767 mRequestThread->dumpCaptureRequestLatency(fd,
768 " ProcessCaptureRequest latency histogram:");
769 }
770
Igor Murashkin1e479c02013-09-06 16:55:14 -0700771 {
772 lines = String8(" Last request sent:\n");
773 write(fd, lines.string(), lines.size());
774
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700775 CameraMetadata lastRequest = getLatestRequestLocked();
Igor Murashkin1e479c02013-09-06 16:55:14 -0700776 lastRequest.dump(fd, /*verbosity*/2, /*indentation*/6);
777 }
778
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800779 if (dumpTemplates) {
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -0800780 const char *templateNames[CAMERA3_TEMPLATE_COUNT] = {
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800781 "TEMPLATE_PREVIEW",
782 "TEMPLATE_STILL_CAPTURE",
783 "TEMPLATE_VIDEO_RECORD",
784 "TEMPLATE_VIDEO_SNAPSHOT",
785 "TEMPLATE_ZERO_SHUTTER_LAG",
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -0800786 "TEMPLATE_MANUAL",
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800787 };
788
789 for (int i = 1; i < CAMERA3_TEMPLATE_COUNT; i++) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800790 camera_metadata_t *templateRequest = nullptr;
791 mInterface->constructDefaultRequestSettings(
792 (camera3_request_template_t) i, &templateRequest);
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800793 lines = String8::format(" HAL Request %s:\n", templateNames[i-1]);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800794 if (templateRequest == nullptr) {
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800795 lines.append(" Not supported\n");
796 write(fd, lines.string(), lines.size());
797 } else {
798 write(fd, lines.string(), lines.size());
799 dump_indented_camera_metadata(templateRequest,
800 fd, /*verbosity*/2, /*indentation*/8);
801 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800802 free_camera_metadata(templateRequest);
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800803 }
804 }
805
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700806 mTagMonitor.dumpMonitoredMetadata(fd);
807
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800808 if (mInterface->valid()) {
Eino-Ville Talvalad00111e2017-01-31 11:59:12 -0800809 lines = String8(" HAL device dump:\n");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800810 write(fd, lines.string(), lines.size());
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800811 mInterface->dump(fd);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800812 }
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800813
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700814 if (gotLock) mLock.unlock();
815 if (gotInterfaceLock) mInterfaceLock.unlock();
816
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800817 return OK;
818}
819
Emilian Peevfaa4bde2020-01-23 12:19:37 -0800820const CameraMetadata& Camera3Device::infoPhysical(const String8& physicalId) const {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800821 ALOGVV("%s: E", __FUNCTION__);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800822 if (CC_UNLIKELY(mStatus == STATUS_UNINITIALIZED ||
823 mStatus == STATUS_ERROR)) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -0700824 ALOGW("%s: Access to static info %s!", __FUNCTION__,
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800825 mStatus == STATUS_ERROR ?
826 "when in error state" : "before init");
827 }
Shuzhen Wang2e7f58f2018-07-11 14:00:29 -0700828 if (physicalId.isEmpty()) {
829 return mDeviceInfo;
830 } else {
831 std::string id(physicalId.c_str());
832 if (mPhysicalDeviceInfoMap.find(id) != mPhysicalDeviceInfoMap.end()) {
833 return mPhysicalDeviceInfoMap.at(id);
834 } else {
835 ALOGE("%s: Invalid physical camera id %s", __FUNCTION__, physicalId.c_str());
836 return mDeviceInfo;
837 }
838 }
839}
840
841const CameraMetadata& Camera3Device::info() const {
842 String8 emptyId;
Emilian Peevfaa4bde2020-01-23 12:19:37 -0800843 return infoPhysical(emptyId);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800844}
845
Jianing Wei90e59c92014-03-12 18:29:36 -0700846status_t Camera3Device::checkStatusOkToCaptureLocked() {
847 switch (mStatus) {
848 case STATUS_ERROR:
849 CLOGE("Device has encountered a serious error");
850 return INVALID_OPERATION;
851 case STATUS_UNINITIALIZED:
852 CLOGE("Device not initialized");
853 return INVALID_OPERATION;
854 case STATUS_UNCONFIGURED:
855 case STATUS_CONFIGURED:
856 case STATUS_ACTIVE:
857 // OK
858 break;
859 default:
860 SET_ERR_L("Unexpected status: %d", mStatus);
861 return INVALID_OPERATION;
862 }
863 return OK;
864}
865
866status_t Camera3Device::convertMetadataListToRequestListLocked(
Emilian Peevaebbe412018-01-15 13:53:24 +0000867 const List<const PhysicalCameraSettingsList> &metadataList,
Shuzhen Wang0129d522016-10-30 22:43:41 -0700868 const std::list<const SurfaceMap> &surfaceMaps,
869 bool repeating,
Shuzhen Wang9d066012016-09-30 11:30:20 -0700870 RequestList *requestList) {
Jianing Wei90e59c92014-03-12 18:29:36 -0700871 if (requestList == NULL) {
872 CLOGE("requestList cannot be NULL.");
873 return BAD_VALUE;
874 }
875
Jianing Weicb0652e2014-03-12 18:29:36 -0700876 int32_t burstId = 0;
Emilian Peevaebbe412018-01-15 13:53:24 +0000877 List<const PhysicalCameraSettingsList>::const_iterator metadataIt = metadataList.begin();
Shuzhen Wang0129d522016-10-30 22:43:41 -0700878 std::list<const SurfaceMap>::const_iterator surfaceMapIt = surfaceMaps.begin();
879 for (; metadataIt != metadataList.end() && surfaceMapIt != surfaceMaps.end();
880 ++metadataIt, ++surfaceMapIt) {
881 sp<CaptureRequest> newRequest = setUpRequestLocked(*metadataIt, *surfaceMapIt);
Jianing Wei90e59c92014-03-12 18:29:36 -0700882 if (newRequest == 0) {
883 CLOGE("Can't create capture request");
884 return BAD_VALUE;
885 }
Jianing Weicb0652e2014-03-12 18:29:36 -0700886
Shuzhen Wang9d066012016-09-30 11:30:20 -0700887 newRequest->mRepeating = repeating;
888
Jianing Weicb0652e2014-03-12 18:29:36 -0700889 // Setup burst Id and request Id
890 newRequest->mResultExtras.burstId = burstId++;
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -0800891 auto requestIdEntry = metadataIt->begin()->metadata.find(ANDROID_REQUEST_ID);
892 if (requestIdEntry.count == 0) {
Jianing Weicb0652e2014-03-12 18:29:36 -0700893 CLOGE("RequestID does not exist in metadata");
894 return BAD_VALUE;
895 }
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -0800896 newRequest->mResultExtras.requestId = requestIdEntry.data.i32[0];
Jianing Weicb0652e2014-03-12 18:29:36 -0700897
Jianing Wei90e59c92014-03-12 18:29:36 -0700898 requestList->push_back(newRequest);
Jianing Wei2d6bb3f2014-04-11 10:00:31 -0700899
900 ALOGV("%s: requestId = %" PRId32, __FUNCTION__, newRequest->mResultExtras.requestId);
Jianing Wei90e59c92014-03-12 18:29:36 -0700901 }
Shuzhen Wang0129d522016-10-30 22:43:41 -0700902 if (metadataIt != metadataList.end() || surfaceMapIt != surfaceMaps.end()) {
903 ALOGE("%s: metadataList and surfaceMaps are not the same size!", __FUNCTION__);
904 return BAD_VALUE;
905 }
Chien-Yu Chen85a64552015-08-28 15:46:12 -0700906
907 // Setup batch size if this is a high speed video recording request.
908 if (mIsConstrainedHighSpeedConfiguration && requestList->size() > 0) {
909 auto firstRequest = requestList->begin();
910 for (auto& outputStream : (*firstRequest)->mOutputStreams) {
911 if (outputStream->isVideoStream()) {
912 (*firstRequest)->mBatchSize = requestList->size();
913 break;
914 }
915 }
916 }
917
Jianing Wei90e59c92014-03-12 18:29:36 -0700918 return OK;
919}
920
Yin-Chia Yeh7e5a2042019-02-06 16:01:06 -0800921status_t Camera3Device::capture(CameraMetadata &request, int64_t* lastFrameNumber) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800922 ATRACE_CALL();
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800923
Emilian Peevaebbe412018-01-15 13:53:24 +0000924 List<const PhysicalCameraSettingsList> requestsList;
Shuzhen Wang0129d522016-10-30 22:43:41 -0700925 std::list<const SurfaceMap> surfaceMaps;
Emilian Peevaebbe412018-01-15 13:53:24 +0000926 convertToRequestList(requestsList, surfaceMaps, request);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700927
Yin-Chia Yeh7e5a2042019-02-06 16:01:06 -0800928 return captureList(requestsList, surfaceMaps, lastFrameNumber);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700929}
930
Emilian Peevaebbe412018-01-15 13:53:24 +0000931void Camera3Device::convertToRequestList(List<const PhysicalCameraSettingsList>& requestsList,
Shuzhen Wang0129d522016-10-30 22:43:41 -0700932 std::list<const SurfaceMap>& surfaceMaps,
933 const CameraMetadata& request) {
Emilian Peevaebbe412018-01-15 13:53:24 +0000934 PhysicalCameraSettingsList requestList;
935 requestList.push_back({std::string(getId().string()), request});
936 requestsList.push_back(requestList);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700937
938 SurfaceMap surfaceMap;
939 camera_metadata_ro_entry streams = request.find(ANDROID_REQUEST_OUTPUT_STREAMS);
940 // With no surface list passed in, stream and surface will have 1-to-1
941 // mapping. So the surface index is 0 for each stream in the surfaceMap.
942 for (size_t i = 0; i < streams.count; i++) {
943 surfaceMap[streams.data.i32[i]].push_back(0);
944 }
945 surfaceMaps.push_back(surfaceMap);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800946}
947
Jianing Wei90e59c92014-03-12 18:29:36 -0700948status_t Camera3Device::submitRequestsHelper(
Emilian Peevaebbe412018-01-15 13:53:24 +0000949 const List<const PhysicalCameraSettingsList> &requests,
Shuzhen Wang0129d522016-10-30 22:43:41 -0700950 const std::list<const SurfaceMap> &surfaceMaps,
951 bool repeating,
Jianing Wei2d6bb3f2014-04-11 10:00:31 -0700952 /*out*/
953 int64_t *lastFrameNumber) {
Jianing Wei90e59c92014-03-12 18:29:36 -0700954 ATRACE_CALL();
955 Mutex::Autolock il(mInterfaceLock);
956 Mutex::Autolock l(mLock);
957
958 status_t res = checkStatusOkToCaptureLocked();
959 if (res != OK) {
960 // error logged by previous call
961 return res;
962 }
963
964 RequestList requestList;
965
Shuzhen Wang0129d522016-10-30 22:43:41 -0700966 res = convertMetadataListToRequestListLocked(requests, surfaceMaps,
967 repeating, /*out*/&requestList);
Jianing Wei90e59c92014-03-12 18:29:36 -0700968 if (res != OK) {
969 // error logged by previous call
970 return res;
971 }
972
973 if (repeating) {
Jianing Wei2d6bb3f2014-04-11 10:00:31 -0700974 res = mRequestThread->setRepeatingRequests(requestList, lastFrameNumber);
Jianing Wei90e59c92014-03-12 18:29:36 -0700975 } else {
Jianing Wei2d6bb3f2014-04-11 10:00:31 -0700976 res = mRequestThread->queueRequestList(requestList, lastFrameNumber);
Jianing Wei90e59c92014-03-12 18:29:36 -0700977 }
978
979 if (res == OK) {
980 waitUntilStateThenRelock(/*active*/true, kActiveTimeout);
981 if (res != OK) {
982 SET_ERR_L("Can't transition to active in %f seconds!",
983 kActiveTimeout/1e9);
984 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800985 ALOGV("Camera %s: Capture request %" PRId32 " enqueued", mId.string(),
Jianing Wei2d6bb3f2014-04-11 10:00:31 -0700986 (*(requestList.begin()))->mResultExtras.requestId);
Jianing Wei90e59c92014-03-12 18:29:36 -0700987 } else {
988 CLOGE("Cannot queue request. Impossible.");
989 return BAD_VALUE;
990 }
991
992 return res;
993}
994
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -0700995hardware::Return<void> Camera3Device::requestStreamBuffers(
996 const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& bufReqs,
997 requestStreamBuffers_cb _hidl_cb) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -0800998 RequestBufferStates states {
999 mId, mRequestBufferInterfaceLock, mUseHalBufManager, mOutputStreams,
1000 *this, *mInterface, *this};
1001 camera3::requestStreamBuffers(states, bufReqs, _hidl_cb);
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07001002 return hardware::Void();
1003}
1004
1005hardware::Return<void> Camera3Device::returnStreamBuffers(
1006 const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer>& buffers) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001007 ReturnBufferStates states {
1008 mId, mUseHalBufManager, mOutputStreams, *mInterface};
1009 camera3::returnStreamBuffers(states, buffers);
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07001010 return hardware::Void();
1011}
1012
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001013hardware::Return<void> Camera3Device::processCaptureResult_3_4(
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001014 const hardware::hidl_vec<
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001015 hardware::camera::device::V3_4::CaptureResult>& results) {
Yin-Chia Yeh657c1872017-07-18 18:09:57 -07001016 // Ideally we should grab mLock, but that can lead to deadlock, and
1017 // it's not super important to get up to date value of mStatus for this
1018 // warning print, hence skipping the lock here
1019 if (mStatus == STATUS_ERROR) {
1020 // Per API contract, HAL should act as closed after device error
1021 // But mStatus can be set to error by framework as well, so just log
1022 // a warning here.
1023 ALOGW("%s: received capture result in error state.", __FUNCTION__);
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07001024 }
Yifan Honga640c5a2017-04-12 16:30:31 -07001025
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001026 sp<NotificationListener> listener;
1027 {
1028 std::lock_guard<std::mutex> l(mOutputLock);
1029 listener = mListener.promote();
1030 }
1031
Yifan Honga640c5a2017-04-12 16:30:31 -07001032 if (mProcessCaptureResultLock.tryLock() != OK) {
1033 // This should never happen; it indicates a wrong client implementation
1034 // that doesn't follow the contract. But, we can be tolerant here.
1035 ALOGE("%s: callback overlapped! waiting 1s...",
1036 __FUNCTION__);
1037 if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
1038 ALOGE("%s: cannot acquire lock in 1s, dropping results",
1039 __FUNCTION__);
1040 // really don't know what to do, so bail out.
1041 return hardware::Void();
1042 }
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001043 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001044 CaptureOutputStates states {
1045 mId,
1046 mInFlightLock, mInFlightMap,
1047 mOutputLock, mResultQueue, mResultSignal,
1048 mNextShutterFrameNumber,
1049 mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
1050 mNextResultFrameNumber,
1051 mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
1052 mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
1053 mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08001054 mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
1055 mTagMonitor, mInputStream, mOutputStreams, listener, *this, *this, *mInterface
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001056 };
1057
Yifan Honga640c5a2017-04-12 16:30:31 -07001058 for (const auto& result : results) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001059 processOneCaptureResultLocked(states, result.v3_2, result.physicalCameraMetadata);
Yifan Honga640c5a2017-04-12 16:30:31 -07001060 }
1061 mProcessCaptureResultLock.unlock();
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001062 return hardware::Void();
1063}
1064
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001065// Only one processCaptureResult should be called at a time, so
1066// the locks won't block. The locks are present here simply to enforce this.
1067hardware::Return<void> Camera3Device::processCaptureResult(
1068 const hardware::hidl_vec<
1069 hardware::camera::device::V3_2::CaptureResult>& results) {
1070 hardware::hidl_vec<hardware::camera::device::V3_4::PhysicalCameraMetadata> noPhysMetadata;
1071
1072 // Ideally we should grab mLock, but that can lead to deadlock, and
1073 // it's not super important to get up to date value of mStatus for this
1074 // warning print, hence skipping the lock here
1075 if (mStatus == STATUS_ERROR) {
1076 // Per API contract, HAL should act as closed after device error
1077 // But mStatus can be set to error by framework as well, so just log
1078 // a warning here.
1079 ALOGW("%s: received capture result in error state.", __FUNCTION__);
1080 }
1081
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001082 sp<NotificationListener> listener;
1083 {
1084 std::lock_guard<std::mutex> l(mOutputLock);
1085 listener = mListener.promote();
1086 }
1087
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001088 if (mProcessCaptureResultLock.tryLock() != OK) {
1089 // This should never happen; it indicates a wrong client implementation
1090 // that doesn't follow the contract. But, we can be tolerant here.
1091 ALOGE("%s: callback overlapped! waiting 1s...",
1092 __FUNCTION__);
1093 if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
1094 ALOGE("%s: cannot acquire lock in 1s, dropping results",
1095 __FUNCTION__);
1096 // really don't know what to do, so bail out.
1097 return hardware::Void();
1098 }
1099 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001100
1101 CaptureOutputStates states {
1102 mId,
1103 mInFlightLock, mInFlightMap,
1104 mOutputLock, mResultQueue, mResultSignal,
1105 mNextShutterFrameNumber,
1106 mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
1107 mNextResultFrameNumber,
1108 mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
1109 mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
1110 mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08001111 mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
1112 mTagMonitor, mInputStream, mOutputStreams, listener, *this, *this, *mInterface
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001113 };
1114
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001115 for (const auto& result : results) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001116 processOneCaptureResultLocked(states, result, noPhysMetadata);
Shuzhen Wang5c22c152017-12-31 17:12:25 -08001117 }
1118 mProcessCaptureResultLock.unlock();
1119 return hardware::Void();
1120}
1121
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001122hardware::Return<void> Camera3Device::notify(
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001123 const hardware::hidl_vec<hardware::camera::device::V3_2::NotifyMsg>& msgs) {
Yin-Chia Yeh657c1872017-07-18 18:09:57 -07001124 // Ideally we should grab mLock, but that can lead to deadlock, and
1125 // it's not super important to get up to date value of mStatus for this
1126 // warning print, hence skipping the lock here
1127 if (mStatus == STATUS_ERROR) {
1128 // Per API contract, HAL should act as closed after device error
1129 // But mStatus can be set to error by framework as well, so just log
1130 // a warning here.
1131 ALOGW("%s: received notify message in error state.", __FUNCTION__);
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07001132 }
Yin-Chia Yeh657c1872017-07-18 18:09:57 -07001133
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001134 sp<NotificationListener> listener;
1135 {
1136 std::lock_guard<std::mutex> l(mOutputLock);
1137 listener = mListener.promote();
1138 }
1139
1140 CaptureOutputStates states {
1141 mId,
1142 mInFlightLock, mInFlightMap,
1143 mOutputLock, mResultQueue, mResultSignal,
1144 mNextShutterFrameNumber,
1145 mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
1146 mNextResultFrameNumber,
1147 mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
1148 mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
1149 mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08001150 mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
1151 mTagMonitor, mInputStream, mOutputStreams, listener, *this, *this, *mInterface
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001152 };
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001153 for (const auto& msg : msgs) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08001154 camera3::notify(states, msg);
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001155 }
1156 return hardware::Void();
1157}
1158
Emilian Peevaebbe412018-01-15 13:53:24 +00001159status_t Camera3Device::captureList(const List<const PhysicalCameraSettingsList> &requestsList,
Shuzhen Wang0129d522016-10-30 22:43:41 -07001160 const std::list<const SurfaceMap> &surfaceMaps,
Jianing Weicb0652e2014-03-12 18:29:36 -07001161 int64_t *lastFrameNumber) {
Jianing Wei90e59c92014-03-12 18:29:36 -07001162 ATRACE_CALL();
1163
Emilian Peevaebbe412018-01-15 13:53:24 +00001164 return submitRequestsHelper(requestsList, surfaceMaps, /*repeating*/false, lastFrameNumber);
Jianing Wei90e59c92014-03-12 18:29:36 -07001165}
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001166
Jianing Weicb0652e2014-03-12 18:29:36 -07001167status_t Camera3Device::setStreamingRequest(const CameraMetadata &request,
1168 int64_t* /*lastFrameNumber*/) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001169 ATRACE_CALL();
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001170
Emilian Peevaebbe412018-01-15 13:53:24 +00001171 List<const PhysicalCameraSettingsList> requestsList;
Shuzhen Wang0129d522016-10-30 22:43:41 -07001172 std::list<const SurfaceMap> surfaceMaps;
Emilian Peevaebbe412018-01-15 13:53:24 +00001173 convertToRequestList(requestsList, surfaceMaps, request);
Shuzhen Wang0129d522016-10-30 22:43:41 -07001174
Emilian Peevaebbe412018-01-15 13:53:24 +00001175 return setStreamingRequestList(requestsList, /*surfaceMap*/surfaceMaps,
Shuzhen Wang0129d522016-10-30 22:43:41 -07001176 /*lastFrameNumber*/NULL);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001177}
1178
Emilian Peevaebbe412018-01-15 13:53:24 +00001179status_t Camera3Device::setStreamingRequestList(
1180 const List<const PhysicalCameraSettingsList> &requestsList,
1181 const std::list<const SurfaceMap> &surfaceMaps, int64_t *lastFrameNumber) {
Jianing Wei90e59c92014-03-12 18:29:36 -07001182 ATRACE_CALL();
1183
Emilian Peevaebbe412018-01-15 13:53:24 +00001184 return submitRequestsHelper(requestsList, surfaceMaps, /*repeating*/true, lastFrameNumber);
Jianing Wei90e59c92014-03-12 18:29:36 -07001185}
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001186
1187sp<Camera3Device::CaptureRequest> Camera3Device::setUpRequestLocked(
Emilian Peevaebbe412018-01-15 13:53:24 +00001188 const PhysicalCameraSettingsList &request, const SurfaceMap &surfaceMap) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001189 status_t res;
1190
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001191 if (mStatus == STATUS_UNCONFIGURED || mNeedConfig) {
Eino-Ville Talvalae7091aa2017-03-07 15:23:06 -08001192 // This point should only be reached via API1 (API2 must explicitly call configureStreams)
1193 // so unilaterally select normal operating mode.
Emilian Peevaebbe412018-01-15 13:53:24 +00001194 res = filterParamsAndConfigureLocked(request.begin()->metadata,
1195 CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE);
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07001196 // Stream configuration failed. Client might try other configuraitons.
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001197 if (res != OK) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07001198 CLOGE("Can't set up streams: %s (%d)", strerror(-res), res);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001199 return NULL;
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07001200 } else if (mStatus == STATUS_UNCONFIGURED) {
1201 // Stream configuration successfully configure to empty stream configuration.
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001202 CLOGE("No streams configured");
1203 return NULL;
1204 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001205 }
1206
Shuzhen Wang0129d522016-10-30 22:43:41 -07001207 sp<CaptureRequest> newRequest = createCaptureRequest(request, surfaceMap);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001208 return newRequest;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001209}
1210
Jianing Weicb0652e2014-03-12 18:29:36 -07001211status_t Camera3Device::clearStreamingRequest(int64_t *lastFrameNumber) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001212 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001213 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001214 Mutex::Autolock l(mLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001215
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001216 switch (mStatus) {
1217 case STATUS_ERROR:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001218 CLOGE("Device has encountered a serious error");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001219 return INVALID_OPERATION;
1220 case STATUS_UNINITIALIZED:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001221 CLOGE("Device not initialized");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001222 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001223 case STATUS_UNCONFIGURED:
1224 case STATUS_CONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001225 case STATUS_ACTIVE:
1226 // OK
1227 break;
1228 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001229 SET_ERR_L("Unexpected status: %d", mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001230 return INVALID_OPERATION;
1231 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001232 ALOGV("Camera %s: Clearing repeating request", mId.string());
Jianing Weicb0652e2014-03-12 18:29:36 -07001233
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07001234 return mRequestThread->clearRepeatingRequests(lastFrameNumber);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001235}
1236
1237status_t Camera3Device::waitUntilRequestReceived(int32_t requestId, nsecs_t timeout) {
1238 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001239 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001240
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001241 return mRequestThread->waitUntilRequestProcessed(requestId, timeout);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001242}
1243
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001244status_t Camera3Device::createInputStream(
1245 uint32_t width, uint32_t height, int format, int *id) {
1246 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001247 Mutex::Autolock il(mInterfaceLock);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001248 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001249 Mutex::Autolock l(mLock);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001250 ALOGV("Camera %s: Creating new input stream %d: %d x %d, format %d",
1251 mId.string(), mNextStreamId, width, height, format);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001252
1253 status_t res;
1254 bool wasActive = false;
1255
1256 switch (mStatus) {
1257 case STATUS_ERROR:
1258 ALOGE("%s: Device has encountered a serious error", __FUNCTION__);
1259 return INVALID_OPERATION;
1260 case STATUS_UNINITIALIZED:
1261 ALOGE("%s: Device not initialized", __FUNCTION__);
1262 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001263 case STATUS_UNCONFIGURED:
1264 case STATUS_CONFIGURED:
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001265 // OK
1266 break;
1267 case STATUS_ACTIVE:
1268 ALOGV("%s: Stopping activity to reconfigure streams", __FUNCTION__);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001269 res = internalPauseAndWaitLocked(maxExpectedDuration);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001270 if (res != OK) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001271 SET_ERR_L("Can't pause captures to reconfigure streams!");
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001272 return res;
1273 }
1274 wasActive = true;
1275 break;
1276 default:
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001277 SET_ERR_L("%s: Unexpected status: %d", mStatus);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001278 return INVALID_OPERATION;
1279 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001280 assert(mStatus != STATUS_ACTIVE);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001281
1282 if (mInputStream != 0) {
1283 ALOGE("%s: Cannot create more than 1 input stream", __FUNCTION__);
1284 return INVALID_OPERATION;
1285 }
1286
1287 sp<Camera3InputStream> newStream = new Camera3InputStream(mNextStreamId,
1288 width, height, format);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001289 newStream->setStatusTracker(mStatusTracker);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001290
1291 mInputStream = newStream;
1292
1293 *id = mNextStreamId++;
1294
1295 // Continue captures if active at start
1296 if (wasActive) {
1297 ALOGV("%s: Restarting activity to reconfigure streams", __FUNCTION__);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001298 // Reuse current operating mode and session parameters for new stream config
1299 res = configureStreamsLocked(mOperatingMode, mSessionParams);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001300 if (res != OK) {
1301 ALOGE("%s: Can't reconfigure device for new stream %d: %s (%d)",
1302 __FUNCTION__, mNextStreamId, strerror(-res), res);
1303 return res;
1304 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001305 internalResumeLocked();
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001306 }
1307
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001308 ALOGV("Camera %s: Created input stream", mId.string());
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001309 return OK;
1310}
1311
Eino-Ville Talvala727d1722015-06-09 13:44:19 -07001312status_t Camera3Device::createStream(sp<Surface> consumer,
Shuzhen Wang0129d522016-10-30 22:43:41 -07001313 uint32_t width, uint32_t height, int format,
1314 android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001315 const String8& physicalCameraId,
Emilian Peev40ead602017-09-26 15:46:36 +01001316 std::vector<int> *surfaceIds, int streamSetId, bool isShared, uint64_t consumerUsage) {
Shuzhen Wang0129d522016-10-30 22:43:41 -07001317 ATRACE_CALL();
1318
1319 if (consumer == nullptr) {
1320 ALOGE("%s: consumer must not be null", __FUNCTION__);
1321 return BAD_VALUE;
1322 }
1323
1324 std::vector<sp<Surface>> consumers;
1325 consumers.push_back(consumer);
1326
1327 return createStream(consumers, /*hasDeferredConsumer*/ false, width, height,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001328 format, dataSpace, rotation, id, physicalCameraId, surfaceIds, streamSetId,
1329 isShared, consumerUsage);
Shuzhen Wang0129d522016-10-30 22:43:41 -07001330}
1331
1332status_t Camera3Device::createStream(const std::vector<sp<Surface>>& consumers,
1333 bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
1334 android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001335 const String8& physicalCameraId,
Emilian Peev40ead602017-09-26 15:46:36 +01001336 std::vector<int> *surfaceIds, int streamSetId, bool isShared, uint64_t consumerUsage) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001337 ATRACE_CALL();
Emilian Peev40ead602017-09-26 15:46:36 +01001338
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001339 Mutex::Autolock il(mInterfaceLock);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001340 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001341 Mutex::Autolock l(mLock);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001342 ALOGV("Camera %s: Creating new stream %d: %d x %d, format %d, dataspace %d rotation %d"
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001343 " consumer usage %" PRIu64 ", isShared %d, physicalCameraId %s", mId.string(),
1344 mNextStreamId, width, height, format, dataSpace, rotation, consumerUsage, isShared,
1345 physicalCameraId.string());
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001346
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001347 status_t res;
1348 bool wasActive = false;
1349
1350 switch (mStatus) {
1351 case STATUS_ERROR:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001352 CLOGE("Device has encountered a serious error");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001353 return INVALID_OPERATION;
1354 case STATUS_UNINITIALIZED:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001355 CLOGE("Device not initialized");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001356 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001357 case STATUS_UNCONFIGURED:
1358 case STATUS_CONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001359 // OK
1360 break;
1361 case STATUS_ACTIVE:
1362 ALOGV("%s: Stopping activity to reconfigure streams", __FUNCTION__);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001363 res = internalPauseAndWaitLocked(maxExpectedDuration);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001364 if (res != OK) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001365 SET_ERR_L("Can't pause captures to reconfigure streams!");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001366 return res;
1367 }
1368 wasActive = true;
1369 break;
1370 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001371 SET_ERR_L("Unexpected status: %d", mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001372 return INVALID_OPERATION;
1373 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001374 assert(mStatus != STATUS_ACTIVE);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001375
1376 sp<Camera3OutputStream> newStream;
Zhijun He5d677d12016-05-29 16:52:39 -07001377
Shuzhen Wang0129d522016-10-30 22:43:41 -07001378 if (consumers.size() == 0 && !hasDeferredConsumer) {
1379 ALOGE("%s: Number of consumers cannot be smaller than 1", __FUNCTION__);
1380 return BAD_VALUE;
1381 }
Zhijun He5d677d12016-05-29 16:52:39 -07001382
Shuzhen Wang0129d522016-10-30 22:43:41 -07001383 if (hasDeferredConsumer && format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
Zhijun He5d677d12016-05-29 16:52:39 -07001384 ALOGE("Deferred consumer stream creation only support IMPLEMENTATION_DEFINED format");
1385 return BAD_VALUE;
1386 }
1387
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001388 if (format == HAL_PIXEL_FORMAT_BLOB) {
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -07001389 ssize_t blobBufferSize;
Shuzhen Wang68ac7ad2019-01-30 14:03:28 -08001390 if (dataSpace == HAL_DATASPACE_DEPTH) {
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -07001391 blobBufferSize = getPointCloudBufferSize();
1392 if (blobBufferSize <= 0) {
1393 SET_ERR_L("Invalid point cloud buffer size %zd", blobBufferSize);
1394 return BAD_VALUE;
1395 }
Shuzhen Wang68ac7ad2019-01-30 14:03:28 -08001396 } else if (dataSpace == static_cast<android_dataspace>(HAL_DATASPACE_JPEG_APP_SEGMENTS)) {
1397 blobBufferSize = width * height;
1398 } else {
1399 blobBufferSize = getJpegBufferSize(width, height);
1400 if (blobBufferSize <= 0) {
1401 SET_ERR_L("Invalid jpeg buffer size %zd", blobBufferSize);
1402 return BAD_VALUE;
1403 }
Zhijun Hef7da0962014-04-24 13:27:56 -07001404 }
Shuzhen Wang0129d522016-10-30 22:43:41 -07001405 newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
Shuzhen Wangc28dccc2016-02-11 23:48:46 -08001406 width, height, blobBufferSize, format, dataSpace, rotation,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001407 mTimestampOffset, physicalCameraId, streamSetId);
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -08001408 } else if (format == HAL_PIXEL_FORMAT_RAW_OPAQUE) {
1409 ssize_t rawOpaqueBufferSize = getRawOpaqueBufferSize(width, height);
1410 if (rawOpaqueBufferSize <= 0) {
1411 SET_ERR_L("Invalid RAW opaque buffer size %zd", rawOpaqueBufferSize);
1412 return BAD_VALUE;
1413 }
Shuzhen Wang0129d522016-10-30 22:43:41 -07001414 newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
Shuzhen Wangc28dccc2016-02-11 23:48:46 -08001415 width, height, rawOpaqueBufferSize, format, dataSpace, rotation,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001416 mTimestampOffset, physicalCameraId, streamSetId);
Shuzhen Wang758c2152017-01-10 18:26:18 -08001417 } else if (isShared) {
1418 newStream = new Camera3SharedOutputStream(mNextStreamId, consumers,
1419 width, height, format, consumerUsage, dataSpace, rotation,
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07001420 mTimestampOffset, physicalCameraId, streamSetId,
1421 mUseHalBufManager);
Shuzhen Wang0129d522016-10-30 22:43:41 -07001422 } else if (consumers.size() == 0 && hasDeferredConsumer) {
Zhijun He5d677d12016-05-29 16:52:39 -07001423 newStream = new Camera3OutputStream(mNextStreamId,
1424 width, height, format, consumerUsage, dataSpace, rotation,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001425 mTimestampOffset, physicalCameraId, streamSetId);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001426 } else {
Shuzhen Wang0129d522016-10-30 22:43:41 -07001427 newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
Shuzhen Wangc28dccc2016-02-11 23:48:46 -08001428 width, height, format, dataSpace, rotation,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001429 mTimestampOffset, physicalCameraId, streamSetId);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001430 }
Emilian Peev40ead602017-09-26 15:46:36 +01001431
1432 size_t consumerCount = consumers.size();
1433 for (size_t i = 0; i < consumerCount; i++) {
1434 int id = newStream->getSurfaceId(consumers[i]);
1435 if (id < 0) {
1436 SET_ERR_L("Invalid surface id");
1437 return BAD_VALUE;
1438 }
1439 if (surfaceIds != nullptr) {
1440 surfaceIds->push_back(id);
1441 }
1442 }
1443
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001444 newStream->setStatusTracker(mStatusTracker);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001445
Emilian Peev08dd2452017-04-06 16:55:14 +01001446 newStream->setBufferManager(mBufferManager);
Zhijun He125684a2015-12-26 15:07:30 -08001447
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001448 res = mOutputStreams.add(mNextStreamId, newStream);
1449 if (res < 0) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001450 SET_ERR_L("Can't add new stream to set: %s (%d)", strerror(-res), res);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001451 return res;
1452 }
1453
1454 *id = mNextStreamId++;
Eino-Ville Talvalaea26c772013-06-11 16:04:06 -07001455 mNeedConfig = true;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001456
1457 // Continue captures if active at start
1458 if (wasActive) {
1459 ALOGV("%s: Restarting activity to reconfigure streams", __FUNCTION__);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001460 // Reuse current operating mode and session parameters for new stream config
1461 res = configureStreamsLocked(mOperatingMode, mSessionParams);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001462 if (res != OK) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001463 CLOGE("Can't reconfigure device for new stream %d: %s (%d)",
1464 mNextStreamId, strerror(-res), res);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001465 return res;
1466 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001467 internalResumeLocked();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001468 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001469 ALOGV("Camera %s: Created new stream", mId.string());
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001470 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001471}
1472
Emilian Peev710c1422017-08-30 11:19:38 +01001473status_t Camera3Device::getStreamInfo(int id, StreamInfo *streamInfo) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001474 ATRACE_CALL();
Emilian Peev710c1422017-08-30 11:19:38 +01001475 if (nullptr == streamInfo) {
1476 return BAD_VALUE;
1477 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001478 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001479 Mutex::Autolock l(mLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001480
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001481 switch (mStatus) {
1482 case STATUS_ERROR:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001483 CLOGE("Device has encountered a serious error");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001484 return INVALID_OPERATION;
1485 case STATUS_UNINITIALIZED:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001486 CLOGE("Device not initialized!");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001487 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001488 case STATUS_UNCONFIGURED:
1489 case STATUS_CONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001490 case STATUS_ACTIVE:
1491 // OK
1492 break;
1493 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001494 SET_ERR_L("Unexpected status: %d", mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001495 return INVALID_OPERATION;
1496 }
1497
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001498 sp<Camera3StreamInterface> stream = mOutputStreams.get(id);
1499 if (stream == nullptr) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001500 CLOGE("Stream %d is unknown", id);
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001501 return BAD_VALUE;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001502 }
1503
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001504 streamInfo->width = stream->getWidth();
1505 streamInfo->height = stream->getHeight();
1506 streamInfo->format = stream->getFormat();
1507 streamInfo->dataSpace = stream->getDataSpace();
1508 streamInfo->formatOverridden = stream->isFormatOverridden();
1509 streamInfo->originalFormat = stream->getOriginalFormat();
1510 streamInfo->dataSpaceOverridden = stream->isDataSpaceOverridden();
1511 streamInfo->originalDataSpace = stream->getOriginalDataSpace();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001512 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001513}
1514
1515status_t Camera3Device::setStreamTransform(int id,
1516 int transform) {
1517 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001518 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001519 Mutex::Autolock l(mLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001520
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001521 switch (mStatus) {
1522 case STATUS_ERROR:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001523 CLOGE("Device has encountered a serious error");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001524 return INVALID_OPERATION;
1525 case STATUS_UNINITIALIZED:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001526 CLOGE("Device not initialized");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001527 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001528 case STATUS_UNCONFIGURED:
1529 case STATUS_CONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001530 case STATUS_ACTIVE:
1531 // OK
1532 break;
1533 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001534 SET_ERR_L("Unexpected status: %d", mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001535 return INVALID_OPERATION;
1536 }
1537
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001538 sp<Camera3OutputStreamInterface> stream = mOutputStreams.get(id);
1539 if (stream == nullptr) {
1540 CLOGE("Stream %d does not exist", id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001541 return BAD_VALUE;
1542 }
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001543 return stream->setTransform(transform);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001544}
1545
1546status_t Camera3Device::deleteStream(int id) {
1547 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001548 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001549 Mutex::Autolock l(mLock);
1550 status_t res;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001551
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001552 ALOGV("%s: Camera %s: Deleting stream %d", __FUNCTION__, mId.string(), id);
Igor Murashkine2172be2013-05-28 15:31:39 -07001553
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001554 // CameraDevice semantics require device to already be idle before
1555 // deleteStream is called, unlike for createStream.
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001556 if (mStatus == STATUS_ACTIVE) {
Yin-Chia Yeh693047d2018-03-08 12:14:19 -08001557 ALOGW("%s: Camera %s: Device not idle", __FUNCTION__, mId.string());
Igor Murashkin52827132013-05-13 14:53:44 -07001558 return -EBUSY;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001559 }
1560
Yin-Chia Yeh5090c732017-07-20 16:05:29 -07001561 if (mStatus == STATUS_ERROR) {
1562 ALOGW("%s: Camera %s: deleteStream not allowed in ERROR state",
1563 __FUNCTION__, mId.string());
1564 return -EBUSY;
1565 }
1566
Igor Murashkin2fba5842013-04-22 14:03:54 -07001567 sp<Camera3StreamInterface> deletedStream;
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001568 sp<Camera3StreamInterface> stream = mOutputStreams.get(id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001569 if (mInputStream != NULL && id == mInputStream->getId()) {
1570 deletedStream = mInputStream;
1571 mInputStream.clear();
1572 } else {
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001573 if (stream == nullptr) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001574 CLOGE("Stream %d does not exist", id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001575 return BAD_VALUE;
1576 }
Zhijun He5f446352014-01-22 09:49:33 -08001577 }
1578
1579 // Delete output stream or the output part of a bi-directional stream.
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07001580 if (stream != nullptr) {
1581 deletedStream = stream;
1582 mOutputStreams.remove(id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001583 }
1584
1585 // Free up the stream endpoint so that it can be used by some other stream
1586 res = deletedStream->disconnect();
1587 if (res != OK) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001588 SET_ERR_L("Can't disconnect deleted stream %d", id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001589 // fall through since we want to still list the stream as deleted.
1590 }
1591 mDeletedStreams.add(deletedStream);
Eino-Ville Talvalaea26c772013-06-11 16:04:06 -07001592 mNeedConfig = true;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001593
1594 return res;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001595}
1596
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001597status_t Camera3Device::configureStreams(const CameraMetadata& sessionParams, int operatingMode) {
Igor Murashkine2d167e2014-08-19 16:19:59 -07001598 ATRACE_CALL();
1599 ALOGV("%s: E", __FUNCTION__);
1600
1601 Mutex::Autolock il(mInterfaceLock);
1602 Mutex::Autolock l(mLock);
Chien-Yu Chen17338fc2015-06-18 16:30:12 -07001603
Emilian Peev811d2952018-05-25 11:08:40 +01001604 // In case the client doesn't include any session parameter, try a
1605 // speculative configuration using the values from the last cached
1606 // default request.
1607 if (sessionParams.isEmpty() &&
1608 ((mLastTemplateId > 0) && (mLastTemplateId < CAMERA3_TEMPLATE_COUNT)) &&
1609 (!mRequestTemplateCache[mLastTemplateId].isEmpty())) {
1610 ALOGV("%s: Speculative session param configuration with template id: %d", __func__,
1611 mLastTemplateId);
1612 return filterParamsAndConfigureLocked(mRequestTemplateCache[mLastTemplateId],
1613 operatingMode);
1614 }
1615
Emilian Peevac3ce6c2017-12-12 15:27:02 +00001616 return filterParamsAndConfigureLocked(sessionParams, operatingMode);
1617}
1618
1619status_t Camera3Device::filterParamsAndConfigureLocked(const CameraMetadata& sessionParams,
1620 int operatingMode) {
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001621 //Filter out any incoming session parameters
1622 const CameraMetadata params(sessionParams);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001623 camera_metadata_entry_t availableSessionKeys = mDeviceInfo.find(
1624 ANDROID_REQUEST_AVAILABLE_SESSION_KEYS);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00001625 CameraMetadata filteredParams(availableSessionKeys.count);
1626 camera_metadata_t *meta = const_cast<camera_metadata_t *>(
1627 filteredParams.getAndLock());
1628 set_camera_metadata_vendor_id(meta, mVendorTagId);
1629 filteredParams.unlock(meta);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001630 if (availableSessionKeys.count > 0) {
1631 for (size_t i = 0; i < availableSessionKeys.count; i++) {
1632 camera_metadata_ro_entry entry = params.find(
1633 availableSessionKeys.data.i32[i]);
1634 if (entry.count > 0) {
1635 filteredParams.update(entry);
1636 }
1637 }
1638 }
1639
1640 return configureStreamsLocked(operatingMode, filteredParams);
Igor Murashkine2d167e2014-08-19 16:19:59 -07001641}
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001642
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -07001643status_t Camera3Device::getInputBufferProducer(
1644 sp<IGraphicBufferProducer> *producer) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07001645 ATRACE_CALL();
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -07001646 Mutex::Autolock il(mInterfaceLock);
1647 Mutex::Autolock l(mLock);
1648
1649 if (producer == NULL) {
1650 return BAD_VALUE;
1651 } else if (mInputStream == NULL) {
1652 return INVALID_OPERATION;
1653 }
1654
1655 return mInputStream->getInputBufferProducer(producer);
1656}
1657
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001658status_t Camera3Device::createDefaultRequest(int templateId,
1659 CameraMetadata *request) {
1660 ATRACE_CALL();
Alex Rayfe7e0c62013-05-30 00:12:13 -07001661 ALOGV("%s: for template %d", __FUNCTION__, templateId);
Chien-Yu Chen9cd14022016-03-09 12:21:01 -08001662
1663 if (templateId <= 0 || templateId >= CAMERA3_TEMPLATE_COUNT) {
1664 android_errorWriteWithInfoLog(CameraService::SN_EVENT_LOG_ID, "26866110",
Jayant Chowdhary12361932018-08-27 14:46:13 -07001665 CameraThreadState::getCallingUid(), nullptr, 0);
Chien-Yu Chen9cd14022016-03-09 12:21:01 -08001666 return BAD_VALUE;
1667 }
1668
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001669 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001670
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001671 {
1672 Mutex::Autolock l(mLock);
1673 switch (mStatus) {
1674 case STATUS_ERROR:
1675 CLOGE("Device has encountered a serious error");
1676 return INVALID_OPERATION;
1677 case STATUS_UNINITIALIZED:
1678 CLOGE("Device is not initialized!");
1679 return INVALID_OPERATION;
1680 case STATUS_UNCONFIGURED:
1681 case STATUS_CONFIGURED:
1682 case STATUS_ACTIVE:
1683 // OK
1684 break;
1685 default:
1686 SET_ERR_L("Unexpected status: %d", mStatus);
1687 return INVALID_OPERATION;
1688 }
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001689
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001690 if (!mRequestTemplateCache[templateId].isEmpty()) {
1691 *request = mRequestTemplateCache[templateId];
Emilian Peev811d2952018-05-25 11:08:40 +01001692 mLastTemplateId = templateId;
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001693 return OK;
1694 }
Zhijun Hea1530f12014-09-14 12:44:20 -07001695 }
1696
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001697 camera_metadata_t *rawRequest;
1698 status_t res = mInterface->constructDefaultRequestSettings(
1699 (camera3_request_template_t) templateId, &rawRequest);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001700
1701 {
1702 Mutex::Autolock l(mLock);
1703 if (res == BAD_VALUE) {
1704 ALOGI("%s: template %d is not supported on this camera device",
1705 __FUNCTION__, templateId);
1706 return res;
1707 } else if (res != OK) {
1708 CLOGE("Unable to construct request template %d: %s (%d)",
1709 templateId, strerror(-res), res);
1710 return res;
1711 }
1712
1713 set_camera_metadata_vendor_id(rawRequest, mVendorTagId);
1714 mRequestTemplateCache[templateId].acquire(rawRequest);
1715
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08001716 // Override the template request with zoomRatioMapper
1717 res = mZoomRatioMappers[mId.c_str()].initZoomRatioInTemplate(
1718 &mRequestTemplateCache[templateId]);
1719 if (res != OK) {
1720 CLOGE("Failed to update zoom ratio for template %d: %s (%d)",
1721 templateId, strerror(-res), res);
1722 return res;
1723 }
1724
Shuzhen Wangd25dc972020-03-24 17:11:43 -07001725 // Fill in JPEG_QUALITY if not available
1726 if (!mRequestTemplateCache[templateId].exists(ANDROID_JPEG_QUALITY)) {
1727 static const uint8_t kDefaultJpegQuality = 95;
1728 mRequestTemplateCache[templateId].update(ANDROID_JPEG_QUALITY,
1729 &kDefaultJpegQuality, 1);
1730 }
1731
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001732 *request = mRequestTemplateCache[templateId];
Emilian Peev811d2952018-05-25 11:08:40 +01001733 mLastTemplateId = templateId;
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001734 }
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001735 return OK;
1736}
1737
1738status_t Camera3Device::waitUntilDrained() {
1739 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001740 Mutex::Autolock il(mInterfaceLock);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001741 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001742 Mutex::Autolock l(mLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001743
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001744 return waitUntilDrainedLocked(maxExpectedDuration);
Zhijun He69a37482014-03-23 18:44:49 -07001745}
1746
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001747status_t Camera3Device::waitUntilDrainedLocked(nsecs_t maxExpectedDuration) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001748 switch (mStatus) {
1749 case STATUS_UNINITIALIZED:
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001750 case STATUS_UNCONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001751 ALOGV("%s: Already idle", __FUNCTION__);
1752 return OK;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001753 case STATUS_CONFIGURED:
1754 // To avoid race conditions, check with tracker to be sure
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001755 case STATUS_ERROR:
1756 case STATUS_ACTIVE:
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001757 // Need to verify shut down
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001758 break;
1759 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001760 SET_ERR_L("Unexpected status: %d",mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001761 return INVALID_OPERATION;
1762 }
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07001763 ALOGV("%s: Camera %s: Waiting until idle (%" PRIi64 "ns)", __FUNCTION__, mId.string(),
1764 maxExpectedDuration);
1765 status_t res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration);
Eino-Ville Talvala9c8a0912014-09-14 14:52:19 -07001766 if (res != OK) {
1767 SET_ERR_L("Error waiting for HAL to drain: %s (%d)", strerror(-res),
1768 res);
1769 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001770 return res;
1771}
1772
Ruben Brunk183f0562015-08-12 12:55:02 -07001773
1774void Camera3Device::internalUpdateStatusLocked(Status status) {
1775 mStatus = status;
1776 mRecentStatusUpdates.add(mStatus);
1777 mStatusChanged.broadcast();
1778}
1779
Eino-Ville 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
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08002225 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
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08002296 auto rotateAndCropEntry =
2297 newRequest->mSettingsList.begin()->metadata.find(ANDROID_SCALER_ROTATE_AND_CROP);
2298 if (rotateAndCropEntry.count > 0 &&
2299 rotateAndCropEntry.data.u8[0] == ANDROID_SCALER_ROTATE_AND_CROP_AUTO) {
2300 newRequest->mRotateAndCropAuto = true;
2301 } else {
2302 newRequest->mRotateAndCropAuto = false;
2303 }
2304
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002305 return newRequest;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002306}
2307
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002308void Camera3Device::cancelStreamsConfigurationLocked() {
2309 int res = OK;
2310 if (mInputStream != NULL && mInputStream->isConfiguring()) {
2311 res = mInputStream->cancelConfiguration();
2312 if (res != OK) {
2313 CLOGE("Can't cancel configuring input stream %d: %s (%d)",
2314 mInputStream->getId(), strerror(-res), res);
2315 }
2316 }
2317
2318 for (size_t i = 0; i < mOutputStreams.size(); i++) {
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002319 sp<Camera3OutputStreamInterface> outputStream = mOutputStreams[i];
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002320 if (outputStream->isConfiguring()) {
2321 res = outputStream->cancelConfiguration();
2322 if (res != OK) {
2323 CLOGE("Can't cancel configuring output stream %d: %s (%d)",
2324 outputStream->getId(), strerror(-res), res);
2325 }
2326 }
2327 }
2328
2329 // Return state to that at start of call, so that future configures
2330 // properly clean things up
2331 internalUpdateStatusLocked(STATUS_UNCONFIGURED);
2332 mNeedConfig = true;
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002333
2334 res = mPreparerThread->resume();
2335 if (res != OK) {
2336 ALOGE("%s: Camera %s: Preparer thread failed to resume!", __FUNCTION__, mId.string());
2337 }
2338}
2339
Emilian Peev0d0191e2020-04-21 17:01:18 -07002340bool Camera3Device::checkAbandonedStreamsLocked() {
2341 if ((mInputStream.get() != nullptr) && (mInputStream->isAbandoned())) {
2342 return true;
2343 }
2344
2345 for (size_t i = 0; i < mOutputStreams.size(); i++) {
2346 auto stream = mOutputStreams[i];
2347 if ((stream.get() != nullptr) && (stream->isAbandoned())) {
2348 return true;
2349 }
2350 }
2351
2352 return false;
2353}
2354
Emilian Peev3bead5f2020-05-28 17:29:08 -07002355bool Camera3Device::reconfigureCamera(const CameraMetadata& sessionParams, int clientStatusId) {
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002356 ATRACE_CALL();
2357 bool ret = false;
2358
Jayant Chowdhary646c31b2020-01-30 13:09:59 -08002359 Mutex::Autolock il(mInterfaceLock);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002360 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
2361
2362 Mutex::Autolock l(mLock);
Emilian Peev0d0191e2020-04-21 17:01:18 -07002363 if (checkAbandonedStreamsLocked()) {
2364 ALOGW("%s: Abandoned stream detected, session parameters can't be applied correctly!",
2365 __FUNCTION__);
2366 return true;
2367 }
2368
Emilian Peev3bead5f2020-05-28 17:29:08 -07002369 status_t rc = NO_ERROR;
2370 bool markClientActive = false;
2371 if (mStatus == STATUS_ACTIVE) {
2372 markClientActive = true;
2373 mPauseStateNotify = true;
2374 mStatusTracker->markComponentIdle(clientStatusId, Fence::NO_FENCE);
2375
2376 rc = internalPauseAndWaitLocked(maxExpectedDuration);
2377 }
2378
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002379 if (rc == NO_ERROR) {
2380 mNeedConfig = true;
2381 rc = configureStreamsLocked(mOperatingMode, sessionParams, /*notifyRequestThread*/ false);
2382 if (rc == NO_ERROR) {
2383 ret = true;
2384 mPauseStateNotify = false;
2385 //Moving to active state while holding 'mLock' is important.
2386 //There could be pending calls to 'create-/deleteStream' which
2387 //will trigger another stream configuration while the already
2388 //present streams end up with outstanding buffers that will
2389 //not get drained.
2390 internalUpdateStatusLocked(STATUS_ACTIVE);
Shuzhen Wang210ba5c2018-07-25 16:47:40 -07002391 } else if (rc == DEAD_OBJECT) {
2392 // DEAD_OBJECT can be returned if either the consumer surface is
2393 // abandoned, or the HAL has died.
2394 // - If the HAL has died, configureStreamsLocked call will set
2395 // device to error state,
2396 // - If surface is abandoned, we should not set device to error
2397 // state.
2398 ALOGE("Failed to re-configure camera due to abandoned surface");
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002399 } else {
Shuzhen Wang210ba5c2018-07-25 16:47:40 -07002400 SET_ERR_L("Failed to re-configure camera: %d", rc);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002401 }
2402 } else {
2403 ALOGE("%s: Failed to pause streaming: %d", __FUNCTION__, rc);
2404 }
2405
Emilian Peev3bead5f2020-05-28 17:29:08 -07002406 if (markClientActive) {
2407 mStatusTracker->markComponentActive(clientStatusId);
2408 }
2409
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002410 return ret;
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002411}
2412
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01002413status_t Camera3Device::configureStreamsLocked(int operatingMode,
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002414 const CameraMetadata& sessionParams, bool notifyRequestThread) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002415 ATRACE_CALL();
2416 status_t res;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002417
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002418 if (mStatus != STATUS_UNCONFIGURED && mStatus != STATUS_CONFIGURED) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002419 CLOGE("Not idle");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002420 return INVALID_OPERATION;
2421 }
2422
Eino-Ville Talvalae7091aa2017-03-07 15:23:06 -08002423 if (operatingMode < 0) {
2424 CLOGE("Invalid operating mode: %d", operatingMode);
2425 return BAD_VALUE;
2426 }
2427
2428 bool isConstrainedHighSpeed =
2429 static_cast<int>(StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE) ==
2430 operatingMode;
2431
2432 if (mOperatingMode != operatingMode) {
2433 mNeedConfig = true;
2434 mIsConstrainedHighSpeedConfiguration = isConstrainedHighSpeed;
2435 mOperatingMode = operatingMode;
2436 }
2437
Shuzhen Wang0cf01cb2019-09-05 13:33:06 -07002438 // In case called from configureStreams, abort queued input buffers not belonging to
2439 // any pending requests.
2440 if (mInputStream != NULL && notifyRequestThread) {
2441 while (true) {
2442 camera3_stream_buffer_t inputBuffer;
2443 status_t res = mInputStream->getInputBuffer(&inputBuffer,
2444 /*respectHalLimit*/ false);
2445 if (res != OK) {
2446 // Exhausted acquiring all input buffers.
2447 break;
2448 }
2449
2450 inputBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
2451 res = mInputStream->returnInputBuffer(inputBuffer);
2452 if (res != OK) {
2453 ALOGE("%s: %d: couldn't return input buffer while clearing input queue: "
2454 "%s (%d)", __FUNCTION__, __LINE__, strerror(-res), res);
2455 }
2456 }
2457 }
2458
Eino-Ville Talvalaea26c772013-06-11 16:04:06 -07002459 if (!mNeedConfig) {
2460 ALOGV("%s: Skipping config, no stream changes", __FUNCTION__);
2461 return OK;
2462 }
2463
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002464 // Workaround for device HALv3.2 or older spec bug - zero streams requires
2465 // adding a dummy stream instead.
2466 // TODO: Bug: 17321404 for fixing the HAL spec and removing this workaround.
2467 if (mOutputStreams.size() == 0) {
2468 addDummyStreamLocked();
2469 } else {
2470 tryRemoveDummyStreamLocked();
2471 }
2472
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002473 // Start configuring the streams
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002474 ALOGV("%s: Camera %s: Starting stream configuration", __FUNCTION__, mId.string());
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002475
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002476 mPreparerThread->pause();
2477
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002478 camera3_stream_configuration config;
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -08002479 config.operation_mode = mOperatingMode;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002480 config.num_streams = (mInputStream != NULL) + mOutputStreams.size();
2481
2482 Vector<camera3_stream_t*> streams;
2483 streams.setCapacity(config.num_streams);
Emilian Peev192ee832018-01-31 14:46:47 +00002484 std::vector<uint32_t> bufferSizes(config.num_streams, 0);
Yin-Chia Yehfb6e55b2018-01-25 10:50:26 -08002485
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002486
2487 if (mInputStream != NULL) {
2488 camera3_stream_t *inputStream;
2489 inputStream = mInputStream->startConfiguration();
2490 if (inputStream == NULL) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002491 CLOGE("Can't start input stream configuration");
2492 cancelStreamsConfigurationLocked();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002493 return INVALID_OPERATION;
2494 }
2495 streams.add(inputStream);
2496 }
2497
2498 for (size_t i = 0; i < mOutputStreams.size(); i++) {
Igor Murashkin2fba5842013-04-22 14:03:54 -07002499
2500 // Don't configure bidi streams twice, nor add them twice to the list
2501 if (mOutputStreams[i].get() ==
2502 static_cast<Camera3StreamInterface*>(mInputStream.get())) {
2503
2504 config.num_streams--;
2505 continue;
2506 }
2507
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002508 camera3_stream_t *outputStream;
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002509 outputStream = mOutputStreams[i]->startConfiguration();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002510 if (outputStream == NULL) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002511 CLOGE("Can't start output stream configuration");
2512 cancelStreamsConfigurationLocked();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002513 return INVALID_OPERATION;
2514 }
2515 streams.add(outputStream);
Yin-Chia Yehfb6e55b2018-01-25 10:50:26 -08002516
Shuzhen Wangb7ab1e42019-02-20 15:42:23 -08002517 if (outputStream->format == HAL_PIXEL_FORMAT_BLOB) {
Emilian Peev192ee832018-01-31 14:46:47 +00002518 size_t k = i + ((mInputStream != nullptr) ? 1 : 0); // Input stream if present should
2519 // always occupy the initial entry.
Shuzhen Wangb7ab1e42019-02-20 15:42:23 -08002520 if (outputStream->data_space == HAL_DATASPACE_V0_JFIF) {
2521 bufferSizes[k] = static_cast<uint32_t>(
2522 getJpegBufferSize(outputStream->width, outputStream->height));
2523 } else if (outputStream->data_space ==
2524 static_cast<android_dataspace>(HAL_DATASPACE_JPEG_APP_SEGMENTS)) {
2525 bufferSizes[k] = outputStream->width * outputStream->height;
2526 } else {
2527 ALOGW("%s: Blob dataSpace %d not supported",
2528 __FUNCTION__, outputStream->data_space);
2529 }
Yin-Chia Yehfb6e55b2018-01-25 10:50:26 -08002530 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002531 }
2532
2533 config.streams = streams.editArray();
2534
2535 // Do the HAL configuration; will potentially touch stream
Shuzhen Wang92653952019-05-07 15:11:43 -07002536 // max_buffers, usage, and priv fields, as well as data_space and format
2537 // fields for IMPLEMENTATION_DEFINED formats.
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002538
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01002539 const camera_metadata_t *sessionBuffer = sessionParams.getAndLock();
Emilian Peev192ee832018-01-31 14:46:47 +00002540 res = mInterface->configureStreams(sessionBuffer, &config, bufferSizes);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01002541 sessionParams.unlock(sessionBuffer);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002542
Eino-Ville Talvala17543512014-08-06 14:32:02 -07002543 if (res == BAD_VALUE) {
2544 // HAL rejected this set of streams as unsupported, clean up config
2545 // attempt and return to unconfigured state
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002546 CLOGE("Set of requested inputs/outputs not supported by HAL");
2547 cancelStreamsConfigurationLocked();
Eino-Ville Talvala17543512014-08-06 14:32:02 -07002548 return BAD_VALUE;
2549 } else if (res != OK) {
2550 // Some other kind of error from configure_streams - this is not
2551 // expected
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002552 SET_ERR_L("Unable to configure streams with HAL: %s (%d)",
2553 strerror(-res), res);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002554 return res;
2555 }
2556
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002557 // Finish all stream configuration immediately.
2558 // TODO: Try to relax this later back to lazy completion, which should be
2559 // faster
2560
Igor Murashkin073f8572013-05-02 14:59:28 -07002561 if (mInputStream != NULL && mInputStream->isConfiguring()) {
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002562 bool streamReConfigured = false;
2563 res = mInputStream->finishConfiguration(&streamReConfigured);
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002564 if (res != OK) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002565 CLOGE("Can't finish configuring input stream %d: %s (%d)",
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002566 mInputStream->getId(), strerror(-res), res);
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002567 cancelStreamsConfigurationLocked();
Shuzhen Wang210ba5c2018-07-25 16:47:40 -07002568 if ((res == NO_INIT || res == DEAD_OBJECT) && mInputStream->isAbandoned()) {
2569 return DEAD_OBJECT;
2570 }
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002571 return BAD_VALUE;
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002572 }
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002573 if (streamReConfigured) {
2574 mInterface->onStreamReConfigured(mInputStream->getId());
2575 }
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002576 }
2577
2578 for (size_t i = 0; i < mOutputStreams.size(); i++) {
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002579 sp<Camera3OutputStreamInterface> outputStream = mOutputStreams[i];
Zhijun He5d677d12016-05-29 16:52:39 -07002580 if (outputStream->isConfiguring() && !outputStream->isConsumerConfigurationDeferred()) {
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002581 bool streamReConfigured = false;
2582 res = outputStream->finishConfiguration(&streamReConfigured);
Igor Murashkin073f8572013-05-02 14:59:28 -07002583 if (res != OK) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002584 CLOGE("Can't finish configuring output stream %d: %s (%d)",
Igor Murashkin073f8572013-05-02 14:59:28 -07002585 outputStream->getId(), strerror(-res), res);
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002586 cancelStreamsConfigurationLocked();
Shuzhen Wang210ba5c2018-07-25 16:47:40 -07002587 if ((res == NO_INIT || res == DEAD_OBJECT) && outputStream->isAbandoned()) {
2588 return DEAD_OBJECT;
2589 }
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002590 return BAD_VALUE;
Igor Murashkin073f8572013-05-02 14:59:28 -07002591 }
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07002592 if (streamReConfigured) {
2593 mInterface->onStreamReConfigured(outputStream->getId());
2594 }
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002595 }
2596 }
2597
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002598 // Request thread needs to know to avoid using repeat-last-settings protocol
2599 // across configure_streams() calls
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002600 if (notifyRequestThread) {
2601 mRequestThread->configurationComplete(mIsConstrainedHighSpeedConfiguration, sessionParams);
2602 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002603
Zhijun He90f7c372016-08-16 16:19:43 -07002604 char value[PROPERTY_VALUE_MAX];
2605 property_get("camera.fifo.disable", value, "0");
2606 int32_t disableFifo = atoi(value);
2607 if (disableFifo != 1) {
2608 // Boost priority of request thread to SCHED_FIFO.
2609 pid_t requestThreadTid = mRequestThread->getTid();
2610 res = requestPriority(getpid(), requestThreadTid,
Mikhail Naganov83f04272017-02-07 10:45:09 -08002611 kRequestThreadPriority, /*isForApp*/ false, /*asynchronous*/ false);
Zhijun He90f7c372016-08-16 16:19:43 -07002612 if (res != OK) {
2613 ALOGW("Can't set realtime priority for request processing thread: %s (%d)",
2614 strerror(-res), res);
2615 } else {
2616 ALOGD("Set real time priority for request queue thread (tid %d)", requestThreadTid);
2617 }
Eino-Ville Talvalaf99498e2015-09-25 16:52:55 -07002618 }
2619
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002620 // Update device state
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01002621 const camera_metadata_t *newSessionParams = sessionParams.getAndLock();
2622 const camera_metadata_t *currentSessionParams = mSessionParams.getAndLock();
2623 bool updateSessionParams = (newSessionParams != currentSessionParams) ? true : false;
2624 sessionParams.unlock(newSessionParams);
2625 mSessionParams.unlock(currentSessionParams);
2626 if (updateSessionParams) {
2627 mSessionParams = sessionParams;
2628 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002629
Eino-Ville Talvalaea26c772013-06-11 16:04:06 -07002630 mNeedConfig = false;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002631
Ruben Brunk183f0562015-08-12 12:55:02 -07002632 internalUpdateStatusLocked((mDummyStreamId == NO_STREAM) ?
2633 STATUS_CONFIGURED : STATUS_UNCONFIGURED);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002634
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002635 ALOGV("%s: Camera %s: Stream configuration complete", __FUNCTION__, mId.string());
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002636
Zhijun He0a210512014-07-24 13:45:15 -07002637 // tear down the deleted streams after configure streams.
2638 mDeletedStreams.clear();
2639
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002640 auto rc = mPreparerThread->resume();
2641 if (rc != OK) {
2642 SET_ERR_L("%s: Camera %s: Preparer thread failed to resume!", __FUNCTION__, mId.string());
2643 return rc;
2644 }
2645
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07002646 if (mDummyStreamId == NO_STREAM) {
2647 mRequestBufferSM.onStreamsConfigured();
2648 }
2649
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002650 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002651}
2652
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002653status_t Camera3Device::addDummyStreamLocked() {
2654 ATRACE_CALL();
2655 status_t res;
2656
2657 if (mDummyStreamId != NO_STREAM) {
2658 // Should never be adding a second dummy stream when one is already
2659 // active
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002660 SET_ERR_L("%s: Camera %s: A dummy stream already exists!",
2661 __FUNCTION__, mId.string());
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002662 return INVALID_OPERATION;
2663 }
2664
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002665 ALOGV("%s: Camera %s: Adding a dummy stream", __FUNCTION__, mId.string());
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002666
2667 sp<Camera3OutputStreamInterface> dummyStream =
2668 new Camera3DummyStream(mNextStreamId);
2669
2670 res = mOutputStreams.add(mNextStreamId, dummyStream);
2671 if (res < 0) {
2672 SET_ERR_L("Can't add dummy stream to set: %s (%d)", strerror(-res), res);
2673 return res;
2674 }
2675
2676 mDummyStreamId = mNextStreamId;
2677 mNextStreamId++;
2678
2679 return OK;
2680}
2681
2682status_t Camera3Device::tryRemoveDummyStreamLocked() {
2683 ATRACE_CALL();
2684 status_t res;
2685
2686 if (mDummyStreamId == NO_STREAM) return OK;
2687 if (mOutputStreams.size() == 1) return OK;
2688
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002689 ALOGV("%s: Camera %s: Removing the dummy stream", __FUNCTION__, mId.string());
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002690
2691 // Ok, have a dummy stream and there's at least one other output stream,
2692 // so remove the dummy
2693
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002694 sp<Camera3StreamInterface> deletedStream = mOutputStreams.get(mDummyStreamId);
2695 if (deletedStream == nullptr) {
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002696 SET_ERR_L("Dummy stream %d does not appear to exist", mDummyStreamId);
2697 return INVALID_OPERATION;
2698 }
Yin-Chia Yeh4ee35432018-10-10 13:52:31 -07002699 mOutputStreams.remove(mDummyStreamId);
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002700
2701 // Free up the stream endpoint so that it can be used by some other stream
2702 res = deletedStream->disconnect();
2703 if (res != OK) {
2704 SET_ERR_L("Can't disconnect deleted dummy stream %d", mDummyStreamId);
2705 // fall through since we want to still list the stream as deleted.
2706 }
2707 mDeletedStreams.add(deletedStream);
2708 mDummyStreamId = NO_STREAM;
2709
2710 return res;
2711}
2712
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002713void Camera3Device::setErrorState(const char *fmt, ...) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07002714 ATRACE_CALL();
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002715 Mutex::Autolock l(mLock);
2716 va_list args;
2717 va_start(args, fmt);
2718
2719 setErrorStateLockedV(fmt, args);
2720
2721 va_end(args);
2722}
2723
2724void Camera3Device::setErrorStateV(const char *fmt, va_list args) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07002725 ATRACE_CALL();
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002726 Mutex::Autolock l(mLock);
2727 setErrorStateLockedV(fmt, args);
2728}
2729
2730void Camera3Device::setErrorStateLocked(const char *fmt, ...) {
2731 va_list args;
2732 va_start(args, fmt);
2733
2734 setErrorStateLockedV(fmt, args);
2735
2736 va_end(args);
2737}
2738
2739void Camera3Device::setErrorStateLockedV(const char *fmt, va_list args) {
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002740 // Print out all error messages to log
2741 String8 errorCause = String8::formatV(fmt, args);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002742 ALOGE("Camera %s: %s", mId.string(), errorCause.string());
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002743
2744 // But only do error state transition steps for the first error
Zhijun Heb05eeae2013-06-06 13:51:22 -07002745 if (mStatus == STATUS_ERROR || mStatus == STATUS_UNINITIALIZED) return;
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002746
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002747 mErrorCause = errorCause;
2748
Yin-Chia Yeh3d145ae2017-07-27 12:47:03 -07002749 if (mRequestThread != nullptr) {
2750 mRequestThread->setPaused(true);
2751 }
Ruben Brunk183f0562015-08-12 12:55:02 -07002752 internalUpdateStatusLocked(STATUS_ERROR);
Eino-Ville Talvala17543512014-08-06 14:32:02 -07002753
2754 // Notify upstream about a device error
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07002755 sp<NotificationListener> listener = mListener.promote();
2756 if (listener != NULL) {
2757 listener->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
Eino-Ville Talvala17543512014-08-06 14:32:02 -07002758 CaptureResultExtras());
2759 }
2760
2761 // Save stack trace. View by dumping it later.
2762 CameraTraces::saveTrace();
2763 // TODO: consider adding errorCause and client pid/procname
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002764}
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002765
2766/**
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002767 * In-flight request management
2768 */
2769
Jianing Weicb0652e2014-03-12 18:29:36 -07002770status_t Camera3Device::registerInFlight(uint32_t frameNumber,
Chien-Yu Chend196d612015-06-22 19:49:01 -07002771 int32_t numBuffers, CaptureResultExtras resultExtras, bool hasInput,
Shuzhen Wang5c22c152017-12-31 17:12:25 -08002772 bool hasAppCallback, nsecs_t maxExpectedDuration,
Shuzhen Wang26abaf42018-08-28 15:41:20 -07002773 std::set<String8>& physicalCameraIds, bool isStillCapture,
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08002774 bool isZslCapture, bool rotateAndCropAuto, const std::set<std::string>& cameraIdsWithZoom,
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08002775 const SurfaceMap& outputSurfaces) {
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002776 ATRACE_CALL();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002777 std::lock_guard<std::mutex> l(mInFlightLock);
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002778
2779 ssize_t res;
Chien-Yu Chend196d612015-06-22 19:49:01 -07002780 res = mInFlightMap.add(frameNumber, InFlightRequest(numBuffers, resultExtras, hasInput,
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07002781 hasAppCallback, maxExpectedDuration, physicalCameraIds, isStillCapture, isZslCapture,
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08002782 rotateAndCropAuto, cameraIdsWithZoom, outputSurfaces));
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002783 if (res < 0) return res;
2784
Eino-Ville Talvala24b366e2016-07-21 12:53:07 -07002785 if (mInFlightMap.size() == 1) {
Emilian Peev26d975d2018-07-05 14:52:57 +01002786 // Hold a separate dedicated tracker lock to prevent race with disconnect and also
2787 // avoid a deadlock during reprocess requests.
2788 Mutex::Autolock l(mTrackerLock);
Yin-Chia Yeh38dfde52017-06-27 17:13:33 -07002789 if (mStatusTracker != nullptr) {
2790 mStatusTracker->markComponentActive(mInFlightStatusId);
2791 }
Eino-Ville Talvala24b366e2016-07-21 12:53:07 -07002792 }
2793
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07002794 mExpectedInflightDuration += maxExpectedDuration;
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002795 return OK;
2796}
2797
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002798void Camera3Device::onInflightEntryRemovedLocked(nsecs_t duration) {
Shuzhen Wangcadb3302016-11-04 14:17:56 -07002799 // Indicate idle inFlightMap to the status tracker
2800 if (mInFlightMap.size() == 0) {
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07002801 mRequestBufferSM.onInflightMapEmpty();
Emilian Peev26d975d2018-07-05 14:52:57 +01002802 // Hold a separate dedicated tracker lock to prevent race with disconnect and also
2803 // avoid a deadlock during reprocess requests.
2804 Mutex::Autolock l(mTrackerLock);
Yin-Chia Yeh38dfde52017-06-27 17:13:33 -07002805 if (mStatusTracker != nullptr) {
2806 mStatusTracker->markComponentIdle(mInFlightStatusId, Fence::NO_FENCE);
2807 }
Shuzhen Wangcadb3302016-11-04 14:17:56 -07002808 }
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07002809 mExpectedInflightDuration -= duration;
Shuzhen Wangcadb3302016-11-04 14:17:56 -07002810}
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08002811
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002812void Camera3Device::checkInflightMapLengthLocked() {
Yin-Chia Yeh99fd0972019-06-27 14:22:44 -07002813 // Sanity check - if we have too many in-flight frames with long total inflight duration,
2814 // something has likely gone wrong. This might still be legit only if application send in
2815 // a long burst of long exposure requests.
2816 if (mExpectedInflightDuration > kMinWarnInflightDuration) {
2817 if (!mIsConstrainedHighSpeedConfiguration && mInFlightMap.size() > kInFlightWarnLimit) {
2818 CLOGW("In-flight list too large: %zu, total inflight duration %" PRIu64,
2819 mInFlightMap.size(), mExpectedInflightDuration);
2820 } else if (mIsConstrainedHighSpeedConfiguration && mInFlightMap.size() >
2821 kInFlightWarnLimitHighSpeed) {
2822 CLOGW("In-flight list too large for high speed configuration: %zu,"
2823 "total inflight duration %" PRIu64,
2824 mInFlightMap.size(), mExpectedInflightDuration);
2825 }
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08002826 }
2827}
2828
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002829void Camera3Device::onInflightMapFlushedLocked() {
2830 mExpectedInflightDuration = 0;
2831}
2832
2833void Camera3Device::removeInFlightMapEntryLocked(int idx) {
2834 ATRACE_CALL();
2835 nsecs_t duration = mInFlightMap.valueAt(idx).maxExpectedDuration;
2836 mInFlightMap.removeItemsAt(idx, 1);
2837
2838 onInflightEntryRemovedLocked(duration);
2839}
2840
2841
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07002842void Camera3Device::flushInflightRequests() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07002843 ATRACE_CALL();
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07002844 sp<NotificationListener> listener;
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07002845 {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002846 std::lock_guard<std::mutex> l(mOutputLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07002847 listener = mListener.promote();
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07002848 }
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002849
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002850 FlushInflightReqStates states {
2851 mId, mInFlightLock, mInFlightMap, mUseHalBufManager,
2852 listener, *this, *mInterface, *this};
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07002853
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08002854 camera3::flushInflightRequests(states);
Eino-Ville Talvala17543512014-08-06 14:32:02 -07002855}
2856
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002857CameraMetadata Camera3Device::getLatestRequestLocked() {
Igor Murashkin1e479c02013-09-06 16:55:14 -07002858 ALOGV("%s", __FUNCTION__);
2859
Igor Murashkin1e479c02013-09-06 16:55:14 -07002860 CameraMetadata retVal;
2861
2862 if (mRequestThread != NULL) {
2863 retVal = mRequestThread->getLatestRequest();
2864 }
2865
Igor Murashkin1e479c02013-09-06 16:55:14 -07002866 return retVal;
2867}
2868
Eino-Ville Talvala4d453832016-07-15 11:56:53 -07002869void Camera3Device::monitorMetadata(TagMonitor::eventSource source,
Shuzhen Wangc2cba122018-05-17 18:10:24 -07002870 int64_t frameNumber, nsecs_t timestamp, const CameraMetadata& metadata,
2871 const std::unordered_map<std::string, CameraMetadata>& physicalMetadata) {
2872
2873 mTagMonitor.monitorMetadata(source, frameNumber, timestamp, metadata,
2874 physicalMetadata);
Eino-Ville Talvala4d453832016-07-15 11:56:53 -07002875}
2876
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002877/**
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002878 * HalInterface inner class methods
2879 */
2880
Yifan Hongf79b5542017-04-11 14:44:25 -07002881Camera3Device::HalInterface::HalInterface(
2882 sp<ICameraDeviceSession> &session,
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08002883 std::shared_ptr<RequestMetadataQueue> queue,
Yin-Chia Yehb978c382019-10-30 00:22:37 -07002884 bool useHalBufManager, bool supportOfflineProcessing) :
Yifan Hongf79b5542017-04-11 14:44:25 -07002885 mHidlSession(session),
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08002886 mRequestMetadataQueue(queue),
Emilian Peev4ec17882019-01-24 17:16:58 -08002887 mUseHalBufManager(useHalBufManager),
Yin-Chia Yehb978c382019-10-30 00:22:37 -07002888 mIsReconfigurationQuerySupported(true),
2889 mSupportOfflineProcessing(supportOfflineProcessing) {
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002890 // Check with hardware service manager if we can downcast these interfaces
2891 // Somewhat expensive, so cache the results at startup
Yin-Chia Yehb978c382019-10-30 00:22:37 -07002892 auto castResult_3_6 = device::V3_6::ICameraDeviceSession::castFrom(mHidlSession);
2893 if (castResult_3_6.isOk()) {
2894 mHidlSession_3_6 = castResult_3_6;
2895 }
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07002896 auto castResult_3_5 = device::V3_5::ICameraDeviceSession::castFrom(mHidlSession);
2897 if (castResult_3_5.isOk()) {
2898 mHidlSession_3_5 = castResult_3_5;
2899 }
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002900 auto castResult_3_4 = device::V3_4::ICameraDeviceSession::castFrom(mHidlSession);
2901 if (castResult_3_4.isOk()) {
2902 mHidlSession_3_4 = castResult_3_4;
2903 }
2904 auto castResult_3_3 = device::V3_3::ICameraDeviceSession::castFrom(mHidlSession);
2905 if (castResult_3_3.isOk()) {
2906 mHidlSession_3_3 = castResult_3_3;
2907 }
2908}
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002909
Yin-Chia Yehb978c382019-10-30 00:22:37 -07002910Camera3Device::HalInterface::HalInterface() :
2911 mUseHalBufManager(false),
2912 mSupportOfflineProcessing(false) {}
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002913
2914Camera3Device::HalInterface::HalInterface(const HalInterface& other) :
Yifan Hongf79b5542017-04-11 14:44:25 -07002915 mHidlSession(other.mHidlSession),
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08002916 mRequestMetadataQueue(other.mRequestMetadataQueue),
Yin-Chia Yehb978c382019-10-30 00:22:37 -07002917 mUseHalBufManager(other.mUseHalBufManager),
2918 mSupportOfflineProcessing(other.mSupportOfflineProcessing) {}
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002919
2920bool Camera3Device::HalInterface::valid() {
Emilian Peev31abd0a2017-05-11 18:37:46 +01002921 return (mHidlSession != nullptr);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002922}
2923
2924void Camera3Device::HalInterface::clear() {
Yin-Chia Yehb978c382019-10-30 00:22:37 -07002925 mHidlSession_3_6.clear();
Emilian Peev644a3e12018-11-23 13:52:39 +00002926 mHidlSession_3_5.clear();
Emilian Peev9e740b02018-01-30 18:28:03 +00002927 mHidlSession_3_4.clear();
2928 mHidlSession_3_3.clear();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002929 mHidlSession.clear();
2930}
2931
2932status_t Camera3Device::HalInterface::constructDefaultRequestSettings(
2933 camera3_request_template_t templateId,
2934 /*out*/ camera_metadata_t **requestTemplate) {
2935 ATRACE_NAME("CameraHal::constructDefaultRequestSettings");
2936 if (!valid()) return INVALID_OPERATION;
2937 status_t res = OK;
2938
Emilian Peev31abd0a2017-05-11 18:37:46 +01002939 common::V1_0::Status status;
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002940
2941 auto requestCallback = [&status, &requestTemplate]
Emilian Peev31abd0a2017-05-11 18:37:46 +01002942 (common::V1_0::Status s, const device::V3_2::CameraMetadata& request) {
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002943 status = s;
2944 if (status == common::V1_0::Status::OK) {
2945 const camera_metadata *r =
2946 reinterpret_cast<const camera_metadata_t*>(request.data());
2947 size_t expectedSize = request.size();
2948 int ret = validate_camera_metadata_structure(r, &expectedSize);
2949 if (ret == OK || ret == CAMERA_METADATA_VALIDATION_SHIFTED) {
2950 *requestTemplate = clone_camera_metadata(r);
2951 if (*requestTemplate == nullptr) {
2952 ALOGE("%s: Unable to clone camera metadata received from HAL",
2953 __FUNCTION__);
Emilian Peev31abd0a2017-05-11 18:37:46 +01002954 status = common::V1_0::Status::INTERNAL_ERROR;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002955 }
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002956 } else {
2957 ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
2958 status = common::V1_0::Status::INTERNAL_ERROR;
Emilian Peev31abd0a2017-05-11 18:37:46 +01002959 }
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002960 }
2961 };
2962 hardware::Return<void> err;
Eino-Ville Talvala96441462018-02-06 11:41:55 -08002963 RequestTemplate id;
2964 switch (templateId) {
2965 case CAMERA3_TEMPLATE_PREVIEW:
2966 id = RequestTemplate::PREVIEW;
2967 break;
2968 case CAMERA3_TEMPLATE_STILL_CAPTURE:
2969 id = RequestTemplate::STILL_CAPTURE;
2970 break;
2971 case CAMERA3_TEMPLATE_VIDEO_RECORD:
2972 id = RequestTemplate::VIDEO_RECORD;
2973 break;
2974 case CAMERA3_TEMPLATE_VIDEO_SNAPSHOT:
2975 id = RequestTemplate::VIDEO_SNAPSHOT;
2976 break;
2977 case CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG:
2978 id = RequestTemplate::ZERO_SHUTTER_LAG;
2979 break;
2980 case CAMERA3_TEMPLATE_MANUAL:
2981 id = RequestTemplate::MANUAL;
2982 break;
2983 default:
2984 // Unknown template ID, or this HAL is too old to support it
2985 return BAD_VALUE;
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002986 }
Eino-Ville Talvala96441462018-02-06 11:41:55 -08002987 err = mHidlSession->constructDefaultRequestSettings(id, requestCallback);
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08002988
Emilian Peev31abd0a2017-05-11 18:37:46 +01002989 if (!err.isOk()) {
2990 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
2991 res = DEAD_OBJECT;
2992 } else {
2993 res = CameraProviderManager::mapToStatusT(status);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002994 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01002995
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002996 return res;
2997}
2998
Emilian Peev4ec17882019-01-24 17:16:58 -08002999bool Camera3Device::HalInterface::isReconfigurationRequired(CameraMetadata& oldSessionParams,
3000 CameraMetadata& newSessionParams) {
3001 // We do reconfiguration by default;
3002 bool ret = true;
3003 if ((mHidlSession_3_5 != nullptr) && mIsReconfigurationQuerySupported) {
3004 android::hardware::hidl_vec<uint8_t> oldParams, newParams;
3005 camera_metadata_t* oldSessioMeta = const_cast<camera_metadata_t*>(
3006 oldSessionParams.getAndLock());
3007 camera_metadata_t* newSessioMeta = const_cast<camera_metadata_t*>(
3008 newSessionParams.getAndLock());
3009 oldParams.setToExternal(reinterpret_cast<uint8_t*>(oldSessioMeta),
3010 get_camera_metadata_size(oldSessioMeta));
3011 newParams.setToExternal(reinterpret_cast<uint8_t*>(newSessioMeta),
3012 get_camera_metadata_size(newSessioMeta));
3013 hardware::camera::common::V1_0::Status callStatus;
3014 bool required;
3015 auto hidlCb = [&callStatus, &required] (hardware::camera::common::V1_0::Status s,
3016 bool requiredFlag) {
3017 callStatus = s;
3018 required = requiredFlag;
3019 };
3020 auto err = mHidlSession_3_5->isReconfigurationRequired(oldParams, newParams, hidlCb);
3021 oldSessionParams.unlock(oldSessioMeta);
3022 newSessionParams.unlock(newSessioMeta);
3023 if (err.isOk()) {
3024 switch (callStatus) {
3025 case hardware::camera::common::V1_0::Status::OK:
3026 ret = required;
3027 break;
3028 case hardware::camera::common::V1_0::Status::METHOD_NOT_SUPPORTED:
3029 mIsReconfigurationQuerySupported = false;
3030 ret = true;
3031 break;
3032 default:
3033 ALOGV("%s: Reconfiguration query failed: %d", __FUNCTION__, callStatus);
3034 ret = true;
3035 }
3036 } else {
3037 ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, err.description().c_str());
3038 ret = true;
3039 }
3040 }
3041
3042 return ret;
3043}
3044
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01003045status_t Camera3Device::HalInterface::configureStreams(const camera_metadata_t *sessionParams,
Emilian Peev192ee832018-01-31 14:46:47 +00003046 camera3_stream_configuration *config, const std::vector<uint32_t>& bufferSizes) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003047 ATRACE_NAME("CameraHal::configureStreams");
3048 if (!valid()) return INVALID_OPERATION;
3049 status_t res = OK;
3050
Emilian Peev31abd0a2017-05-11 18:37:46 +01003051 // Convert stream config to HIDL
3052 std::set<int> activeStreams;
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003053 device::V3_2::StreamConfiguration requestedConfiguration3_2;
3054 device::V3_4::StreamConfiguration requestedConfiguration3_4;
3055 requestedConfiguration3_2.streams.resize(config->num_streams);
3056 requestedConfiguration3_4.streams.resize(config->num_streams);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003057 for (size_t i = 0; i < config->num_streams; i++) {
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003058 device::V3_2::Stream &dst3_2 = requestedConfiguration3_2.streams[i];
3059 device::V3_4::Stream &dst3_4 = requestedConfiguration3_4.streams[i];
Emilian Peev31abd0a2017-05-11 18:37:46 +01003060 camera3_stream_t *src = config->streams[i];
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003061
Emilian Peev31abd0a2017-05-11 18:37:46 +01003062 Camera3Stream* cam3stream = Camera3Stream::cast(src);
3063 cam3stream->setBufferFreedListener(this);
3064 int streamId = cam3stream->getId();
3065 StreamType streamType;
3066 switch (src->stream_type) {
3067 case CAMERA3_STREAM_OUTPUT:
3068 streamType = StreamType::OUTPUT;
3069 break;
3070 case CAMERA3_STREAM_INPUT:
3071 streamType = StreamType::INPUT;
3072 break;
3073 default:
3074 ALOGE("%s: Stream %d: Unsupported stream type %d",
3075 __FUNCTION__, streamId, config->streams[i]->stream_type);
3076 return BAD_VALUE;
3077 }
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003078 dst3_2.id = streamId;
3079 dst3_2.streamType = streamType;
3080 dst3_2.width = src->width;
3081 dst3_2.height = src->height;
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003082 dst3_2.usage = mapToConsumerUsage(cam3stream->getUsage());
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003083 dst3_2.rotation = mapToStreamRotation((camera3_stream_rotation_t) src->rotation);
Shuzhen Wang92653952019-05-07 15:11:43 -07003084 // For HidlSession version 3.5 or newer, the format and dataSpace sent
3085 // to HAL are original, not the overriden ones.
3086 if (mHidlSession_3_5 != nullptr) {
3087 dst3_2.format = mapToPixelFormat(cam3stream->isFormatOverridden() ?
3088 cam3stream->getOriginalFormat() : src->format);
3089 dst3_2.dataSpace = mapToHidlDataspace(cam3stream->isDataSpaceOverridden() ?
3090 cam3stream->getOriginalDataSpace() : src->data_space);
3091 } else {
3092 dst3_2.format = mapToPixelFormat(src->format);
3093 dst3_2.dataSpace = mapToHidlDataspace(src->data_space);
3094 }
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003095 dst3_4.v3_2 = dst3_2;
Emilian Peev192ee832018-01-31 14:46:47 +00003096 dst3_4.bufferSize = bufferSizes[i];
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003097 if (src->physical_camera_id != nullptr) {
3098 dst3_4.physicalCameraId = src->physical_camera_id;
3099 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003100
3101 activeStreams.insert(streamId);
3102 // Create Buffer ID map if necessary
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003103 mBufferRecords.tryCreateBufferCache(streamId);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003104 }
3105 // remove BufferIdMap for deleted streams
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003106 mBufferRecords.removeInactiveBufferCaches(activeStreams);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003107
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003108 StreamConfigurationMode operationMode;
Emilian Peev31abd0a2017-05-11 18:37:46 +01003109 res = mapToStreamConfigurationMode(
3110 (camera3_stream_configuration_mode_t) config->operation_mode,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003111 /*out*/ &operationMode);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003112 if (res != OK) {
3113 return res;
3114 }
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003115 requestedConfiguration3_2.operationMode = operationMode;
3116 requestedConfiguration3_4.operationMode = operationMode;
3117 requestedConfiguration3_4.sessionParams.setToExternal(
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01003118 reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams)),
3119 get_camera_metadata_size(sessionParams));
3120
Emilian Peev31abd0a2017-05-11 18:37:46 +01003121 // Invoke configureStreams
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003122 device::V3_3::HalStreamConfiguration finalConfiguration;
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003123 device::V3_4::HalStreamConfiguration finalConfiguration3_4;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003124 device::V3_6::HalStreamConfiguration finalConfiguration3_6;
Emilian Peev31abd0a2017-05-11 18:37:46 +01003125 common::V1_0::Status status;
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003126
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003127 auto configStream34Cb = [&status, &finalConfiguration3_4]
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003128 (common::V1_0::Status s, const device::V3_4::HalStreamConfiguration& halConfiguration) {
3129 finalConfiguration3_4 = halConfiguration;
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01003130 status = s;
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003131 };
3132
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003133 auto configStream36Cb = [&status, &finalConfiguration3_6]
3134 (common::V1_0::Status s, const device::V3_6::HalStreamConfiguration& halConfiguration) {
3135 finalConfiguration3_6 = halConfiguration;
3136 status = s;
3137 };
3138
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003139 auto postprocConfigStream34 = [&finalConfiguration, &finalConfiguration3_4]
3140 (hardware::Return<void>& err) -> status_t {
3141 if (!err.isOk()) {
3142 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3143 return DEAD_OBJECT;
3144 }
3145 finalConfiguration.streams.resize(finalConfiguration3_4.streams.size());
3146 for (size_t i = 0; i < finalConfiguration3_4.streams.size(); i++) {
3147 finalConfiguration.streams[i] = finalConfiguration3_4.streams[i].v3_3;
3148 }
3149 return OK;
3150 };
3151
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003152 auto postprocConfigStream36 = [&finalConfiguration, &finalConfiguration3_6]
3153 (hardware::Return<void>& err) -> status_t {
3154 if (!err.isOk()) {
3155 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3156 return DEAD_OBJECT;
3157 }
3158 finalConfiguration.streams.resize(finalConfiguration3_6.streams.size());
3159 for (size_t i = 0; i < finalConfiguration3_6.streams.size(); i++) {
3160 finalConfiguration.streams[i] = finalConfiguration3_6.streams[i].v3_4.v3_3;
3161 }
3162 return OK;
3163 };
3164
Shuzhen Wang92653952019-05-07 15:11:43 -07003165 // See which version of HAL we have
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003166 if (mHidlSession_3_6 != nullptr) {
3167 ALOGV("%s: v3.6 device found", __FUNCTION__);
3168 device::V3_5::StreamConfiguration requestedConfiguration3_5;
3169 requestedConfiguration3_5.v3_4 = requestedConfiguration3_4;
3170 requestedConfiguration3_5.streamConfigCounter = mNextStreamConfigCounter++;
3171 auto err = mHidlSession_3_6->configureStreams_3_6(
3172 requestedConfiguration3_5, configStream36Cb);
3173 res = postprocConfigStream36(err);
3174 if (res != OK) {
3175 return res;
3176 }
3177 } else if (mHidlSession_3_5 != nullptr) {
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003178 ALOGV("%s: v3.5 device found", __FUNCTION__);
3179 device::V3_5::StreamConfiguration requestedConfiguration3_5;
3180 requestedConfiguration3_5.v3_4 = requestedConfiguration3_4;
3181 requestedConfiguration3_5.streamConfigCounter = mNextStreamConfigCounter++;
3182 auto err = mHidlSession_3_5->configureStreams_3_5(
3183 requestedConfiguration3_5, configStream34Cb);
3184 res = postprocConfigStream34(err);
3185 if (res != OK) {
3186 return res;
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01003187 }
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003188 } else if (mHidlSession_3_4 != nullptr) {
3189 // We do; use v3.4 for the call
3190 ALOGV("%s: v3.4 device found", __FUNCTION__);
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003191 auto err = mHidlSession_3_4->configureStreams_3_4(
3192 requestedConfiguration3_4, configStream34Cb);
3193 res = postprocConfigStream34(err);
3194 if (res != OK) {
3195 return res;
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003196 }
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08003197 } else if (mHidlSession_3_3 != nullptr) {
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003198 // We do; use v3.3 for the call
3199 ALOGV("%s: v3.3 device found", __FUNCTION__);
Eino-Ville Talvala1a86df52018-01-17 16:00:35 -08003200 auto err = mHidlSession_3_3->configureStreams_3_3(requestedConfiguration3_2,
Emilian Peev31abd0a2017-05-11 18:37:46 +01003201 [&status, &finalConfiguration]
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003202 (common::V1_0::Status s, const device::V3_3::HalStreamConfiguration& halConfiguration) {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003203 finalConfiguration = halConfiguration;
3204 status = s;
3205 });
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003206 if (!err.isOk()) {
3207 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3208 return DEAD_OBJECT;
3209 }
3210 } else {
3211 // We don't; use v3.2 call and construct a v3.3 HalStreamConfiguration
3212 ALOGV("%s: v3.2 device found", __FUNCTION__);
3213 HalStreamConfiguration finalConfiguration_3_2;
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003214 auto err = mHidlSession->configureStreams(requestedConfiguration3_2,
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003215 [&status, &finalConfiguration_3_2]
3216 (common::V1_0::Status s, const HalStreamConfiguration& halConfiguration) {
3217 finalConfiguration_3_2 = halConfiguration;
3218 status = s;
3219 });
3220 if (!err.isOk()) {
3221 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3222 return DEAD_OBJECT;
3223 }
3224 finalConfiguration.streams.resize(finalConfiguration_3_2.streams.size());
3225 for (size_t i = 0; i < finalConfiguration_3_2.streams.size(); i++) {
3226 finalConfiguration.streams[i].v3_2 = finalConfiguration_3_2.streams[i];
3227 finalConfiguration.streams[i].overrideDataSpace =
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003228 requestedConfiguration3_2.streams[i].dataSpace;
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003229 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003230 }
3231
3232 if (status != common::V1_0::Status::OK ) {
3233 return CameraProviderManager::mapToStatusT(status);
3234 }
3235
3236 // And convert output stream configuration from HIDL
3237
3238 for (size_t i = 0; i < config->num_streams; i++) {
3239 camera3_stream_t *dst = config->streams[i];
3240 int streamId = Camera3Stream::cast(dst)->getId();
3241
3242 // Start scan at i, with the assumption that the stream order matches
3243 size_t realIdx = i;
3244 bool found = false;
Eino-Ville Talvala370875f2019-04-12 12:40:27 -07003245 size_t halStreamCount = finalConfiguration.streams.size();
3246 for (size_t idx = 0; idx < halStreamCount; idx++) {
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003247 if (finalConfiguration.streams[realIdx].v3_2.id == streamId) {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003248 found = true;
3249 break;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003250 }
Eino-Ville Talvala370875f2019-04-12 12:40:27 -07003251 realIdx = (realIdx >= halStreamCount - 1) ? 0 : realIdx + 1;
Emilian Peev31abd0a2017-05-11 18:37:46 +01003252 }
3253 if (!found) {
3254 ALOGE("%s: Stream %d not found in stream configuration response from HAL",
3255 __FUNCTION__, streamId);
3256 return INVALID_OPERATION;
3257 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003258 device::V3_3::HalStream &src = finalConfiguration.streams[realIdx];
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003259 device::V3_6::HalStream &src_36 = finalConfiguration3_6.streams[realIdx];
Yin-Chia Yeh77327052017-01-09 18:23:07 -08003260
Emilian Peev710c1422017-08-30 11:19:38 +01003261 Camera3Stream* dstStream = Camera3Stream::cast(dst);
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003262 int overrideFormat = mapToFrameworkFormat(src.v3_2.overrideFormat);
3263 android_dataspace overrideDataSpace = mapToFrameworkDataspace(src.overrideDataSpace);
3264
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003265 if (mHidlSession_3_6 != nullptr) {
3266 dstStream->setOfflineProcessingSupport(src_36.supportOffline);
3267 }
3268
Yin-Chia Yeh90667662019-07-01 15:45:00 -07003269 if (dstStream->getOriginalFormat() != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
Shuzhen Wang92653952019-05-07 15:11:43 -07003270 dstStream->setFormatOverride(false);
3271 dstStream->setDataSpaceOverride(false);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003272 if (dst->format != overrideFormat) {
3273 ALOGE("%s: Stream %d: Format override not allowed for format 0x%x", __FUNCTION__,
3274 streamId, dst->format);
Yin-Chia Yeh77327052017-01-09 18:23:07 -08003275 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003276 if (dst->data_space != overrideDataSpace) {
3277 ALOGE("%s: Stream %d: DataSpace override not allowed for format 0x%x", __FUNCTION__,
3278 streamId, dst->format);
3279 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003280 } else {
Shuzhen Wang92653952019-05-07 15:11:43 -07003281 bool needFormatOverride =
3282 requestedConfiguration3_2.streams[i].format != src.v3_2.overrideFormat;
3283 bool needDataspaceOverride =
3284 requestedConfiguration3_2.streams[i].dataSpace != src.overrideDataSpace;
Emilian Peev31abd0a2017-05-11 18:37:46 +01003285 // Override allowed with IMPLEMENTATION_DEFINED
Shuzhen Wang92653952019-05-07 15:11:43 -07003286 dstStream->setFormatOverride(needFormatOverride);
3287 dstStream->setDataSpaceOverride(needDataspaceOverride);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003288 dst->format = overrideFormat;
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003289 dst->data_space = overrideDataSpace;
Yin-Chia Yeh77327052017-01-09 18:23:07 -08003290 }
3291
Emilian Peev31abd0a2017-05-11 18:37:46 +01003292 if (dst->stream_type == CAMERA3_STREAM_INPUT) {
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003293 if (src.v3_2.producerUsage != 0) {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003294 ALOGE("%s: Stream %d: INPUT streams must have 0 for producer usage",
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003295 __FUNCTION__, streamId);
3296 return INVALID_OPERATION;
3297 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003298 dstStream->setUsage(
3299 mapConsumerToFrameworkUsage(src.v3_2.consumerUsage));
Emilian Peev31abd0a2017-05-11 18:37:46 +01003300 } else {
3301 // OUTPUT
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003302 if (src.v3_2.consumerUsage != 0) {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003303 ALOGE("%s: Stream %d: OUTPUT streams must have 0 for consumer usage",
3304 __FUNCTION__, streamId);
3305 return INVALID_OPERATION;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003306 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003307 dstStream->setUsage(
3308 mapProducerToFrameworkUsage(src.v3_2.producerUsage));
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003309 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003310 dst->max_buffers = src.v3_2.maxBuffers;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003311 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003312
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003313 return res;
3314}
3315
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003316status_t Camera3Device::HalInterface::wrapAsHidlRequest(camera3_capture_request_t* request,
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003317 /*out*/device::V3_2::CaptureRequest* captureRequest,
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003318 /*out*/std::vector<native_handle_t*>* handlesCreated,
3319 /*out*/std::vector<std::pair<int32_t, int32_t>>* inflightBuffers) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003320 ATRACE_CALL();
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003321 if (captureRequest == nullptr || handlesCreated == nullptr || inflightBuffers == nullptr) {
3322 ALOGE("%s: captureRequest (%p), handlesCreated (%p), and inflightBuffers(%p) "
3323 "must not be null", __FUNCTION__, captureRequest, handlesCreated, inflightBuffers);
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003324 return BAD_VALUE;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003325 }
3326
3327 captureRequest->frameNumber = request->frame_number;
Yifan Hongf79b5542017-04-11 14:44:25 -07003328
3329 captureRequest->fmqSettingsSize = 0;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003330
3331 {
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003332 if (request->input_buffer != nullptr) {
3333 int32_t streamId = Camera3Stream::cast(request->input_buffer->stream)->getId();
3334 buffer_handle_t buf = *(request->input_buffer->buffer);
3335 auto pair = getBufferId(buf, streamId);
3336 bool isNewBuffer = pair.first;
3337 uint64_t bufferId = pair.second;
3338 captureRequest->inputBuffer.streamId = streamId;
3339 captureRequest->inputBuffer.bufferId = bufferId;
3340 captureRequest->inputBuffer.buffer = (isNewBuffer) ? buf : nullptr;
3341 captureRequest->inputBuffer.status = BufferStatus::OK;
3342 native_handle_t *acquireFence = nullptr;
3343 if (request->input_buffer->acquire_fence != -1) {
3344 acquireFence = native_handle_create(1,0);
3345 acquireFence->data[0] = request->input_buffer->acquire_fence;
3346 handlesCreated->push_back(acquireFence);
3347 }
3348 captureRequest->inputBuffer.acquireFence = acquireFence;
3349 captureRequest->inputBuffer.releaseFence = nullptr;
3350
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003351 mBufferRecords.pushInflightBuffer(captureRequest->frameNumber, streamId,
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003352 request->input_buffer->buffer);
3353 inflightBuffers->push_back(std::make_pair(captureRequest->frameNumber, streamId));
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003354 } else {
3355 captureRequest->inputBuffer.streamId = -1;
3356 captureRequest->inputBuffer.bufferId = BUFFER_ID_NO_BUFFER;
3357 }
3358
3359 captureRequest->outputBuffers.resize(request->num_output_buffers);
3360 for (size_t i = 0; i < request->num_output_buffers; i++) {
3361 const camera3_stream_buffer_t *src = request->output_buffers + i;
3362 StreamBuffer &dst = captureRequest->outputBuffers[i];
3363 int32_t streamId = Camera3Stream::cast(src->stream)->getId();
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003364 if (src->buffer != nullptr) {
3365 buffer_handle_t buf = *(src->buffer);
3366 auto pair = getBufferId(buf, streamId);
3367 bool isNewBuffer = pair.first;
3368 dst.bufferId = pair.second;
3369 dst.buffer = isNewBuffer ? buf : nullptr;
3370 native_handle_t *acquireFence = nullptr;
3371 if (src->acquire_fence != -1) {
3372 acquireFence = native_handle_create(1,0);
3373 acquireFence->data[0] = src->acquire_fence;
3374 handlesCreated->push_back(acquireFence);
3375 }
3376 dst.acquireFence = acquireFence;
3377 } else if (mUseHalBufManager) {
3378 // HAL buffer management path
3379 dst.bufferId = BUFFER_ID_NO_BUFFER;
3380 dst.buffer = nullptr;
3381 dst.acquireFence = nullptr;
3382 } else {
3383 ALOGE("%s: cannot send a null buffer in capture request!", __FUNCTION__);
3384 return BAD_VALUE;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003385 }
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003386 dst.streamId = streamId;
3387 dst.status = BufferStatus::OK;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003388 dst.releaseFence = nullptr;
3389
Yin-Chia Yeh5f840f82019-03-05 11:59:04 -08003390 // Output buffers are empty when using HAL buffer manager
3391 if (!mUseHalBufManager) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003392 mBufferRecords.pushInflightBuffer(
3393 captureRequest->frameNumber, streamId, src->buffer);
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003394 inflightBuffers->push_back(std::make_pair(captureRequest->frameNumber, streamId));
Yin-Chia Yeh5f840f82019-03-05 11:59:04 -08003395 }
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003396 }
3397 }
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003398 return OK;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003399}
3400
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003401void Camera3Device::HalInterface::cleanupNativeHandles(
3402 std::vector<native_handle_t*> *handles, bool closeFd) {
3403 if (handles == nullptr) {
3404 return;
3405 }
3406 if (closeFd) {
3407 for (auto& handle : *handles) {
3408 native_handle_close(handle);
3409 }
3410 }
3411 for (auto& handle : *handles) {
3412 native_handle_delete(handle);
3413 }
3414 handles->clear();
3415 return;
3416}
3417
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003418status_t Camera3Device::HalInterface::processBatchCaptureRequests(
3419 std::vector<camera3_capture_request_t*>& requests,/*out*/uint32_t* numRequestProcessed) {
3420 ATRACE_NAME("CameraHal::processBatchCaptureRequests");
3421 if (!valid()) return INVALID_OPERATION;
3422
Emilian Peevaebbe412018-01-15 13:53:24 +00003423 sp<device::V3_4::ICameraDeviceSession> hidlSession_3_4;
3424 auto castResult_3_4 = device::V3_4::ICameraDeviceSession::castFrom(mHidlSession);
3425 if (castResult_3_4.isOk()) {
3426 hidlSession_3_4 = castResult_3_4;
3427 }
3428
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003429 hardware::hidl_vec<device::V3_2::CaptureRequest> captureRequests;
Emilian Peevaebbe412018-01-15 13:53:24 +00003430 hardware::hidl_vec<device::V3_4::CaptureRequest> captureRequests_3_4;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003431 size_t batchSize = requests.size();
Emilian Peevaebbe412018-01-15 13:53:24 +00003432 if (hidlSession_3_4 != nullptr) {
3433 captureRequests_3_4.resize(batchSize);
3434 } else {
3435 captureRequests.resize(batchSize);
3436 }
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003437 std::vector<native_handle_t*> handlesCreated;
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003438 std::vector<std::pair<int32_t, int32_t>> inflightBuffers;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003439
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003440 status_t res = OK;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003441 for (size_t i = 0; i < batchSize; i++) {
Emilian Peevaebbe412018-01-15 13:53:24 +00003442 if (hidlSession_3_4 != nullptr) {
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003443 res = wrapAsHidlRequest(requests[i], /*out*/&captureRequests_3_4[i].v3_2,
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003444 /*out*/&handlesCreated, /*out*/&inflightBuffers);
Emilian Peevaebbe412018-01-15 13:53:24 +00003445 } else {
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003446 res = wrapAsHidlRequest(requests[i], /*out*/&captureRequests[i],
3447 /*out*/&handlesCreated, /*out*/&inflightBuffers);
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003448 }
3449 if (res != OK) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003450 mBufferRecords.popInflightBuffers(inflightBuffers);
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003451 cleanupNativeHandles(&handlesCreated);
Yin-Chia Yeh651fe2e2018-11-13 11:49:31 -08003452 return res;
Emilian Peevaebbe412018-01-15 13:53:24 +00003453 }
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003454 }
3455
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003456 std::vector<device::V3_2::BufferCache> cachesToRemove;
3457 {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003458 std::lock_guard<std::mutex> lock(mFreedBuffersLock);
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003459 for (auto& pair : mFreedBuffers) {
3460 // The stream might have been removed since onBufferFreed
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003461 if (mBufferRecords.isStreamCached(pair.first)) {
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003462 cachesToRemove.push_back({pair.first, pair.second});
3463 }
3464 }
3465 mFreedBuffers.clear();
3466 }
3467
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003468 common::V1_0::Status status = common::V1_0::Status::INTERNAL_ERROR;
3469 *numRequestProcessed = 0;
Yifan Hongf79b5542017-04-11 14:44:25 -07003470
3471 // Write metadata to FMQ.
3472 for (size_t i = 0; i < batchSize; i++) {
3473 camera3_capture_request_t* request = requests[i];
Emilian Peevaebbe412018-01-15 13:53:24 +00003474 device::V3_2::CaptureRequest* captureRequest;
3475 if (hidlSession_3_4 != nullptr) {
3476 captureRequest = &captureRequests_3_4[i].v3_2;
3477 } else {
3478 captureRequest = &captureRequests[i];
3479 }
Yifan Hongf79b5542017-04-11 14:44:25 -07003480
3481 if (request->settings != nullptr) {
3482 size_t settingsSize = get_camera_metadata_size(request->settings);
3483 if (mRequestMetadataQueue != nullptr && mRequestMetadataQueue->write(
3484 reinterpret_cast<const uint8_t*>(request->settings), settingsSize)) {
3485 captureRequest->settings.resize(0);
3486 captureRequest->fmqSettingsSize = settingsSize;
3487 } else {
3488 if (mRequestMetadataQueue != nullptr) {
3489 ALOGW("%s: couldn't utilize fmq, fallback to hwbinder", __FUNCTION__);
3490 }
3491 captureRequest->settings.setToExternal(
3492 reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(request->settings)),
3493 get_camera_metadata_size(request->settings));
3494 captureRequest->fmqSettingsSize = 0u;
3495 }
3496 } else {
3497 // A null request settings maps to a size-0 CameraMetadata
3498 captureRequest->settings.resize(0);
3499 captureRequest->fmqSettingsSize = 0u;
3500 }
Emilian Peevaebbe412018-01-15 13:53:24 +00003501
3502 if (hidlSession_3_4 != nullptr) {
3503 captureRequests_3_4[i].physicalCameraSettings.resize(request->num_physcam_settings);
3504 for (size_t j = 0; j < request->num_physcam_settings; j++) {
Emilian Peev00420d22018-02-05 21:33:13 +00003505 if (request->physcam_settings != nullptr) {
3506 size_t settingsSize = get_camera_metadata_size(request->physcam_settings[j]);
3507 if (mRequestMetadataQueue != nullptr && mRequestMetadataQueue->write(
3508 reinterpret_cast<const uint8_t*>(request->physcam_settings[j]),
3509 settingsSize)) {
3510 captureRequests_3_4[i].physicalCameraSettings[j].settings.resize(0);
3511 captureRequests_3_4[i].physicalCameraSettings[j].fmqSettingsSize =
3512 settingsSize;
3513 } else {
3514 if (mRequestMetadataQueue != nullptr) {
3515 ALOGW("%s: couldn't utilize fmq, fallback to hwbinder", __FUNCTION__);
3516 }
3517 captureRequests_3_4[i].physicalCameraSettings[j].settings.setToExternal(
3518 reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(
3519 request->physcam_settings[j])),
3520 get_camera_metadata_size(request->physcam_settings[j]));
3521 captureRequests_3_4[i].physicalCameraSettings[j].fmqSettingsSize = 0u;
Emilian Peevaebbe412018-01-15 13:53:24 +00003522 }
Emilian Peev00420d22018-02-05 21:33:13 +00003523 } else {
Emilian Peevaebbe412018-01-15 13:53:24 +00003524 captureRequests_3_4[i].physicalCameraSettings[j].fmqSettingsSize = 0u;
Emilian Peev00420d22018-02-05 21:33:13 +00003525 captureRequests_3_4[i].physicalCameraSettings[j].settings.resize(0);
Emilian Peevaebbe412018-01-15 13:53:24 +00003526 }
3527 captureRequests_3_4[i].physicalCameraSettings[j].physicalCameraId =
3528 request->physcam_id[j];
3529 }
3530 }
Yifan Hongf79b5542017-04-11 14:44:25 -07003531 }
Emilian Peevaebbe412018-01-15 13:53:24 +00003532
3533 hardware::details::return_status err;
Jayant Chowdharyc8d581e2018-07-16 14:46:23 -07003534 auto resultCallback =
3535 [&status, &numRequestProcessed] (auto s, uint32_t n) {
3536 status = s;
3537 *numRequestProcessed = n;
3538 };
Emilian Peevaebbe412018-01-15 13:53:24 +00003539 if (hidlSession_3_4 != nullptr) {
3540 err = hidlSession_3_4->processCaptureRequest_3_4(captureRequests_3_4, cachesToRemove,
Jayant Chowdharyc8d581e2018-07-16 14:46:23 -07003541 resultCallback);
Emilian Peevaebbe412018-01-15 13:53:24 +00003542 } else {
3543 err = mHidlSession->processCaptureRequest(captureRequests, cachesToRemove,
Jayant Chowdharyc8d581e2018-07-16 14:46:23 -07003544 resultCallback);
Emilian Peevaebbe412018-01-15 13:53:24 +00003545 }
Eino-Ville Talvalac5cbb872017-04-27 12:48:33 -07003546 if (!err.isOk()) {
3547 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003548 status = common::V1_0::Status::CAMERA_DISCONNECTED;
Eino-Ville Talvalac5cbb872017-04-27 12:48:33 -07003549 }
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003550
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003551 if (status == common::V1_0::Status::OK && *numRequestProcessed != batchSize) {
3552 ALOGE("%s: processCaptureRequest returns OK but processed %d/%zu requests",
3553 __FUNCTION__, *numRequestProcessed, batchSize);
3554 status = common::V1_0::Status::INTERNAL_ERROR;
3555 }
3556
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003557 res = CameraProviderManager::mapToStatusT(status);
3558 if (res == OK) {
3559 if (mHidlSession->isRemote()) {
3560 // Only close acquire fence FDs when the HIDL transaction succeeds (so the FDs have been
3561 // sent to camera HAL processes)
3562 cleanupNativeHandles(&handlesCreated, /*closeFd*/true);
3563 } else {
3564 // In passthrough mode the FDs are now owned by HAL
3565 cleanupNativeHandles(&handlesCreated);
3566 }
3567 } else {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003568 mBufferRecords.popInflightBuffers(inflightBuffers);
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003569 cleanupNativeHandles(&handlesCreated);
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003570 }
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003571 return res;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003572}
3573
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003574status_t Camera3Device::HalInterface::flush() {
3575 ATRACE_NAME("CameraHal::flush");
3576 if (!valid()) return INVALID_OPERATION;
3577 status_t res = OK;
3578
Emilian Peev31abd0a2017-05-11 18:37:46 +01003579 auto err = mHidlSession->flush();
3580 if (!err.isOk()) {
3581 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3582 res = DEAD_OBJECT;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003583 } else {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003584 res = CameraProviderManager::mapToStatusT(err);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003585 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003586
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003587 return res;
3588}
3589
Emilian Peev31abd0a2017-05-11 18:37:46 +01003590status_t Camera3Device::HalInterface::dump(int /*fd*/) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003591 ATRACE_NAME("CameraHal::dump");
3592 if (!valid()) return INVALID_OPERATION;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003593
Emilian Peev31abd0a2017-05-11 18:37:46 +01003594 // Handled by CameraProviderManager::dump
3595
3596 return OK;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003597}
3598
3599status_t Camera3Device::HalInterface::close() {
3600 ATRACE_NAME("CameraHal::close()");
3601 if (!valid()) return INVALID_OPERATION;
3602 status_t res = OK;
3603
Emilian Peev31abd0a2017-05-11 18:37:46 +01003604 auto err = mHidlSession->close();
3605 // Interface will be dead shortly anyway, so don't log errors
3606 if (!err.isOk()) {
3607 res = DEAD_OBJECT;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003608 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003609
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003610 return res;
3611}
3612
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003613void Camera3Device::HalInterface::signalPipelineDrain(const std::vector<int>& streamIds) {
3614 ATRACE_NAME("CameraHal::signalPipelineDrain");
3615 if (!valid() || mHidlSession_3_5 == nullptr) {
3616 ALOGE("%s called on invalid camera!", __FUNCTION__);
3617 return;
3618 }
3619
Yin-Chia Yehc300a072019-02-13 14:56:57 -08003620 auto err = mHidlSession_3_5->signalStreamFlush(streamIds, mNextStreamConfigCounter - 1);
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003621 if (!err.isOk()) {
3622 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3623 return;
3624 }
3625}
3626
Yin-Chia Yehb978c382019-10-30 00:22:37 -07003627status_t Camera3Device::HalInterface::switchToOffline(
3628 const std::vector<int32_t>& streamsToKeep,
3629 /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003630 /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
3631 /*out*/camera3::BufferRecords* bufferRecords) {
Yin-Chia Yehb978c382019-10-30 00:22:37 -07003632 ATRACE_NAME("CameraHal::switchToOffline");
3633 if (!valid() || mHidlSession_3_6 == nullptr) {
3634 ALOGE("%s called on invalid camera!", __FUNCTION__);
3635 return INVALID_OPERATION;
3636 }
3637
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003638 if (offlineSessionInfo == nullptr || offlineSession == nullptr || bufferRecords == nullptr) {
3639 ALOGE("%s: output arguments must not be null!", __FUNCTION__);
Yin-Chia Yehb978c382019-10-30 00:22:37 -07003640 return INVALID_OPERATION;
3641 }
3642
3643 common::V1_0::Status status = common::V1_0::Status::INTERNAL_ERROR;
Yin-Chia Yehb978c382019-10-30 00:22:37 -07003644 auto resultCallback =
3645 [&status, &offlineSessionInfo, &offlineSession] (auto s, auto info, auto session) {
3646 status = s;
3647 *offlineSessionInfo = info;
3648 *offlineSession = session;
3649 };
3650 auto err = mHidlSession_3_6->switchToOffline(streamsToKeep, resultCallback);
3651
3652 if (!err.isOk()) {
3653 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3654 return DEAD_OBJECT;
3655 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003656
3657 status_t ret = CameraProviderManager::mapToStatusT(status);
3658 if (ret != OK) {
3659 return ret;
3660 }
3661
3662 // TODO: assert no ongoing requestBuffer/returnBuffer call here
3663 // TODO: update RequestBufferStateMachine to block requestBuffer/returnBuffer once HAL
3664 // returns from switchToOffline.
3665
3666
3667 // Validate buffer caches
3668 std::vector<int32_t> streams;
3669 streams.reserve(offlineSessionInfo->offlineStreams.size());
3670 for (auto offlineStream : offlineSessionInfo->offlineStreams) {
3671 int32_t id = offlineStream.id;
3672 streams.push_back(id);
3673 // Verify buffer caches
3674 std::vector<uint64_t> bufIds(offlineStream.circulatingBufferIds.begin(),
3675 offlineStream.circulatingBufferIds.end());
3676 if (!verifyBufferIds(id, bufIds)) {
3677 ALOGE("%s: stream ID %d buffer cache records mismatch!", __FUNCTION__, id);
3678 return UNKNOWN_ERROR;
3679 }
3680 }
3681
3682 // Move buffer records
3683 bufferRecords->takeBufferCaches(mBufferRecords, streams);
3684 bufferRecords->takeInflightBufferMap(mBufferRecords);
3685 bufferRecords->takeRequestedBufferMap(mBufferRecords);
3686 return ret;
Yin-Chia Yehb978c382019-10-30 00:22:37 -07003687}
3688
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07003689void Camera3Device::HalInterface::getInflightBufferKeys(
3690 std::vector<std::pair<int32_t, int32_t>>* out) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003691 mBufferRecords.getInflightBufferKeys(out);
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07003692 return;
3693}
3694
Yin-Chia Yeh84be5782019-03-01 11:47:02 -08003695void Camera3Device::HalInterface::getInflightRequestBufferKeys(
3696 std::vector<uint64_t>* out) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003697 mBufferRecords.getInflightRequestBufferKeys(out);
Yin-Chia Yeh84be5782019-03-01 11:47:02 -08003698 return;
3699}
3700
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003701bool Camera3Device::HalInterface::verifyBufferIds(
3702 int32_t streamId, std::vector<uint64_t>& bufIds) {
3703 return mBufferRecords.verifyBufferIds(streamId, bufIds);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003704}
3705
3706status_t Camera3Device::HalInterface::popInflightBuffer(
Yin-Chia Yehf4650602017-01-10 13:13:39 -08003707 int32_t frameNumber, int32_t streamId,
3708 /*out*/ buffer_handle_t **buffer) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003709 return mBufferRecords.popInflightBuffer(frameNumber, streamId, buffer);
Yin-Chia Yehf8e28fb2019-05-16 11:46:54 -07003710}
3711
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07003712status_t Camera3Device::HalInterface::pushInflightRequestBuffer(
Yin-Chia Yeh84be5782019-03-01 11:47:02 -08003713 uint64_t bufferId, buffer_handle_t* buf, int32_t streamId) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003714 return mBufferRecords.pushInflightRequestBuffer(bufferId, buf, streamId);
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07003715}
3716
3717// Find and pop a buffer_handle_t based on bufferId
3718status_t Camera3Device::HalInterface::popInflightRequestBuffer(
Yin-Chia Yeh84be5782019-03-01 11:47:02 -08003719 uint64_t bufferId,
3720 /*out*/ buffer_handle_t** buffer,
3721 /*optional out*/ int32_t* streamId) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003722 return mBufferRecords.popInflightRequestBuffer(bufferId, buffer, streamId);
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07003723}
3724
Yin-Chia Yeh77327052017-01-09 18:23:07 -08003725std::pair<bool, uint64_t> Camera3Device::HalInterface::getBufferId(
3726 const buffer_handle_t& buf, int streamId) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003727 return mBufferRecords.getBufferId(buf, streamId);
Yin-Chia Yeh77327052017-01-09 18:23:07 -08003728}
3729
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003730void Camera3Device::HalInterface::onBufferFreed(
3731 int streamId, const native_handle_t* handle) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003732 uint32_t bufferId = mBufferRecords.removeOneBufferCache(streamId, handle);
3733 std::lock_guard<std::mutex> lock(mFreedBuffersLock);
3734 if (bufferId != BUFFER_ID_NO_BUFFER) {
3735 mFreedBuffers.push_back(std::make_pair(streamId, bufferId));
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003736 }
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003737}
3738
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07003739void Camera3Device::HalInterface::onStreamReConfigured(int streamId) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08003740 std::vector<uint64_t> bufIds = mBufferRecords.clearBufferCaches(streamId);
3741 std::lock_guard<std::mutex> lock(mFreedBuffersLock);
3742 for (auto bufferId : bufIds) {
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07003743 mFreedBuffers.push_back(std::make_pair(streamId, bufferId));
3744 }
Yin-Chia Yeh573a2702019-04-17 10:08:55 -07003745}
3746
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003747/**
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003748 * RequestThread inner class methods
3749 */
3750
3751Camera3Device::RequestThread::RequestThread(wp<Camera3Device> parent,
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07003752 sp<StatusTracker> statusTracker,
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07003753 sp<HalInterface> interface, const Vector<int32_t>& sessionParamKeys,
3754 bool useHalBufManager) :
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07003755 Thread(/*canCallJava*/false),
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003756 mParent(parent),
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07003757 mStatusTracker(statusTracker),
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003758 mInterface(interface),
Eino-Ville Talvala77c1a352016-06-13 12:32:43 -07003759 mListener(nullptr),
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07003760 mId(getId(parent)),
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003761 mReconfigured(false),
3762 mDoPause(false),
3763 mPaused(true),
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07003764 mNotifyPipelineDrain(false),
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003765 mFrameNumber(0),
Jianing Weicb0652e2014-03-12 18:29:36 -07003766 mLatestRequestId(NAME_NOT_FOUND),
Yin-Chia Yehc00a25c2014-08-21 14:27:44 -07003767 mCurrentAfTriggerId(0),
3768 mCurrentPreCaptureTriggerId(0),
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08003769 mRotateAndCropOverride(ANDROID_SCALER_ROTATE_AND_CROP_NONE),
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003770 mRepeatingLastFrameNumber(
3771 hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES),
Shuzhen Wang686f6442017-06-20 16:16:04 -07003772 mPrepareVideoStream(false),
Emilian Peeva14b4dd2018-05-15 11:00:31 +01003773 mConstrainedMode(false),
Emilian Peevac3ce6c2017-12-12 15:27:02 +00003774 mRequestLatency(kRequestLatencyBinSize),
3775 mSessionParamKeys(sessionParamKeys),
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07003776 mLatestSessionParams(sessionParamKeys.size()),
3777 mUseHalBufManager(useHalBufManager) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07003778 mStatusId = statusTracker->addComponent();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003779}
3780
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003781Camera3Device::RequestThread::~RequestThread() {}
3782
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07003783void Camera3Device::RequestThread::setNotificationListener(
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07003784 wp<NotificationListener> listener) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003785 ATRACE_CALL();
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003786 Mutex::Autolock l(mRequestLock);
3787 mListener = listener;
3788}
3789
Emilian Peevac3ce6c2017-12-12 15:27:02 +00003790void Camera3Device::RequestThread::configurationComplete(bool isConstrainedHighSpeed,
3791 const CameraMetadata& sessionParams) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003792 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003793 Mutex::Autolock l(mRequestLock);
3794 mReconfigured = true;
Emilian Peevac3ce6c2017-12-12 15:27:02 +00003795 mLatestSessionParams = sessionParams;
Chien-Yu Chenc66969b2016-05-19 16:37:51 -07003796 // Prepare video stream for high speed recording.
3797 mPrepareVideoStream = isConstrainedHighSpeed;
Emilian Peeva14b4dd2018-05-15 11:00:31 +01003798 mConstrainedMode = isConstrainedHighSpeed;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003799}
3800
Jianing Wei90e59c92014-03-12 18:29:36 -07003801status_t Camera3Device::RequestThread::queueRequestList(
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003802 List<sp<CaptureRequest> > &requests,
3803 /*out*/
3804 int64_t *lastFrameNumber) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003805 ATRACE_CALL();
Jianing Wei90e59c92014-03-12 18:29:36 -07003806 Mutex::Autolock l(mRequestLock);
3807 for (List<sp<CaptureRequest> >::iterator it = requests.begin(); it != requests.end();
3808 ++it) {
3809 mRequestQueue.push_back(*it);
3810 }
3811
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003812 if (lastFrameNumber != NULL) {
3813 *lastFrameNumber = mFrameNumber + mRequestQueue.size() - 1;
3814 ALOGV("%s: requestId %d, mFrameNumber %" PRId32 ", lastFrameNumber %" PRId64 ".",
3815 __FUNCTION__, (*(requests.begin()))->mResultExtras.requestId, mFrameNumber,
3816 *lastFrameNumber);
3817 }
Jianing Weicb0652e2014-03-12 18:29:36 -07003818
Jianing Wei90e59c92014-03-12 18:29:36 -07003819 unpauseForNewRequests();
3820
3821 return OK;
3822}
3823
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003824
3825status_t Camera3Device::RequestThread::queueTrigger(
3826 RequestTrigger trigger[],
3827 size_t count) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003828 ATRACE_CALL();
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003829 Mutex::Autolock l(mTriggerMutex);
3830 status_t ret;
3831
3832 for (size_t i = 0; i < count; ++i) {
3833 ret = queueTriggerLocked(trigger[i]);
3834
3835 if (ret != OK) {
3836 return ret;
3837 }
3838 }
3839
3840 return OK;
3841}
3842
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003843const String8& Camera3Device::RequestThread::getId(const wp<Camera3Device> &device) {
3844 static String8 deadId("<DeadDevice>");
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07003845 sp<Camera3Device> d = device.promote();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003846 if (d != nullptr) return d->mId;
3847 return deadId;
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07003848}
3849
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003850status_t Camera3Device::RequestThread::queueTriggerLocked(
3851 RequestTrigger trigger) {
3852
3853 uint32_t tag = trigger.metadataTag;
3854 ssize_t index = mTriggerMap.indexOfKey(tag);
3855
3856 switch (trigger.getTagType()) {
3857 case TYPE_BYTE:
3858 // fall-through
3859 case TYPE_INT32:
3860 break;
3861 default:
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07003862 ALOGE("%s: Type not supported: 0x%x", __FUNCTION__,
3863 trigger.getTagType());
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003864 return INVALID_OPERATION;
3865 }
3866
3867 /**
3868 * Collect only the latest trigger, since we only have 1 field
3869 * in the request settings per trigger tag, and can't send more than 1
3870 * trigger per request.
3871 */
3872 if (index != NAME_NOT_FOUND) {
3873 mTriggerMap.editValueAt(index) = trigger;
3874 } else {
3875 mTriggerMap.add(tag, trigger);
3876 }
3877
3878 return OK;
3879}
3880
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003881status_t Camera3Device::RequestThread::setRepeatingRequests(
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003882 const RequestList &requests,
3883 /*out*/
3884 int64_t *lastFrameNumber) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003885 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003886 Mutex::Autolock l(mRequestLock);
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003887 if (lastFrameNumber != NULL) {
3888 *lastFrameNumber = mRepeatingLastFrameNumber;
3889 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003890 mRepeatingRequests.clear();
3891 mRepeatingRequests.insert(mRepeatingRequests.begin(),
3892 requests.begin(), requests.end());
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07003893
3894 unpauseForNewRequests();
3895
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003896 mRepeatingLastFrameNumber = hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003897 return OK;
3898}
3899
Chih-Hung Hsieh8b0b9712016-08-09 14:25:53 -07003900bool Camera3Device::RequestThread::isRepeatingRequestLocked(const sp<CaptureRequest>& requestIn) {
Yin-Chia Yeh8684b7f2014-06-13 14:53:05 -07003901 if (mRepeatingRequests.empty()) {
3902 return false;
3903 }
3904 int32_t requestId = requestIn->mResultExtras.requestId;
3905 const RequestList &repeatRequests = mRepeatingRequests;
3906 // All repeating requests are guaranteed to have same id so only check first quest
3907 const sp<CaptureRequest> firstRequest = *repeatRequests.begin();
3908 return (firstRequest->mResultExtras.requestId == requestId);
3909}
3910
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003911status_t Camera3Device::RequestThread::clearRepeatingRequests(/*out*/int64_t *lastFrameNumber) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003912 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003913 Mutex::Autolock l(mRequestLock);
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07003914 return clearRepeatingRequestsLocked(lastFrameNumber);
3915
3916}
3917
3918status_t Camera3Device::RequestThread::clearRepeatingRequestsLocked(/*out*/int64_t *lastFrameNumber) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003919 mRepeatingRequests.clear();
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003920 if (lastFrameNumber != NULL) {
3921 *lastFrameNumber = mRepeatingLastFrameNumber;
3922 }
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003923 mRepeatingLastFrameNumber = hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003924 return OK;
3925}
3926
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003927status_t Camera3Device::RequestThread::clear(
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003928 /*out*/int64_t *lastFrameNumber) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003929 ATRACE_CALL();
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07003930 Mutex::Autolock l(mRequestLock);
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003931 ALOGV("RequestThread::%s:", __FUNCTION__);
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003932
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07003933 mRepeatingRequests.clear();
Yin-Chia Yeh8684b7f2014-06-13 14:53:05 -07003934
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003935 // Send errors for all requests pending in the request queue, including
3936 // pending repeating requests
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07003937 sp<NotificationListener> listener = mListener.promote();
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003938 if (listener != NULL) {
3939 for (RequestList::iterator it = mRequestQueue.begin();
3940 it != mRequestQueue.end(); ++it) {
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07003941 // Abort the input buffers for reprocess requests.
3942 if ((*it)->mInputStream != NULL) {
3943 camera3_stream_buffer_t inputBuffer;
Eino-Ville Talvalaba435252017-06-21 16:07:25 -07003944 status_t res = (*it)->mInputStream->getInputBuffer(&inputBuffer,
3945 /*respectHalLimit*/ false);
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07003946 if (res != OK) {
3947 ALOGW("%s: %d: couldn't get input buffer while clearing the request "
3948 "list: %s (%d)", __FUNCTION__, __LINE__, strerror(-res), res);
3949 } else {
Shuzhen Wang0cf01cb2019-09-05 13:33:06 -07003950 inputBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07003951 res = (*it)->mInputStream->returnInputBuffer(inputBuffer);
3952 if (res != OK) {
3953 ALOGE("%s: %d: couldn't return input buffer while clearing the request "
3954 "list: %s (%d)", __FUNCTION__, __LINE__, strerror(-res), res);
3955 }
3956 }
3957 }
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003958 // Set the frame number this request would have had, if it
3959 // had been submitted; this frame number will not be reused.
3960 // The requestId and burstId fields were set when the request was
3961 // submitted originally (in convertMetadataListToRequestListLocked)
3962 (*it)->mResultExtras.frameNumber = mFrameNumber++;
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003963 listener->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003964 (*it)->mResultExtras);
Yin-Chia Yeh8684b7f2014-06-13 14:53:05 -07003965 }
3966 }
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07003967 mRequestQueue.clear();
Jinguang Dongb26e7a02016-11-14 16:04:02 +08003968
3969 Mutex::Autolock al(mTriggerMutex);
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07003970 mTriggerMap.clear();
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003971 if (lastFrameNumber != NULL) {
3972 *lastFrameNumber = mRepeatingLastFrameNumber;
3973 }
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003974 mRepeatingLastFrameNumber = hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES;
Emilian Peev8dae54c2019-12-02 15:17:17 -08003975 mRequestSignal.signal();
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07003976 return OK;
3977}
3978
Chien-Yu Chen85a64552015-08-28 15:46:12 -07003979status_t Camera3Device::RequestThread::flush() {
3980 ATRACE_CALL();
3981 Mutex::Autolock l(mFlushLock);
3982
Emilian Peev08dd2452017-04-06 16:55:14 +01003983 return mInterface->flush();
Chien-Yu Chen85a64552015-08-28 15:46:12 -07003984}
3985
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003986void Camera3Device::RequestThread::setPaused(bool paused) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003987 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003988 Mutex::Autolock l(mPauseLock);
3989 mDoPause = paused;
3990 mDoPauseSignal.signal();
3991}
3992
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003993status_t Camera3Device::RequestThread::waitUntilRequestProcessed(
3994 int32_t requestId, nsecs_t timeout) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003995 ATRACE_CALL();
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003996 Mutex::Autolock l(mLatestRequestMutex);
3997 status_t res;
3998 while (mLatestRequestId != requestId) {
3999 nsecs_t startTime = systemTime();
4000
4001 res = mLatestRequestSignal.waitRelative(mLatestRequestMutex, timeout);
4002 if (res != OK) return res;
4003
4004 timeout -= (systemTime() - startTime);
4005 }
4006
4007 return OK;
4008}
4009
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004010void Camera3Device::RequestThread::requestExit() {
4011 // Call parent to set up shutdown
4012 Thread::requestExit();
4013 // The exit from any possible waits
4014 mDoPauseSignal.signal();
4015 mRequestSignal.signal();
Shuzhen Wang686f6442017-06-20 16:16:04 -07004016
4017 mRequestLatency.log("ProcessCaptureRequest latency histogram");
4018 mRequestLatency.reset();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004019}
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004020
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07004021void Camera3Device::RequestThread::checkAndStopRepeatingRequest() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004022 ATRACE_CALL();
Yin-Chia Yeh473fad92016-05-23 15:54:41 -07004023 bool surfaceAbandoned = false;
4024 int64_t lastFrameNumber = 0;
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07004025 sp<NotificationListener> listener;
Yin-Chia Yeh473fad92016-05-23 15:54:41 -07004026 {
4027 Mutex::Autolock l(mRequestLock);
4028 // Check all streams needed by repeating requests are still valid. Otherwise, stop
4029 // repeating requests.
4030 for (const auto& request : mRepeatingRequests) {
4031 for (const auto& s : request->mOutputStreams) {
4032 if (s->isAbandoned()) {
4033 surfaceAbandoned = true;
4034 clearRepeatingRequestsLocked(&lastFrameNumber);
4035 break;
4036 }
4037 }
4038 if (surfaceAbandoned) {
4039 break;
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07004040 }
4041 }
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07004042 listener = mListener.promote();
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07004043 }
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07004044
4045 if (listener != NULL && surfaceAbandoned) {
4046 listener->notifyRepeatingRequestError(lastFrameNumber);
Yin-Chia Yeh473fad92016-05-23 15:54:41 -07004047 }
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07004048}
4049
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004050bool Camera3Device::RequestThread::sendRequestsBatch() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004051 ATRACE_CALL();
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004052 status_t res;
4053 size_t batchSize = mNextRequests.size();
4054 std::vector<camera3_capture_request_t*> requests(batchSize);
4055 uint32_t numRequestProcessed = 0;
4056 for (size_t i = 0; i < batchSize; i++) {
4057 requests[i] = &mNextRequests.editItemAt(i).halRequest;
Yin-Chia Yeh885691c2018-05-01 15:54:24 -07004058 ATRACE_ASYNC_BEGIN("frame capture", mNextRequests[i].halRequest.frame_number);
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004059 }
4060
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004061 res = mInterface->processBatchCaptureRequests(requests, &numRequestProcessed);
4062
4063 bool triggerRemoveFailed = false;
4064 NextRequest& triggerFailedRequest = mNextRequests.editItemAt(0);
4065 for (size_t i = 0; i < numRequestProcessed; i++) {
4066 NextRequest& nextRequest = mNextRequests.editItemAt(i);
4067 nextRequest.submitted = true;
4068
Shuzhen Wangc2cba122018-05-17 18:10:24 -07004069 updateNextRequest(nextRequest);
Emilian Peevaebbe412018-01-15 13:53:24 +00004070
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004071 if (!triggerRemoveFailed) {
4072 // Remove any previously queued triggers (after unlock)
4073 status_t removeTriggerRes = removeTriggers(mPrevRequest);
4074 if (removeTriggerRes != OK) {
4075 triggerRemoveFailed = true;
4076 triggerFailedRequest = nextRequest;
4077 }
4078 }
4079 }
4080
4081 if (triggerRemoveFailed) {
4082 SET_ERR("RequestThread: Unable to remove triggers "
4083 "(capture request %d, HAL device: %s (%d)",
4084 triggerFailedRequest.halRequest.frame_number, strerror(-res), res);
4085 cleanUpFailedRequests(/*sendRequestError*/ false);
4086 return false;
4087 }
4088
4089 if (res != OK) {
4090 // Should only get a failure here for malformed requests or device-level
4091 // errors, so consider all errors fatal. Bad metadata failures should
4092 // come through notify.
4093 SET_ERR("RequestThread: Unable to submit capture request %d to HAL device: %s (%d)",
4094 mNextRequests[numRequestProcessed].halRequest.frame_number,
4095 strerror(-res), res);
4096 cleanUpFailedRequests(/*sendRequestError*/ false);
4097 return false;
4098 }
4099 return true;
4100}
4101
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07004102nsecs_t Camera3Device::RequestThread::calculateMaxExpectedDuration(const camera_metadata_t *request) {
4103 nsecs_t maxExpectedDuration = kDefaultExpectedDuration;
4104 camera_metadata_ro_entry_t e = camera_metadata_ro_entry_t();
4105 find_camera_metadata_ro_entry(request,
4106 ANDROID_CONTROL_AE_MODE,
4107 &e);
4108 if (e.count == 0) return maxExpectedDuration;
4109
4110 switch (e.data.u8[0]) {
4111 case ANDROID_CONTROL_AE_MODE_OFF:
4112 find_camera_metadata_ro_entry(request,
4113 ANDROID_SENSOR_EXPOSURE_TIME,
4114 &e);
4115 if (e.count > 0) {
4116 maxExpectedDuration = e.data.i64[0];
4117 }
4118 find_camera_metadata_ro_entry(request,
4119 ANDROID_SENSOR_FRAME_DURATION,
4120 &e);
4121 if (e.count > 0) {
4122 maxExpectedDuration = std::max(e.data.i64[0], maxExpectedDuration);
4123 }
4124 break;
4125 default:
4126 find_camera_metadata_ro_entry(request,
4127 ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
4128 &e);
4129 if (e.count > 1) {
4130 maxExpectedDuration = 1e9 / e.data.u8[0];
4131 }
4132 break;
4133 }
4134
4135 return maxExpectedDuration;
4136}
4137
Emilian Peeva14b4dd2018-05-15 11:00:31 +01004138bool Camera3Device::RequestThread::skipHFRTargetFPSUpdate(int32_t tag,
4139 const camera_metadata_ro_entry_t& newEntry, const camera_metadata_entry_t& currentEntry) {
4140 if (mConstrainedMode && (ANDROID_CONTROL_AE_TARGET_FPS_RANGE == tag) &&
4141 (newEntry.count == currentEntry.count) && (currentEntry.count == 2) &&
4142 (currentEntry.data.i32[1] == newEntry.data.i32[1])) {
4143 return true;
4144 }
4145
4146 return false;
4147}
4148
Shuzhen Wangc2cba122018-05-17 18:10:24 -07004149void Camera3Device::RequestThread::updateNextRequest(NextRequest& nextRequest) {
4150 // Update the latest request sent to HAL
4151 if (nextRequest.halRequest.settings != NULL) { // Don't update if they were unchanged
4152 Mutex::Autolock al(mLatestRequestMutex);
4153
4154 camera_metadata_t* cloned = clone_camera_metadata(nextRequest.halRequest.settings);
4155 mLatestRequest.acquire(cloned);
4156
4157 mLatestPhysicalRequest.clear();
4158 for (uint32_t i = 0; i < nextRequest.halRequest.num_physcam_settings; i++) {
4159 cloned = clone_camera_metadata(nextRequest.halRequest.physcam_settings[i]);
4160 mLatestPhysicalRequest.emplace(nextRequest.halRequest.physcam_id[i],
4161 CameraMetadata(cloned));
4162 }
4163
4164 sp<Camera3Device> parent = mParent.promote();
4165 if (parent != NULL) {
4166 parent->monitorMetadata(TagMonitor::REQUEST,
4167 nextRequest.halRequest.frame_number,
4168 0, mLatestRequest, mLatestPhysicalRequest);
4169 }
4170 }
4171
4172 if (nextRequest.halRequest.settings != NULL) {
4173 nextRequest.captureRequest->mSettingsList.begin()->metadata.unlock(
4174 nextRequest.halRequest.settings);
4175 }
4176
4177 cleanupPhysicalSettings(nextRequest.captureRequest, &nextRequest.halRequest);
4178}
4179
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004180bool Camera3Device::RequestThread::updateSessionParameters(const CameraMetadata& settings) {
4181 ATRACE_CALL();
4182 bool updatesDetected = false;
4183
Emilian Peev4ec17882019-01-24 17:16:58 -08004184 CameraMetadata updatedParams(mLatestSessionParams);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004185 for (auto tag : mSessionParamKeys) {
4186 camera_metadata_ro_entry entry = settings.find(tag);
Emilian Peev4ec17882019-01-24 17:16:58 -08004187 camera_metadata_entry lastEntry = updatedParams.find(tag);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004188
4189 if (entry.count > 0) {
4190 bool isDifferent = false;
4191 if (lastEntry.count > 0) {
4192 // Have a last value, compare to see if changed
4193 if (lastEntry.type == entry.type &&
4194 lastEntry.count == entry.count) {
4195 // Same type and count, compare values
4196 size_t bytesPerValue = camera_metadata_type_size[lastEntry.type];
4197 size_t entryBytes = bytesPerValue * lastEntry.count;
4198 int cmp = memcmp(entry.data.u8, lastEntry.data.u8, entryBytes);
4199 if (cmp != 0) {
4200 isDifferent = true;
4201 }
4202 } else {
4203 // Count or type has changed
4204 isDifferent = true;
4205 }
4206 } else {
4207 // No last entry, so always consider to be different
4208 isDifferent = true;
4209 }
4210
4211 if (isDifferent) {
4212 ALOGV("%s: Session parameter tag id %d changed", __FUNCTION__, tag);
Emilian Peeva14b4dd2018-05-15 11:00:31 +01004213 if (!skipHFRTargetFPSUpdate(tag, entry, lastEntry)) {
4214 updatesDetected = true;
4215 }
Emilian Peev4ec17882019-01-24 17:16:58 -08004216 updatedParams.update(entry);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004217 }
4218 } else if (lastEntry.count > 0) {
4219 // Value has been removed
4220 ALOGV("%s: Session parameter tag id %d removed", __FUNCTION__, tag);
Emilian Peev4ec17882019-01-24 17:16:58 -08004221 updatedParams.erase(tag);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004222 updatesDetected = true;
4223 }
4224 }
4225
Emilian Peev4ec17882019-01-24 17:16:58 -08004226 bool reconfigureRequired;
4227 if (updatesDetected) {
4228 reconfigureRequired = mInterface->isReconfigurationRequired(mLatestSessionParams,
4229 updatedParams);
4230 mLatestSessionParams = updatedParams;
4231 } else {
4232 reconfigureRequired = false;
4233 }
4234
4235 return reconfigureRequired;
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004236}
4237
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004238bool Camera3Device::RequestThread::threadLoop() {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004239 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004240 status_t res;
Jayant Chowdhary37eca242019-11-18 08:55:56 -08004241 // Any function called from threadLoop() must not hold mInterfaceLock since
4242 // it could lead to deadlocks (disconnect() -> hold mInterfaceMutex -> wait for request thread
4243 // to finish -> request thread waits on mInterfaceMutex) http://b/143513518
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004244
4245 // Handle paused state.
4246 if (waitIfPaused()) {
4247 return true;
4248 }
4249
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004250 // Wait for the next batch of requests.
4251 waitForNextRequestBatch();
4252 if (mNextRequests.size() == 0) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004253 return true;
4254 }
4255
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004256 // Get the latest request ID, if any
4257 int latestRequestId;
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004258 camera_metadata_entry_t requestIdEntry = mNextRequests[mNextRequests.size() - 1].
Emilian Peevaebbe412018-01-15 13:53:24 +00004259 captureRequest->mSettingsList.begin()->metadata.find(ANDROID_REQUEST_ID);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004260 if (requestIdEntry.count > 0) {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004261 latestRequestId = requestIdEntry.data.i32[0];
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004262 } else {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004263 ALOGW("%s: Did not have android.request.id set in the request.", __FUNCTION__);
4264 latestRequestId = NAME_NOT_FOUND;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004265 }
4266
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004267 // 'mNextRequests' will at this point contain either a set of HFR batched requests
4268 // or a single request from streaming or burst. In either case the first element
4269 // should contain the latest camera settings that we need to check for any session
4270 // parameter updates.
Emilian Peevaebbe412018-01-15 13:53:24 +00004271 if (updateSessionParameters(mNextRequests[0].captureRequest->mSettingsList.begin()->metadata)) {
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004272 res = OK;
4273
4274 //Input stream buffers are already acquired at this point so an input stream
4275 //will not be able to move to idle state unless we force it.
4276 if (mNextRequests[0].captureRequest->mInputStream != nullptr) {
4277 res = mNextRequests[0].captureRequest->mInputStream->forceToIdle();
4278 if (res != OK) {
4279 ALOGE("%s: Failed to force idle input stream: %d", __FUNCTION__, res);
4280 cleanUpFailedRequests(/*sendRequestError*/ false);
4281 return false;
4282 }
4283 }
4284
4285 if (res == OK) {
Emilian Peev3bead5f2020-05-28 17:29:08 -07004286 sp<Camera3Device> parent = mParent.promote();
4287 if (parent != nullptr) {
4288 mReconfigured |= parent->reconfigureCamera(mLatestSessionParams, mStatusId);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004289 }
Emilian Peev3bead5f2020-05-28 17:29:08 -07004290 setPaused(false);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004291
4292 if (mNextRequests[0].captureRequest->mInputStream != nullptr) {
4293 mNextRequests[0].captureRequest->mInputStream->restoreConfiguredState();
4294 if (res != OK) {
4295 ALOGE("%s: Failed to restore configured input stream: %d", __FUNCTION__, res);
4296 cleanUpFailedRequests(/*sendRequestError*/ false);
4297 return false;
4298 }
4299 }
4300 }
4301 }
4302
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004303 // Prepare a batch of HAL requests and output buffers.
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004304 res = prepareHalRequests();
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004305 if (res == TIMED_OUT) {
4306 // Not a fatal error if getting output buffers time out.
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004307 cleanUpFailedRequests(/*sendRequestError*/ true);
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07004308 // Check if any stream is abandoned.
4309 checkAndStopRepeatingRequest();
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004310 return true;
4311 } else if (res != OK) {
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004312 cleanUpFailedRequests(/*sendRequestError*/ false);
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07004313 return false;
4314 }
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004315
Zhijun Hecc27e112013-10-03 16:12:43 -07004316 // Inform waitUntilRequestProcessed thread of a new request ID
4317 {
4318 Mutex::Autolock al(mLatestRequestMutex);
4319
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004320 mLatestRequestId = latestRequestId;
Zhijun Hecc27e112013-10-03 16:12:43 -07004321 mLatestRequestSignal.signal();
4322 }
4323
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004324 // Submit a batch of requests to HAL.
4325 // Use flush lock only when submitting multilple requests in a batch.
4326 // TODO: The problem with flush lock is flush() will be blocked by process_capture_request()
4327 // which may take a long time to finish so synchronizing flush() and
4328 // process_capture_request() defeats the purpose of cancelling requests ASAP with flush().
4329 // For now, only synchronize for high speed recording and we should figure something out for
4330 // removing the synchronization.
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004331 bool useFlushLock = mNextRequests.size() > 1;
Eino-Ville Talvala17a61ad2013-06-03 16:53:32 -07004332
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004333 if (useFlushLock) {
4334 mFlushLock.lock();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004335 }
4336
Zhijun Hef0645c12016-08-02 00:58:11 -07004337 ALOGVV("%s: %d: submitting %zu requests in a batch.", __FUNCTION__, __LINE__,
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004338 mNextRequests.size());
Igor Murashkin1e479c02013-09-06 16:55:14 -07004339
Yin-Chia Yehcd333fe2019-02-08 13:45:41 -08004340 sp<Camera3Device> parent = mParent.promote();
4341 if (parent != nullptr) {
4342 parent->mRequestBufferSM.onSubmittingRequest();
4343 }
4344
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004345 bool submitRequestSuccess = false;
Shuzhen Wang686f6442017-06-20 16:16:04 -07004346 nsecs_t tRequestStart = systemTime(SYSTEM_TIME_MONOTONIC);
Yin-Chia Yeh11648852019-05-16 10:42:54 -07004347 submitRequestSuccess = sendRequestsBatch();
4348
Shuzhen Wang686f6442017-06-20 16:16:04 -07004349 nsecs_t tRequestEnd = systemTime(SYSTEM_TIME_MONOTONIC);
4350 mRequestLatency.add(tRequestStart, tRequestEnd);
Igor Murashkin1e479c02013-09-06 16:55:14 -07004351
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004352 if (useFlushLock) {
4353 mFlushLock.unlock();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004354 }
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004355
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004356 // Unset as current request
4357 {
4358 Mutex::Autolock l(mRequestLock);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004359 mNextRequests.clear();
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004360 }
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004361 mRequestSubmittedSignal.signal();
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004362
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004363 return submitRequestSuccess;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004364}
4365
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004366status_t Camera3Device::RequestThread::prepareHalRequests() {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004367 ATRACE_CALL();
4368
Yin-Chia Yehd07b11e2018-06-01 12:50:02 -07004369 bool batchedRequest = mNextRequests[0].captureRequest->mBatchSize > 1;
Shuzhen Wang4a472662017-02-26 23:29:04 -08004370 for (size_t i = 0; i < mNextRequests.size(); i++) {
4371 auto& nextRequest = mNextRequests.editItemAt(i);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004372 sp<CaptureRequest> captureRequest = nextRequest.captureRequest;
4373 camera3_capture_request_t* halRequest = &nextRequest.halRequest;
4374 Vector<camera3_stream_buffer_t>* outputBuffers = &nextRequest.outputBuffers;
4375
4376 // Prepare a request to HAL
4377 halRequest->frame_number = captureRequest->mResultExtras.frameNumber;
4378
4379 // Insert any queued triggers (before metadata is locked)
4380 status_t res = insertTriggers(captureRequest);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004381 if (res < 0) {
4382 SET_ERR("RequestThread: Unable to insert triggers "
4383 "(capture request %d, HAL device: %s (%d)",
4384 halRequest->frame_number, strerror(-res), res);
4385 return INVALID_OPERATION;
4386 }
Eino-Ville Talvala7b8a1fd2018-05-22 15:30:35 -07004387
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004388 int triggerCount = res;
4389 bool triggersMixedIn = (triggerCount > 0 || mPrevTriggers > 0);
4390 mPrevTriggers = triggerCount;
4391
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08004392 bool rotateAndCropChanged = overrideAutoRotateAndCrop(captureRequest);
4393
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004394 // If the request is the same as last, or we had triggers last time
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08004395 bool newRequest =
4396 (mPrevRequest != captureRequest || triggersMixedIn || rotateAndCropChanged) &&
Yin-Chia Yehd07b11e2018-06-01 12:50:02 -07004397 // Request settings are all the same within one batch, so only treat the first
4398 // request in a batch as new
Zhijun He54c36822018-07-18 09:33:39 -07004399 !(batchedRequest && i > 0);
Emilian Peev00420d22018-02-05 21:33:13 +00004400 if (newRequest) {
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08004401 std::set<std::string> cameraIdsWithZoom;
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004402 /**
4403 * HAL workaround:
4404 * Insert a dummy trigger ID if a trigger is set but no trigger ID is
4405 */
4406 res = addDummyTriggerIds(captureRequest);
4407 if (res != OK) {
4408 SET_ERR("RequestThread: Unable to insert dummy trigger IDs "
4409 "(capture request %d, HAL device: %s (%d)",
4410 halRequest->frame_number, strerror(-res), res);
4411 return INVALID_OPERATION;
4412 }
4413
Eino-Ville Talvala7b8a1fd2018-05-22 15:30:35 -07004414 {
4415 // Correct metadata regions for distortion correction if enabled
4416 sp<Camera3Device> parent = mParent.promote();
4417 if (parent != nullptr) {
Shuzhen Wang4f6fa9d2019-03-29 10:40:35 -07004418 List<PhysicalCameraSettings>::iterator it;
4419 for (it = captureRequest->mSettingsList.begin();
4420 it != captureRequest->mSettingsList.end(); it++) {
4421 if (parent->mDistortionMappers.find(it->cameraId) ==
4422 parent->mDistortionMappers.end()) {
4423 continue;
4424 }
4425 res = parent->mDistortionMappers[it->cameraId].correctCaptureRequest(
4426 &(it->metadata));
4427 if (res != OK) {
4428 SET_ERR("RequestThread: Unable to correct capture requests "
4429 "for lens distortion for request %d: %s (%d)",
4430 halRequest->frame_number, strerror(-res), res);
4431 return INVALID_OPERATION;
4432 }
Eino-Ville Talvala7b8a1fd2018-05-22 15:30:35 -07004433 }
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08004434
4435 for (it = captureRequest->mSettingsList.begin();
4436 it != captureRequest->mSettingsList.end(); it++) {
4437 if (parent->mZoomRatioMappers.find(it->cameraId) ==
4438 parent->mZoomRatioMappers.end()) {
4439 continue;
4440 }
4441
4442 camera_metadata_entry_t e = it->metadata.find(ANDROID_CONTROL_ZOOM_RATIO);
4443 if (e.count > 0 && e.data.f[0] != 1.0f) {
4444 cameraIdsWithZoom.insert(it->cameraId);
4445 }
4446
4447 res = parent->mZoomRatioMappers[it->cameraId].updateCaptureRequest(
4448 &(it->metadata));
4449 if (res != OK) {
4450 SET_ERR("RequestThread: Unable to correct capture requests "
4451 "for zoom ratio for request %d: %s (%d)",
4452 halRequest->frame_number, strerror(-res), res);
4453 return INVALID_OPERATION;
4454 }
4455 }
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08004456 if (captureRequest->mRotateAndCropAuto) {
4457 for (it = captureRequest->mSettingsList.begin();
4458 it != captureRequest->mSettingsList.end(); it++) {
4459 auto mapper = parent->mRotateAndCropMappers.find(it->cameraId);
4460 if (mapper != parent->mRotateAndCropMappers.end()) {
4461 res = mapper->second.updateCaptureRequest(&(it->metadata));
4462 if (res != OK) {
4463 SET_ERR("RequestThread: Unable to correct capture requests "
4464 "for rotate-and-crop for request %d: %s (%d)",
4465 halRequest->frame_number, strerror(-res), res);
4466 return INVALID_OPERATION;
4467 }
4468 }
4469 }
4470 }
Eino-Ville Talvala7b8a1fd2018-05-22 15:30:35 -07004471 }
4472 }
4473
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004474 /**
4475 * The request should be presorted so accesses in HAL
4476 * are O(logn). Sidenote, sorting a sorted metadata is nop.
4477 */
Emilian Peevaebbe412018-01-15 13:53:24 +00004478 captureRequest->mSettingsList.begin()->metadata.sort();
4479 halRequest->settings = captureRequest->mSettingsList.begin()->metadata.getAndLock();
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004480 mPrevRequest = captureRequest;
Shuzhen Wangdbdf72b2019-11-13 11:22:12 -08004481 mPrevCameraIdsWithZoom = cameraIdsWithZoom;
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004482 ALOGVV("%s: Request settings are NEW", __FUNCTION__);
4483
4484 IF_ALOGV() {
4485 camera_metadata_ro_entry_t e = camera_metadata_ro_entry_t();
4486 find_camera_metadata_ro_entry(
4487 halRequest->settings,
4488 ANDROID_CONTROL_AF_TRIGGER,
4489 &e
4490 );
4491 if (e.count > 0) {
4492 ALOGV("%s: Request (frame num %d) had AF trigger 0x%x",
4493 __FUNCTION__,
4494 halRequest->frame_number,
4495 e.data.u8[0]);
4496 }
4497 }
4498 } else {
4499 // leave request.settings NULL to indicate 'reuse latest given'
4500 ALOGVV("%s: Request settings are REUSED",
4501 __FUNCTION__);
4502 }
4503
Emilian Peevaebbe412018-01-15 13:53:24 +00004504 if (captureRequest->mSettingsList.size() > 1) {
4505 halRequest->num_physcam_settings = captureRequest->mSettingsList.size() - 1;
4506 halRequest->physcam_id = new const char* [halRequest->num_physcam_settings];
Emilian Peev00420d22018-02-05 21:33:13 +00004507 if (newRequest) {
4508 halRequest->physcam_settings =
4509 new const camera_metadata* [halRequest->num_physcam_settings];
4510 } else {
4511 halRequest->physcam_settings = nullptr;
4512 }
Emilian Peevaebbe412018-01-15 13:53:24 +00004513 auto it = ++captureRequest->mSettingsList.begin();
4514 size_t i = 0;
4515 for (; it != captureRequest->mSettingsList.end(); it++, i++) {
4516 halRequest->physcam_id[i] = it->cameraId.c_str();
Emilian Peev00420d22018-02-05 21:33:13 +00004517 if (newRequest) {
4518 it->metadata.sort();
4519 halRequest->physcam_settings[i] = it->metadata.getAndLock();
4520 }
Emilian Peevaebbe412018-01-15 13:53:24 +00004521 }
4522 }
4523
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004524 uint32_t totalNumBuffers = 0;
4525
4526 // Fill in buffers
4527 if (captureRequest->mInputStream != NULL) {
4528 halRequest->input_buffer = &captureRequest->mInputBuffer;
4529 totalNumBuffers += 1;
4530 } else {
4531 halRequest->input_buffer = NULL;
4532 }
4533
4534 outputBuffers->insertAt(camera3_stream_buffer_t(), 0,
4535 captureRequest->mOutputStreams.size());
4536 halRequest->output_buffers = outputBuffers->array();
Shuzhen Wang5c22c152017-12-31 17:12:25 -08004537 std::set<String8> requestedPhysicalCameras;
Yin-Chia Yehb3a80b12018-09-04 12:13:05 -07004538
4539 sp<Camera3Device> parent = mParent.promote();
4540 if (parent == NULL) {
4541 // Should not happen, and nowhere to send errors to, so just log it
4542 CLOGE("RequestThread: Parent is gone");
4543 return INVALID_OPERATION;
4544 }
4545 nsecs_t waitDuration = kBaseGetBufferWait + parent->getExpectedInFlightDuration();
4546
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004547 SurfaceMap uniqueSurfaceIdMap;
Shuzhen Wang4a472662017-02-26 23:29:04 -08004548 for (size_t j = 0; j < captureRequest->mOutputStreams.size(); j++) {
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004549 sp<Camera3OutputStreamInterface> outputStream =
4550 captureRequest->mOutputStreams.editItemAt(j);
4551 int streamId = outputStream->getId();
Chien-Yu Chenc66969b2016-05-19 16:37:51 -07004552
4553 // Prepare video buffers for high speed recording on the first video request.
4554 if (mPrepareVideoStream && outputStream->isVideoStream()) {
4555 // Only try to prepare video stream on the first video request.
4556 mPrepareVideoStream = false;
4557
Shuzhen Wangb3a0fb52018-09-13 17:24:08 -07004558 res = outputStream->startPrepare(Camera3StreamInterface::ALLOCATE_PIPELINE_MAX,
4559 false /*blockRequest*/);
Chien-Yu Chenc66969b2016-05-19 16:37:51 -07004560 while (res == NOT_ENOUGH_DATA) {
4561 res = outputStream->prepareNextBuffer();
4562 }
4563 if (res != OK) {
4564 ALOGW("%s: Preparing video buffers for high speed failed: %s (%d)",
4565 __FUNCTION__, strerror(-res), res);
4566 outputStream->cancelPrepare();
4567 }
4568 }
4569
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004570 std::vector<size_t> uniqueSurfaceIds;
4571 res = outputStream->getUniqueSurfaceIds(
4572 captureRequest->mOutputSurfaces[streamId],
4573 &uniqueSurfaceIds);
4574 // INVALID_OPERATION is normal output for streams not supporting surfaceIds
4575 if (res != OK && res != INVALID_OPERATION) {
4576 ALOGE("%s: failed to query stream %d unique surface IDs",
4577 __FUNCTION__, streamId);
4578 return res;
4579 }
4580 if (res == OK) {
4581 uniqueSurfaceIdMap.insert({streamId, std::move(uniqueSurfaceIds)});
4582 }
4583
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07004584 if (mUseHalBufManager) {
Yin-Chia Yeh110342b2018-11-19 11:47:46 -08004585 if (outputStream->isAbandoned()) {
Yin-Chia Yeha1b56c82019-03-27 15:50:39 -07004586 ALOGV("%s: stream %d is abandoned, skipping request", __FUNCTION__, streamId);
Yin-Chia Yeh110342b2018-11-19 11:47:46 -08004587 return TIMED_OUT;
4588 }
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07004589 // HAL will request buffer through requestStreamBuffer API
4590 camera3_stream_buffer_t& buffer = outputBuffers->editItemAt(j);
4591 buffer.stream = outputStream->asHalStream();
4592 buffer.buffer = nullptr;
4593 buffer.status = CAMERA3_BUFFER_STATUS_OK;
4594 buffer.acquire_fence = -1;
4595 buffer.release_fence = -1;
4596 } else {
4597 res = outputStream->getBuffer(&outputBuffers->editItemAt(j),
4598 waitDuration,
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004599 captureRequest->mOutputSurfaces[streamId]);
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07004600 if (res != OK) {
4601 // Can't get output buffer from gralloc queue - this could be due to
4602 // abandoned queue or other consumer misbehavior, so not a fatal
4603 // error
Yin-Chia Yeha1b56c82019-03-27 15:50:39 -07004604 ALOGV("RequestThread: Can't get output buffer, skipping request:"
Yin-Chia Yehd5cd5ff2018-10-01 14:43:04 -07004605 " %s (%d)", strerror(-res), res);
4606
4607 return TIMED_OUT;
4608 }
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004609 }
Shuzhen Wang68ac7ad2019-01-30 14:03:28 -08004610
4611 {
4612 sp<Camera3Device> parent = mParent.promote();
4613 if (parent != nullptr) {
4614 const String8& streamCameraId = outputStream->getPhysicalCameraId();
4615 for (const auto& settings : captureRequest->mSettingsList) {
4616 if ((streamCameraId.isEmpty() &&
4617 parent->getId() == settings.cameraId.c_str()) ||
4618 streamCameraId == settings.cameraId.c_str()) {
4619 outputStream->fireBufferRequestForFrameNumber(
4620 captureRequest->mResultExtras.frameNumber,
4621 settings.metadata);
4622 }
4623 }
4624 }
4625 }
Shuzhen Wang0129d522016-10-30 22:43:41 -07004626
Shuzhen Wang5c22c152017-12-31 17:12:25 -08004627 String8 physicalCameraId = outputStream->getPhysicalCameraId();
4628
4629 if (!physicalCameraId.isEmpty()) {
4630 // Physical stream isn't supported for input request.
4631 if (halRequest->input_buffer) {
4632 CLOGE("Physical stream is not supported for input request");
4633 return INVALID_OPERATION;
4634 }
4635 requestedPhysicalCameras.insert(physicalCameraId);
4636 }
4637 halRequest->num_output_buffers++;
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004638 }
4639 totalNumBuffers += halRequest->num_output_buffers;
4640
4641 // Log request in the in-flight queue
Shuzhen Wang4a472662017-02-26 23:29:04 -08004642 // If this request list is for constrained high speed recording (not
4643 // preview), and the current request is not the last one in the batch,
4644 // do not send callback to the app.
4645 bool hasCallback = true;
Yin-Chia Yehd07b11e2018-06-01 12:50:02 -07004646 if (batchedRequest && i != mNextRequests.size()-1) {
Shuzhen Wang4a472662017-02-26 23:29:04 -08004647 hasCallback = false;
4648 }
Emilian Peev9dd21f42018-08-03 13:39:29 +01004649 bool isStillCapture = false;
Shuzhen Wang26abaf42018-08-28 15:41:20 -07004650 bool isZslCapture = false;
Emilian Peev9dd21f42018-08-03 13:39:29 +01004651 if (!mNextRequests[0].captureRequest->mSettingsList.begin()->metadata.isEmpty()) {
4652 camera_metadata_ro_entry_t e = camera_metadata_ro_entry_t();
4653 find_camera_metadata_ro_entry(halRequest->settings, ANDROID_CONTROL_CAPTURE_INTENT, &e);
4654 if ((e.count > 0) && (e.data.u8[0] == ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE)) {
4655 isStillCapture = true;
4656 ATRACE_ASYNC_BEGIN("still capture", mNextRequests[i].halRequest.frame_number);
4657 }
Shuzhen Wang26abaf42018-08-28 15:41:20 -07004658
4659 find_camera_metadata_ro_entry(halRequest->settings, ANDROID_CONTROL_ENABLE_ZSL, &e);
4660 if ((e.count > 0) && (e.data.u8[0] == ANDROID_CONTROL_ENABLE_ZSL_TRUE)) {
4661 isZslCapture = true;
4662 }
Emilian Peev9dd21f42018-08-03 13:39:29 +01004663 }
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004664 res = parent->registerInFlight(halRequest->frame_number,
4665 totalNumBuffers, captureRequest->mResultExtras,
4666 /*hasInput*/halRequest->input_buffer != NULL,
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07004667 hasCallback,
Shuzhen Wang5c22c152017-12-31 17:12:25 -08004668 calculateMaxExpectedDuration(halRequest->settings),
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08004669 requestedPhysicalCameras, isStillCapture, isZslCapture,
4670 captureRequest->mRotateAndCropAuto, mPrevCameraIdsWithZoom,
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004671 (mUseHalBufManager) ? uniqueSurfaceIdMap :
4672 SurfaceMap{});
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004673 ALOGVV("%s: registered in flight requestId = %" PRId32 ", frameNumber = %" PRId64
4674 ", burstId = %" PRId32 ".",
4675 __FUNCTION__,
4676 captureRequest->mResultExtras.requestId, captureRequest->mResultExtras.frameNumber,
4677 captureRequest->mResultExtras.burstId);
4678 if (res != OK) {
4679 SET_ERR("RequestThread: Unable to register new in-flight request:"
4680 " %s (%d)", strerror(-res), res);
4681 return INVALID_OPERATION;
4682 }
4683 }
4684
4685 return OK;
4686}
4687
Igor Murashkin1e479c02013-09-06 16:55:14 -07004688CameraMetadata Camera3Device::RequestThread::getLatestRequest() const {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004689 ATRACE_CALL();
Igor Murashkin1e479c02013-09-06 16:55:14 -07004690 Mutex::Autolock al(mLatestRequestMutex);
4691
4692 ALOGV("RequestThread::%s", __FUNCTION__);
4693
4694 return mLatestRequest;
4695}
4696
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07004697bool Camera3Device::RequestThread::isStreamPending(
4698 sp<Camera3StreamInterface>& stream) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004699 ATRACE_CALL();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07004700 Mutex::Autolock l(mRequestLock);
4701
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004702 for (const auto& nextRequest : mNextRequests) {
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004703 if (!nextRequest.submitted) {
4704 for (const auto& s : nextRequest.captureRequest->mOutputStreams) {
4705 if (stream == s) return true;
4706 }
4707 if (stream == nextRequest.captureRequest->mInputStream) return true;
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004708 }
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004709 }
4710
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07004711 for (const auto& request : mRequestQueue) {
4712 for (const auto& s : request->mOutputStreams) {
4713 if (stream == s) return true;
4714 }
4715 if (stream == request->mInputStream) return true;
4716 }
4717
4718 for (const auto& request : mRepeatingRequests) {
4719 for (const auto& s : request->mOutputStreams) {
4720 if (stream == s) return true;
4721 }
4722 if (stream == request->mInputStream) return true;
4723 }
4724
4725 return false;
4726}
Jianing Weicb0652e2014-03-12 18:29:36 -07004727
Emilian Peev40ead602017-09-26 15:46:36 +01004728bool Camera3Device::RequestThread::isOutputSurfacePending(int streamId, size_t surfaceId) {
4729 ATRACE_CALL();
4730 Mutex::Autolock l(mRequestLock);
4731
4732 for (const auto& nextRequest : mNextRequests) {
4733 for (const auto& s : nextRequest.captureRequest->mOutputSurfaces) {
4734 if (s.first == streamId) {
4735 const auto &it = std::find(s.second.begin(), s.second.end(), surfaceId);
4736 if (it != s.second.end()) {
4737 return true;
4738 }
4739 }
4740 }
4741 }
4742
4743 for (const auto& request : mRequestQueue) {
4744 for (const auto& s : request->mOutputSurfaces) {
4745 if (s.first == streamId) {
4746 const auto &it = std::find(s.second.begin(), s.second.end(), surfaceId);
4747 if (it != s.second.end()) {
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004748 return true;
Emilian Peev40ead602017-09-26 15:46:36 +01004749 }
4750 }
4751 }
4752 }
4753
4754 for (const auto& request : mRepeatingRequests) {
4755 for (const auto& s : request->mOutputSurfaces) {
4756 if (s.first == streamId) {
4757 const auto &it = std::find(s.second.begin(), s.second.end(), surfaceId);
4758 if (it != s.second.end()) {
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -07004759 return true;
Emilian Peev40ead602017-09-26 15:46:36 +01004760 }
4761 }
4762 }
4763 }
4764
4765 return false;
4766}
4767
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07004768void Camera3Device::RequestThread::signalPipelineDrain(const std::vector<int>& streamIds) {
4769 if (!mUseHalBufManager) {
4770 ALOGE("%s called for camera device not supporting HAL buffer management", __FUNCTION__);
4771 return;
4772 }
4773
4774 Mutex::Autolock pl(mPauseLock);
4775 if (mPaused) {
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07004776 mInterface->signalPipelineDrain(streamIds);
4777 return;
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07004778 }
4779 // If request thread is still busy, wait until paused then notify HAL
4780 mNotifyPipelineDrain = true;
4781 mStreamIdsToBeDrained = streamIds;
4782}
4783
Emilian Peevc0fe54c2020-03-11 14:05:07 -07004784void Camera3Device::RequestThread::clearPreviousRequest() {
4785 Mutex::Autolock l(mRequestLock);
4786 mPrevRequest.clear();
4787}
4788
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004789status_t Camera3Device::RequestThread::switchToOffline(
4790 const std::vector<int32_t>& streamsToKeep,
4791 /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004792 /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
4793 /*out*/camera3::BufferRecords* bufferRecords) {
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004794 Mutex::Autolock l(mRequestLock);
4795 clearRepeatingRequestsLocked(/*lastFrameNumber*/nullptr);
4796
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004797 // Wait until request thread is fully stopped
4798 // TBD: check if request thread is being paused by other APIs (shouldn't be)
4799
4800 // We could also check for mRepeatingRequests.empty(), but the API interface
4801 // is serialized by Camera3Device::mInterfaceLock so no one should be able to submit any
4802 // new requests during the call; hence skip that check.
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004803 bool queueEmpty = mNextRequests.empty() && mRequestQueue.empty();
4804 while (!queueEmpty) {
4805 status_t res = mRequestSubmittedSignal.waitRelative(mRequestLock, kRequestSubmitTimeout);
4806 if (res == TIMED_OUT) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004807 ALOGE("%s: request thread failed to submit one request within timeout!", __FUNCTION__);
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004808 return res;
4809 } else if (res != OK) {
4810 ALOGE("%s: request thread failed to submit a request: %s (%d)!",
4811 __FUNCTION__, strerror(-res), res);
4812 return res;
4813 }
4814 queueEmpty = mNextRequests.empty() && mRequestQueue.empty();
4815 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004816
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004817 return mInterface->switchToOffline(
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004818 streamsToKeep, offlineSessionInfo, offlineSession, bufferRecords);
Yin-Chia Yehb978c382019-10-30 00:22:37 -07004819}
4820
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08004821status_t Camera3Device::RequestThread::setRotateAndCropAutoBehavior(
4822 camera_metadata_enum_android_scaler_rotate_and_crop_t rotateAndCropValue) {
4823 ATRACE_CALL();
4824 Mutex::Autolock l(mTriggerMutex);
4825 if (rotateAndCropValue == ANDROID_SCALER_ROTATE_AND_CROP_AUTO) {
4826 return BAD_VALUE;
4827 }
4828 mRotateAndCropOverride = rotateAndCropValue;
4829 return OK;
4830}
4831
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07004832nsecs_t Camera3Device::getExpectedInFlightDuration() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004833 ATRACE_CALL();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004834 std::lock_guard<std::mutex> l(mInFlightLock);
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07004835 return mExpectedInflightDuration > kMinInflightDuration ?
4836 mExpectedInflightDuration : kMinInflightDuration;
4837}
4838
Emilian Peevaebbe412018-01-15 13:53:24 +00004839void Camera3Device::RequestThread::cleanupPhysicalSettings(sp<CaptureRequest> request,
4840 camera3_capture_request_t *halRequest) {
4841 if ((request == nullptr) || (halRequest == nullptr)) {
4842 ALOGE("%s: Invalid request!", __FUNCTION__);
4843 return;
4844 }
4845
4846 if (halRequest->num_physcam_settings > 0) {
4847 if (halRequest->physcam_id != nullptr) {
4848 delete [] halRequest->physcam_id;
4849 halRequest->physcam_id = nullptr;
4850 }
4851 if (halRequest->physcam_settings != nullptr) {
4852 auto it = ++(request->mSettingsList.begin());
4853 size_t i = 0;
4854 for (; it != request->mSettingsList.end(); it++, i++) {
4855 it->metadata.unlock(halRequest->physcam_settings[i]);
4856 }
4857 delete [] halRequest->physcam_settings;
4858 halRequest->physcam_settings = nullptr;
4859 }
4860 }
4861}
4862
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004863void Camera3Device::RequestThread::cleanUpFailedRequests(bool sendRequestError) {
4864 if (mNextRequests.empty()) {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004865 return;
4866 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004867
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004868 for (auto& nextRequest : mNextRequests) {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004869 // Skip the ones that have been submitted successfully.
4870 if (nextRequest.submitted) {
4871 continue;
4872 }
4873
4874 sp<CaptureRequest> captureRequest = nextRequest.captureRequest;
4875 camera3_capture_request_t* halRequest = &nextRequest.halRequest;
4876 Vector<camera3_stream_buffer_t>* outputBuffers = &nextRequest.outputBuffers;
4877
4878 if (halRequest->settings != NULL) {
Emilian Peevaebbe412018-01-15 13:53:24 +00004879 captureRequest->mSettingsList.begin()->metadata.unlock(halRequest->settings);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004880 }
4881
Emilian Peevaebbe412018-01-15 13:53:24 +00004882 cleanupPhysicalSettings(captureRequest, halRequest);
4883
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004884 if (captureRequest->mInputStream != NULL) {
4885 captureRequest->mInputBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
4886 captureRequest->mInputStream->returnInputBuffer(captureRequest->mInputBuffer);
4887 }
4888
Yin-Chia Yeh21cb47b2019-01-18 15:08:17 -08004889 // No output buffer can be returned when using HAL buffer manager
4890 if (!mUseHalBufManager) {
4891 for (size_t i = 0; i < halRequest->num_output_buffers; i++) {
4892 //Buffers that failed processing could still have
4893 //valid acquire fence.
4894 int acquireFence = (*outputBuffers)[i].acquire_fence;
4895 if (0 <= acquireFence) {
4896 close(acquireFence);
4897 outputBuffers->editItemAt(i).acquire_fence = -1;
4898 }
4899 outputBuffers->editItemAt(i).status = CAMERA3_BUFFER_STATUS_ERROR;
4900 captureRequest->mOutputStreams.editItemAt(i)->returnBuffer((*outputBuffers)[i], 0,
4901 /*timestampIncreasing*/true, std::vector<size_t> (),
4902 captureRequest->mResultExtras.frameNumber);
Emilian Peevc58cf4c2017-05-11 17:23:41 +01004903 }
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004904 }
4905
4906 if (sendRequestError) {
4907 Mutex::Autolock l(mRequestLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07004908 sp<NotificationListener> listener = mListener.promote();
4909 if (listener != NULL) {
4910 listener->notifyError(
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08004911 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004912 captureRequest->mResultExtras);
4913 }
4914 }
Shuzhen Wangcadb3302016-11-04 14:17:56 -07004915
4916 // Remove yet-to-be submitted inflight request from inflightMap
4917 {
4918 sp<Camera3Device> parent = mParent.promote();
4919 if (parent != NULL) {
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08004920 std::lock_guard<std::mutex> l(parent->mInFlightLock);
Shuzhen Wangcadb3302016-11-04 14:17:56 -07004921 ssize_t idx = parent->mInFlightMap.indexOfKey(captureRequest->mResultExtras.frameNumber);
4922 if (idx >= 0) {
4923 ALOGV("%s: Remove inflight request from queue: frameNumber %" PRId64,
4924 __FUNCTION__, captureRequest->mResultExtras.frameNumber);
4925 parent->removeInFlightMapEntryLocked(idx);
4926 }
4927 }
4928 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004929 }
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004930
4931 Mutex::Autolock l(mRequestLock);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004932 mNextRequests.clear();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004933}
4934
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004935void Camera3Device::RequestThread::waitForNextRequestBatch() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004936 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004937 // Optimized a bit for the simple steady-state case (single repeating
4938 // request), to avoid putting that request in the queue temporarily.
4939 Mutex::Autolock l(mRequestLock);
4940
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004941 assert(mNextRequests.empty());
4942
4943 NextRequest nextRequest;
4944 nextRequest.captureRequest = waitForNextRequestLocked();
4945 if (nextRequest.captureRequest == nullptr) {
4946 return;
4947 }
4948
4949 nextRequest.halRequest = camera3_capture_request_t();
4950 nextRequest.submitted = false;
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004951 mNextRequests.add(nextRequest);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004952
4953 // Wait for additional requests
4954 const size_t batchSize = nextRequest.captureRequest->mBatchSize;
4955
4956 for (size_t i = 1; i < batchSize; i++) {
4957 NextRequest additionalRequest;
4958 additionalRequest.captureRequest = waitForNextRequestLocked();
4959 if (additionalRequest.captureRequest == nullptr) {
4960 break;
4961 }
4962
4963 additionalRequest.halRequest = camera3_capture_request_t();
4964 additionalRequest.submitted = false;
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004965 mNextRequests.add(additionalRequest);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004966 }
4967
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004968 if (mNextRequests.size() < batchSize) {
Eino-Ville Talvalad309fb92015-11-25 12:12:45 -08004969 ALOGE("RequestThread: only get %zu out of %zu requests. Skipping requests.",
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004970 mNextRequests.size(), batchSize);
4971 cleanUpFailedRequests(/*sendRequestError*/true);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004972 }
4973
4974 return;
4975}
4976
4977sp<Camera3Device::CaptureRequest>
4978 Camera3Device::RequestThread::waitForNextRequestLocked() {
4979 status_t res;
4980 sp<CaptureRequest> nextRequest;
4981
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004982 while (mRequestQueue.empty()) {
4983 if (!mRepeatingRequests.empty()) {
4984 // Always atomically enqueue all requests in a repeating request
4985 // list. Guarantees a complete in-sequence set of captures to
4986 // application.
4987 const RequestList &requests = mRepeatingRequests;
4988 RequestList::const_iterator firstRequest =
4989 requests.begin();
4990 nextRequest = *firstRequest;
4991 mRequestQueue.insert(mRequestQueue.end(),
4992 ++firstRequest,
4993 requests.end());
4994 // No need to wait any longer
Jianing Weicb0652e2014-03-12 18:29:36 -07004995
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07004996 mRepeatingLastFrameNumber = mFrameNumber + requests.size() - 1;
Jianing Weicb0652e2014-03-12 18:29:36 -07004997
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004998 break;
4999 }
5000
5001 res = mRequestSignal.waitRelative(mRequestLock, kRequestTimeout);
5002
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005003 if ((mRequestQueue.empty() && mRepeatingRequests.empty()) ||
5004 exitPending()) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005005 Mutex::Autolock pl(mPauseLock);
5006 if (mPaused == false) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005007 ALOGV("%s: RequestThread: Going idle", __FUNCTION__);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005008 mPaused = true;
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07005009 if (mNotifyPipelineDrain) {
5010 mInterface->signalPipelineDrain(mStreamIdsToBeDrained);
5011 mNotifyPipelineDrain = false;
5012 mStreamIdsToBeDrained.clear();
5013 }
Yin-Chia Yehc300a072019-02-13 14:56:57 -08005014 // Let the tracker know
5015 sp<StatusTracker> statusTracker = mStatusTracker.promote();
5016 if (statusTracker != 0) {
5017 statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);
5018 }
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005019 sp<Camera3Device> parent = mParent.promote();
5020 if (parent != nullptr) {
5021 parent->mRequestBufferSM.onRequestThreadPaused();
5022 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005023 }
5024 // Stop waiting for now and let thread management happen
5025 return NULL;
5026 }
5027 }
5028
5029 if (nextRequest == NULL) {
5030 // Don't have a repeating request already in hand, so queue
5031 // must have an entry now.
5032 RequestList::iterator firstRequest =
5033 mRequestQueue.begin();
5034 nextRequest = *firstRequest;
5035 mRequestQueue.erase(firstRequest);
Shuzhen Wang9d066012016-09-30 11:30:20 -07005036 if (mRequestQueue.empty() && !nextRequest->mRepeating) {
5037 sp<NotificationListener> listener = mListener.promote();
5038 if (listener != NULL) {
5039 listener->notifyRequestQueueEmpty();
5040 }
5041 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005042 }
5043
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07005044 // In case we've been unpaused by setPaused clearing mDoPause, need to
5045 // update internal pause state (capture/setRepeatingRequest unpause
5046 // directly).
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005047 Mutex::Autolock pl(mPauseLock);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005048 if (mPaused) {
5049 ALOGV("%s: RequestThread: Unpaused", __FUNCTION__);
5050 sp<StatusTracker> statusTracker = mStatusTracker.promote();
5051 if (statusTracker != 0) {
5052 statusTracker->markComponentActive(mStatusId);
5053 }
5054 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005055 mPaused = false;
5056
5057 // Check if we've reconfigured since last time, and reset the preview
5058 // request if so. Can't use 'NULL request == repeat' across configure calls.
5059 if (mReconfigured) {
5060 mPrevRequest.clear();
5061 mReconfigured = false;
5062 }
5063
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07005064 if (nextRequest != NULL) {
5065 nextRequest->mResultExtras.frameNumber = mFrameNumber++;
Yin-Chia Yehc00a25c2014-08-21 14:27:44 -07005066 nextRequest->mResultExtras.afTriggerId = mCurrentAfTriggerId;
5067 nextRequest->mResultExtras.precaptureTriggerId = mCurrentPreCaptureTriggerId;
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07005068
5069 // Since RequestThread::clear() removes buffers from the input stream,
5070 // get the right buffer here before unlocking mRequestLock
5071 if (nextRequest->mInputStream != NULL) {
5072 res = nextRequest->mInputStream->getInputBuffer(&nextRequest->mInputBuffer);
5073 if (res != OK) {
5074 // Can't get input buffer from gralloc queue - this could be due to
5075 // disconnected queue or other producer misbehavior, so not a fatal
5076 // error
5077 ALOGE("%s: Can't get input buffer, skipping request:"
5078 " %s (%d)", __FUNCTION__, strerror(-res), res);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005079
5080 sp<NotificationListener> listener = mListener.promote();
5081 if (listener != NULL) {
5082 listener->notifyError(
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08005083 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07005084 nextRequest->mResultExtras);
5085 }
5086 return NULL;
5087 }
5088 }
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07005089 }
Chien-Yu Chend196d612015-06-22 19:49:01 -07005090
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005091 return nextRequest;
5092}
5093
5094bool Camera3Device::RequestThread::waitIfPaused() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005095 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005096 status_t res;
5097 Mutex::Autolock l(mPauseLock);
5098 while (mDoPause) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005099 if (mPaused == false) {
5100 mPaused = true;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005101 ALOGV("%s: RequestThread: Paused", __FUNCTION__);
Yin-Chia Yeh7447f0f2018-10-11 15:28:12 -07005102 if (mNotifyPipelineDrain) {
5103 mInterface->signalPipelineDrain(mStreamIdsToBeDrained);
5104 mNotifyPipelineDrain = false;
5105 mStreamIdsToBeDrained.clear();
5106 }
Yin-Chia Yehc300a072019-02-13 14:56:57 -08005107 // Let the tracker know
5108 sp<StatusTracker> statusTracker = mStatusTracker.promote();
5109 if (statusTracker != 0) {
5110 statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);
5111 }
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005112 sp<Camera3Device> parent = mParent.promote();
5113 if (parent != nullptr) {
5114 parent->mRequestBufferSM.onRequestThreadPaused();
5115 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005116 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005117
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005118 res = mDoPauseSignal.waitRelative(mPauseLock, kRequestTimeout);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005119 if (res == TIMED_OUT || exitPending()) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005120 return true;
5121 }
5122 }
5123 // We don't set mPaused to false here, because waitForNextRequest needs
5124 // to further manage the paused state in case of starvation.
5125 return false;
5126}
5127
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07005128void Camera3Device::RequestThread::unpauseForNewRequests() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005129 ATRACE_CALL();
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07005130 // With work to do, mark thread as unpaused.
5131 // If paused by request (setPaused), don't resume, to avoid
5132 // extra signaling/waiting overhead to waitUntilPaused
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005133 mRequestSignal.signal();
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07005134 Mutex::Autolock p(mPauseLock);
5135 if (!mDoPause) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07005136 ALOGV("%s: RequestThread: Going active", __FUNCTION__);
5137 if (mPaused) {
5138 sp<StatusTracker> statusTracker = mStatusTracker.promote();
5139 if (statusTracker != 0) {
5140 statusTracker->markComponentActive(mStatusId);
5141 }
5142 }
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07005143 mPaused = false;
5144 }
5145}
5146
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07005147void Camera3Device::RequestThread::setErrorState(const char *fmt, ...) {
5148 sp<Camera3Device> parent = mParent.promote();
5149 if (parent != NULL) {
5150 va_list args;
5151 va_start(args, fmt);
5152
5153 parent->setErrorStateV(fmt, args);
5154
5155 va_end(args);
5156 }
5157}
5158
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005159status_t Camera3Device::RequestThread::insertTriggers(
5160 const sp<CaptureRequest> &request) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005161 ATRACE_CALL();
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005162 Mutex::Autolock al(mTriggerMutex);
5163
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07005164 sp<Camera3Device> parent = mParent.promote();
5165 if (parent == NULL) {
5166 CLOGE("RequestThread: Parent is gone");
5167 return DEAD_OBJECT;
5168 }
5169
Emilian Peevaebbe412018-01-15 13:53:24 +00005170 CameraMetadata &metadata = request->mSettingsList.begin()->metadata;
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005171 size_t count = mTriggerMap.size();
5172
5173 for (size_t i = 0; i < count; ++i) {
5174 RequestTrigger trigger = mTriggerMap.valueAt(i);
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005175 uint32_t tag = trigger.metadataTag;
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07005176
5177 if (tag == ANDROID_CONTROL_AF_TRIGGER_ID || tag == ANDROID_CONTROL_AE_PRECAPTURE_ID) {
5178 bool isAeTrigger = (trigger.metadataTag == ANDROID_CONTROL_AE_PRECAPTURE_ID);
5179 uint32_t triggerId = static_cast<uint32_t>(trigger.entryValue);
Yin-Chia Yehc00a25c2014-08-21 14:27:44 -07005180 if (isAeTrigger) {
5181 request->mResultExtras.precaptureTriggerId = triggerId;
5182 mCurrentPreCaptureTriggerId = triggerId;
5183 } else {
5184 request->mResultExtras.afTriggerId = triggerId;
5185 mCurrentAfTriggerId = triggerId;
5186 }
Emilian Peev7e25e5e2017-04-07 15:48:49 +01005187 continue;
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07005188 }
5189
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005190 camera_metadata_entry entry = metadata.find(tag);
5191
5192 if (entry.count > 0) {
5193 /**
5194 * Already has an entry for this trigger in the request.
5195 * Rewrite it with our requested trigger value.
5196 */
5197 RequestTrigger oldTrigger = trigger;
5198
5199 oldTrigger.entryValue = entry.data.u8[0];
5200
5201 mTriggerReplacedMap.add(tag, oldTrigger);
5202 } else {
5203 /**
5204 * More typical, no trigger entry, so we just add it
5205 */
5206 mTriggerRemovedMap.add(tag, trigger);
5207 }
5208
5209 status_t res;
5210
5211 switch (trigger.getTagType()) {
5212 case TYPE_BYTE: {
5213 uint8_t entryValue = static_cast<uint8_t>(trigger.entryValue);
5214 res = metadata.update(tag,
5215 &entryValue,
5216 /*count*/1);
5217 break;
5218 }
5219 case TYPE_INT32:
5220 res = metadata.update(tag,
5221 &trigger.entryValue,
5222 /*count*/1);
5223 break;
5224 default:
5225 ALOGE("%s: Type not supported: 0x%x",
5226 __FUNCTION__,
5227 trigger.getTagType());
5228 return INVALID_OPERATION;
5229 }
5230
5231 if (res != OK) {
5232 ALOGE("%s: Failed to update request metadata with trigger tag %s"
5233 ", value %d", __FUNCTION__, trigger.getTagName(),
5234 trigger.entryValue);
5235 return res;
5236 }
5237
5238 ALOGV("%s: Mixed in trigger %s, value %d", __FUNCTION__,
5239 trigger.getTagName(),
5240 trigger.entryValue);
5241 }
5242
5243 mTriggerMap.clear();
5244
5245 return count;
5246}
5247
5248status_t Camera3Device::RequestThread::removeTriggers(
5249 const sp<CaptureRequest> &request) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005250 ATRACE_CALL();
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005251 Mutex::Autolock al(mTriggerMutex);
5252
Emilian Peevaebbe412018-01-15 13:53:24 +00005253 CameraMetadata &metadata = request->mSettingsList.begin()->metadata;
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005254
5255 /**
5256 * Replace all old entries with their old values.
5257 */
5258 for (size_t i = 0; i < mTriggerReplacedMap.size(); ++i) {
5259 RequestTrigger trigger = mTriggerReplacedMap.valueAt(i);
5260
5261 status_t res;
5262
5263 uint32_t tag = trigger.metadataTag;
5264 switch (trigger.getTagType()) {
5265 case TYPE_BYTE: {
5266 uint8_t entryValue = static_cast<uint8_t>(trigger.entryValue);
5267 res = metadata.update(tag,
5268 &entryValue,
5269 /*count*/1);
5270 break;
5271 }
5272 case TYPE_INT32:
5273 res = metadata.update(tag,
5274 &trigger.entryValue,
5275 /*count*/1);
5276 break;
5277 default:
5278 ALOGE("%s: Type not supported: 0x%x",
5279 __FUNCTION__,
5280 trigger.getTagType());
5281 return INVALID_OPERATION;
5282 }
5283
5284 if (res != OK) {
5285 ALOGE("%s: Failed to restore request metadata with trigger tag %s"
5286 ", trigger value %d", __FUNCTION__,
5287 trigger.getTagName(), trigger.entryValue);
5288 return res;
5289 }
5290 }
5291 mTriggerReplacedMap.clear();
5292
5293 /**
5294 * Remove all new entries.
5295 */
5296 for (size_t i = 0; i < mTriggerRemovedMap.size(); ++i) {
5297 RequestTrigger trigger = mTriggerRemovedMap.valueAt(i);
5298 status_t res = metadata.erase(trigger.metadataTag);
5299
5300 if (res != OK) {
5301 ALOGE("%s: Failed to erase metadata with trigger tag %s"
5302 ", trigger value %d", __FUNCTION__,
5303 trigger.getTagName(), trigger.entryValue);
5304 return res;
5305 }
5306 }
5307 mTriggerRemovedMap.clear();
5308
5309 return OK;
5310}
5311
Eino-Ville Talvala2f876f92013-09-13 11:39:24 -07005312status_t Camera3Device::RequestThread::addDummyTriggerIds(
5313 const sp<CaptureRequest> &request) {
Eino-Ville Talvalad309fb92015-11-25 12:12:45 -08005314 // Trigger ID 0 had special meaning in the HAL2 spec, so avoid it here
Eino-Ville Talvala2f876f92013-09-13 11:39:24 -07005315 static const int32_t dummyTriggerId = 1;
5316 status_t res;
5317
Emilian Peevaebbe412018-01-15 13:53:24 +00005318 CameraMetadata &metadata = request->mSettingsList.begin()->metadata;
Eino-Ville Talvala2f876f92013-09-13 11:39:24 -07005319
5320 // If AF trigger is active, insert a dummy AF trigger ID if none already
5321 // exists
5322 camera_metadata_entry afTrigger = metadata.find(ANDROID_CONTROL_AF_TRIGGER);
5323 camera_metadata_entry afId = metadata.find(ANDROID_CONTROL_AF_TRIGGER_ID);
5324 if (afTrigger.count > 0 &&
5325 afTrigger.data.u8[0] != ANDROID_CONTROL_AF_TRIGGER_IDLE &&
5326 afId.count == 0) {
5327 res = metadata.update(ANDROID_CONTROL_AF_TRIGGER_ID, &dummyTriggerId, 1);
5328 if (res != OK) return res;
5329 }
5330
5331 // If AE precapture trigger is active, insert a dummy precapture trigger ID
5332 // if none already exists
5333 camera_metadata_entry pcTrigger =
5334 metadata.find(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER);
5335 camera_metadata_entry pcId = metadata.find(ANDROID_CONTROL_AE_PRECAPTURE_ID);
5336 if (pcTrigger.count > 0 &&
5337 pcTrigger.data.u8[0] != ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE &&
5338 pcId.count == 0) {
5339 res = metadata.update(ANDROID_CONTROL_AE_PRECAPTURE_ID,
5340 &dummyTriggerId, 1);
5341 if (res != OK) return res;
5342 }
5343
5344 return OK;
5345}
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005346
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08005347bool Camera3Device::RequestThread::overrideAutoRotateAndCrop(
5348 const sp<CaptureRequest> &request) {
5349 ATRACE_CALL();
5350
5351 if (request->mRotateAndCropAuto) {
5352 Mutex::Autolock l(mTriggerMutex);
5353 CameraMetadata &metadata = request->mSettingsList.begin()->metadata;
5354
5355 auto rotateAndCropEntry = metadata.find(ANDROID_SCALER_ROTATE_AND_CROP);
5356 if (rotateAndCropEntry.count > 0) {
5357 if (rotateAndCropEntry.data.u8[0] == mRotateAndCropOverride) {
5358 return false;
5359 } else {
5360 rotateAndCropEntry.data.u8[0] = mRotateAndCropOverride;
5361 return true;
5362 }
5363 } else {
5364 uint8_t rotateAndCrop_u8 = mRotateAndCropOverride;
5365 metadata.update(ANDROID_SCALER_ROTATE_AND_CROP,
5366 &rotateAndCrop_u8, 1);
5367 return true;
5368 }
5369 }
5370 return false;
5371}
5372
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005373/**
5374 * PreparerThread inner class methods
5375 */
5376
5377Camera3Device::PreparerThread::PreparerThread() :
Eino-Ville Talvala77c1a352016-06-13 12:32:43 -07005378 Thread(/*canCallJava*/false), mListener(nullptr),
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005379 mActive(false), mCancelNow(false), mCurrentMaxCount(0), mCurrentPrepareComplete(false) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005380}
5381
5382Camera3Device::PreparerThread::~PreparerThread() {
5383 Thread::requestExitAndWait();
5384 if (mCurrentStream != nullptr) {
5385 mCurrentStream->cancelPrepare();
5386 ATRACE_ASYNC_END("stream prepare", mCurrentStream->getId());
5387 mCurrentStream.clear();
5388 }
5389 clear();
5390}
5391
Ruben Brunkc78ac262015-08-13 17:58:46 -07005392status_t Camera3Device::PreparerThread::prepare(int maxCount, sp<Camera3StreamInterface>& stream) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005393 ATRACE_CALL();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005394 status_t res;
5395
5396 Mutex::Autolock l(mLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005397 sp<NotificationListener> listener = mListener.promote();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005398
Shuzhen Wangb3a0fb52018-09-13 17:24:08 -07005399 res = stream->startPrepare(maxCount, true /*blockRequest*/);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005400 if (res == OK) {
5401 // No preparation needed, fire listener right off
5402 ALOGV("%s: Stream %d already prepared", __FUNCTION__, stream->getId());
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005403 if (listener != NULL) {
5404 listener->notifyPrepared(stream->getId());
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005405 }
5406 return OK;
5407 } else if (res != NOT_ENOUGH_DATA) {
5408 return res;
5409 }
5410
5411 // Need to prepare, start up thread if necessary
5412 if (!mActive) {
5413 // mRunning will change to false before the thread fully shuts down, so wait to be sure it
5414 // isn't running
5415 Thread::requestExitAndWait();
5416 res = Thread::run("C3PrepThread", PRIORITY_BACKGROUND);
5417 if (res != OK) {
5418 ALOGE("%s: Unable to start preparer stream: %d (%s)", __FUNCTION__, res, strerror(-res));
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005419 if (listener != NULL) {
5420 listener->notifyPrepared(stream->getId());
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005421 }
5422 return res;
5423 }
5424 mCancelNow = false;
5425 mActive = true;
5426 ALOGV("%s: Preparer stream started", __FUNCTION__);
5427 }
5428
5429 // queue up the work
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005430 mPendingStreams.emplace(maxCount, stream);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005431 ALOGV("%s: Stream %d queued for preparing", __FUNCTION__, stream->getId());
5432
5433 return OK;
5434}
5435
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005436void Camera3Device::PreparerThread::pause() {
5437 ATRACE_CALL();
5438
5439 Mutex::Autolock l(mLock);
5440
5441 std::unordered_map<int, sp<camera3::Camera3StreamInterface> > pendingStreams;
5442 pendingStreams.insert(mPendingStreams.begin(), mPendingStreams.end());
5443 sp<camera3::Camera3StreamInterface> currentStream = mCurrentStream;
5444 int currentMaxCount = mCurrentMaxCount;
5445 mPendingStreams.clear();
5446 mCancelNow = true;
5447 while (mActive) {
5448 auto res = mThreadActiveSignal.waitRelative(mLock, kActiveTimeout);
5449 if (res == TIMED_OUT) {
5450 ALOGE("%s: Timed out waiting on prepare thread!", __FUNCTION__);
5451 return;
5452 } else if (res != OK) {
5453 ALOGE("%s: Encountered an error: %d waiting on prepare thread!", __FUNCTION__, res);
5454 return;
5455 }
5456 }
5457
5458 //Check whether the prepare thread was able to complete the current
5459 //stream. In case work is still pending emplace it along with the rest
5460 //of the streams in the pending list.
5461 if (currentStream != nullptr) {
5462 if (!mCurrentPrepareComplete) {
5463 pendingStreams.emplace(currentMaxCount, currentStream);
5464 }
5465 }
5466
5467 mPendingStreams.insert(pendingStreams.begin(), pendingStreams.end());
5468 for (const auto& it : mPendingStreams) {
5469 it.second->cancelPrepare();
5470 }
5471}
5472
5473status_t Camera3Device::PreparerThread::resume() {
5474 ATRACE_CALL();
5475 status_t res;
5476
5477 Mutex::Autolock l(mLock);
5478 sp<NotificationListener> listener = mListener.promote();
5479
5480 if (mActive) {
5481 ALOGE("%s: Trying to resume an already active prepare thread!", __FUNCTION__);
5482 return NO_INIT;
5483 }
5484
5485 auto it = mPendingStreams.begin();
5486 for (; it != mPendingStreams.end();) {
Shuzhen Wangb3a0fb52018-09-13 17:24:08 -07005487 res = it->second->startPrepare(it->first, true /*blockRequest*/);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005488 if (res == OK) {
5489 if (listener != NULL) {
5490 listener->notifyPrepared(it->second->getId());
5491 }
5492 it = mPendingStreams.erase(it);
5493 } else if (res != NOT_ENOUGH_DATA) {
5494 ALOGE("%s: Unable to start preparer stream: %d (%s)", __FUNCTION__,
5495 res, strerror(-res));
5496 it = mPendingStreams.erase(it);
5497 } else {
5498 it++;
5499 }
5500 }
5501
5502 if (mPendingStreams.empty()) {
5503 return OK;
5504 }
5505
5506 res = Thread::run("C3PrepThread", PRIORITY_BACKGROUND);
5507 if (res != OK) {
5508 ALOGE("%s: Unable to start preparer stream: %d (%s)",
5509 __FUNCTION__, res, strerror(-res));
5510 return res;
5511 }
5512 mCancelNow = false;
5513 mActive = true;
5514 ALOGV("%s: Preparer stream started", __FUNCTION__);
5515
5516 return OK;
5517}
5518
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005519status_t Camera3Device::PreparerThread::clear() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005520 ATRACE_CALL();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005521 Mutex::Autolock l(mLock);
5522
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005523 for (const auto& it : mPendingStreams) {
5524 it.second->cancelPrepare();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005525 }
5526 mPendingStreams.clear();
5527 mCancelNow = true;
5528
5529 return OK;
5530}
5531
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005532void Camera3Device::PreparerThread::setNotificationListener(wp<NotificationListener> listener) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005533 ATRACE_CALL();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005534 Mutex::Autolock l(mLock);
5535 mListener = listener;
5536}
5537
5538bool Camera3Device::PreparerThread::threadLoop() {
5539 status_t res;
5540 {
5541 Mutex::Autolock l(mLock);
5542 if (mCurrentStream == nullptr) {
5543 // End thread if done with work
5544 if (mPendingStreams.empty()) {
5545 ALOGV("%s: Preparer stream out of work", __FUNCTION__);
5546 // threadLoop _must not_ re-acquire mLock after it sets mActive to false; would
5547 // cause deadlock with prepare()'s requestExitAndWait triggered by !mActive.
5548 mActive = false;
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005549 mThreadActiveSignal.signal();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005550 return false;
5551 }
5552
5553 // Get next stream to prepare
5554 auto it = mPendingStreams.begin();
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005555 mCurrentStream = it->second;
5556 mCurrentMaxCount = it->first;
5557 mCurrentPrepareComplete = false;
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005558 mPendingStreams.erase(it);
5559 ATRACE_ASYNC_BEGIN("stream prepare", mCurrentStream->getId());
5560 ALOGV("%s: Preparing stream %d", __FUNCTION__, mCurrentStream->getId());
5561 } else if (mCancelNow) {
5562 mCurrentStream->cancelPrepare();
5563 ATRACE_ASYNC_END("stream prepare", mCurrentStream->getId());
5564 ALOGV("%s: Cancelling stream %d prepare", __FUNCTION__, mCurrentStream->getId());
5565 mCurrentStream.clear();
5566 mCancelNow = false;
5567 return true;
5568 }
5569 }
5570
5571 res = mCurrentStream->prepareNextBuffer();
5572 if (res == NOT_ENOUGH_DATA) return true;
5573 if (res != OK) {
5574 // Something bad happened; try to recover by cancelling prepare and
5575 // signalling listener anyway
5576 ALOGE("%s: Stream %d returned error %d (%s) during prepare", __FUNCTION__,
5577 mCurrentStream->getId(), res, strerror(-res));
5578 mCurrentStream->cancelPrepare();
5579 }
5580
5581 // This stream has finished, notify listener
5582 Mutex::Autolock l(mLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005583 sp<NotificationListener> listener = mListener.promote();
5584 if (listener != NULL) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005585 ALOGV("%s: Stream %d prepare done, signaling listener", __FUNCTION__,
5586 mCurrentStream->getId());
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005587 listener->notifyPrepared(mCurrentStream->getId());
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005588 }
5589
5590 ATRACE_ASYNC_END("stream prepare", mCurrentStream->getId());
5591 mCurrentStream.clear();
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005592 mCurrentPrepareComplete = true;
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005593
5594 return true;
5595}
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005596
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005597status_t Camera3Device::RequestBufferStateMachine::initialize(
5598 sp<camera3::StatusTracker> statusTracker) {
5599 if (statusTracker == nullptr) {
5600 ALOGE("%s: statusTracker is null", __FUNCTION__);
5601 return BAD_VALUE;
5602 }
5603
5604 std::lock_guard<std::mutex> lock(mLock);
5605 mStatusTracker = statusTracker;
5606 mRequestBufferStatusId = statusTracker->addComponent();
5607 return OK;
5608}
5609
5610bool Camera3Device::RequestBufferStateMachine::startRequestBuffer() {
5611 std::lock_guard<std::mutex> lock(mLock);
Yin-Chia Yeh8a4ccb02018-11-16 15:43:36 -08005612 if (mStatus == RB_STATUS_READY || mStatus == RB_STATUS_PENDING_STOP) {
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005613 mRequestBufferOngoing = true;
Yin-Chia Yeh8a4ccb02018-11-16 15:43:36 -08005614 notifyTrackerLocked(/*active*/true);
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005615 return true;
5616 }
5617 return false;
5618}
5619
5620void Camera3Device::RequestBufferStateMachine::endRequestBuffer() {
5621 std::lock_guard<std::mutex> lock(mLock);
5622 if (!mRequestBufferOngoing) {
5623 ALOGE("%s called without a successful startRequestBuffer call first!", __FUNCTION__);
5624 return;
5625 }
5626 mRequestBufferOngoing = false;
5627 if (mStatus == RB_STATUS_PENDING_STOP) {
5628 checkSwitchToStopLocked();
5629 }
Yin-Chia Yeh8a4ccb02018-11-16 15:43:36 -08005630 notifyTrackerLocked(/*active*/false);
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005631}
5632
5633void Camera3Device::RequestBufferStateMachine::onStreamsConfigured() {
5634 std::lock_guard<std::mutex> lock(mLock);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005635 mSwitchedToOffline = false;
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005636 mStatus = RB_STATUS_READY;
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005637 return;
5638}
5639
Yin-Chia Yehcd333fe2019-02-08 13:45:41 -08005640void Camera3Device::RequestBufferStateMachine::onSubmittingRequest() {
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005641 std::lock_guard<std::mutex> lock(mLock);
5642 mRequestThreadPaused = false;
Yin-Chia Yehcd333fe2019-02-08 13:45:41 -08005643 // inflight map register actually happens in prepareHalRequest now, but it is close enough
5644 // approximation.
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005645 mInflightMapEmpty = false;
5646 if (mStatus == RB_STATUS_STOPPED) {
5647 mStatus = RB_STATUS_READY;
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005648 }
5649 return;
5650}
5651
5652void Camera3Device::RequestBufferStateMachine::onRequestThreadPaused() {
5653 std::lock_guard<std::mutex> lock(mLock);
5654 mRequestThreadPaused = true;
5655 if (mStatus == RB_STATUS_PENDING_STOP) {
5656 checkSwitchToStopLocked();
5657 }
5658 return;
5659}
5660
5661void Camera3Device::RequestBufferStateMachine::onInflightMapEmpty() {
5662 std::lock_guard<std::mutex> lock(mLock);
5663 mInflightMapEmpty = true;
5664 if (mStatus == RB_STATUS_PENDING_STOP) {
5665 checkSwitchToStopLocked();
5666 }
5667 return;
5668}
5669
5670void Camera3Device::RequestBufferStateMachine::onWaitUntilIdle() {
5671 std::lock_guard<std::mutex> lock(mLock);
5672 if (!checkSwitchToStopLocked()) {
5673 mStatus = RB_STATUS_PENDING_STOP;
5674 }
5675 return;
5676}
5677
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005678bool Camera3Device::RequestBufferStateMachine::onSwitchToOfflineSuccess() {
5679 std::lock_guard<std::mutex> lock(mLock);
5680 if (mRequestBufferOngoing) {
5681 ALOGE("%s: HAL must not be requesting buffer after HAL returns switchToOffline!",
5682 __FUNCTION__);
5683 return false;
5684 }
5685 mSwitchedToOffline = true;
5686 mInflightMapEmpty = true;
5687 mRequestThreadPaused = true;
5688 mStatus = RB_STATUS_STOPPED;
5689 return true;
5690}
5691
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005692void Camera3Device::RequestBufferStateMachine::notifyTrackerLocked(bool active) {
5693 sp<StatusTracker> statusTracker = mStatusTracker.promote();
5694 if (statusTracker != nullptr) {
5695 if (active) {
5696 statusTracker->markComponentActive(mRequestBufferStatusId);
5697 } else {
5698 statusTracker->markComponentIdle(mRequestBufferStatusId, Fence::NO_FENCE);
5699 }
5700 }
5701}
5702
5703bool Camera3Device::RequestBufferStateMachine::checkSwitchToStopLocked() {
5704 if (mInflightMapEmpty && mRequestThreadPaused && !mRequestBufferOngoing) {
5705 mStatus = RB_STATUS_STOPPED;
Yin-Chia Yeh30ab5ed2018-10-12 15:57:04 -07005706 return true;
5707 }
5708 return false;
5709}
5710
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005711bool Camera3Device::startRequestBuffer() {
5712 return mRequestBufferSM.startRequestBuffer();
5713}
Shuzhen Wang268a1362018-10-16 16:32:59 -07005714
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005715void Camera3Device::endRequestBuffer() {
5716 mRequestBufferSM.endRequestBuffer();
5717}
Shuzhen Wang268a1362018-10-16 16:32:59 -07005718
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005719nsecs_t Camera3Device::getWaitDuration() {
5720 return kBaseGetBufferWait + getExpectedInFlightDuration();
5721}
Shuzhen Wang268a1362018-10-16 16:32:59 -07005722
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005723void Camera3Device::getInflightBufferKeys(std::vector<std::pair<int32_t, int32_t>>* out) {
5724 mInterface->getInflightBufferKeys(out);
5725}
Shuzhen Wang268a1362018-10-16 16:32:59 -07005726
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005727void Camera3Device::getInflightRequestBufferKeys(std::vector<uint64_t>* out) {
5728 mInterface->getInflightRequestBufferKeys(out);
5729}
Shuzhen Wang268a1362018-10-16 16:32:59 -07005730
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005731std::vector<sp<Camera3StreamInterface>> Camera3Device::getAllStreams() {
5732 std::vector<sp<Camera3StreamInterface>> ret;
5733 bool hasInputStream = mInputStream != nullptr;
5734 ret.reserve(mOutputStreams.size() + mDeletedStreams.size() + ((hasInputStream) ? 1 : 0));
5735 if (hasInputStream) {
5736 ret.push_back(mInputStream);
Shuzhen Wang268a1362018-10-16 16:32:59 -07005737 }
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005738 for (size_t i = 0; i < mOutputStreams.size(); i++) {
5739 ret.push_back(mOutputStreams[i]);
5740 }
5741 for (size_t i = 0; i < mDeletedStreams.size(); i++) {
5742 ret.push_back(mDeletedStreams[i]);
5743 }
5744 return ret;
Shuzhen Wang268a1362018-10-16 16:32:59 -07005745}
5746
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005747status_t Camera3Device::switchToOffline(
5748 const std::vector<int32_t>& streamsToKeep,
5749 /*out*/ sp<CameraOfflineSessionBase>* session) {
5750 ATRACE_CALL();
5751 if (session == nullptr) {
5752 ALOGE("%s: session must not be null", __FUNCTION__);
5753 return BAD_VALUE;
5754 }
5755
5756 Mutex::Autolock il(mInterfaceLock);
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005757
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005758 bool hasInputStream = mInputStream != nullptr;
5759 int32_t inputStreamId = hasInputStream ? mInputStream->getId() : -1;
5760 bool inputStreamSupportsOffline = hasInputStream ?
5761 mInputStream->getOfflineProcessingSupport() : false;
5762 auto outputStreamIds = mOutputStreams.getStreamIds();
5763 auto streamIds = outputStreamIds;
5764 if (hasInputStream) {
5765 streamIds.push_back(mInputStream->getId());
5766 }
5767
5768 // Check all streams in streamsToKeep supports offline mode
5769 for (auto id : streamsToKeep) {
5770 if (std::find(streamIds.begin(), streamIds.end(), id) == streamIds.end()) {
5771 ALOGE("%s: Unknown stream ID %d", __FUNCTION__, id);
5772 return BAD_VALUE;
5773 } else if (id == inputStreamId) {
5774 if (!inputStreamSupportsOffline) {
5775 ALOGE("%s: input stream %d cannot be switched to offline",
5776 __FUNCTION__, id);
5777 return BAD_VALUE;
5778 }
5779 } else {
5780 sp<camera3::Camera3OutputStreamInterface> stream = mOutputStreams.get(id);
5781 if (!stream->getOfflineProcessingSupport()) {
5782 ALOGE("%s: output stream %d cannot be switched to offline",
5783 __FUNCTION__, id);
5784 return BAD_VALUE;
5785 }
5786 }
5787 }
5788
5789 // TODO: block surface sharing and surface group streams until we can support them
5790
5791 // Stop repeating request, wait until all remaining requests are submitted, then call into
5792 // HAL switchToOffline
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005793 hardware::camera::device::V3_6::CameraOfflineSessionInfo offlineSessionInfo;
5794 sp<hardware::camera::device::V3_6::ICameraOfflineSession> offlineSession;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005795 camera3::BufferRecords bufferRecords;
5796 status_t ret = mRequestThread->switchToOffline(
5797 streamsToKeep, &offlineSessionInfo, &offlineSession, &bufferRecords);
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005798
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005799 if (ret != OK) {
5800 SET_ERR("Switch to offline failed: %s (%d)", strerror(-ret), ret);
5801 return ret;
5802 }
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005803
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005804 bool succ = mRequestBufferSM.onSwitchToOfflineSuccess();
5805 if (!succ) {
5806 SET_ERR("HAL must not be calling requestStreamBuffers call");
5807 // TODO: block ALL callbacks from HAL till app configured new streams?
5808 return UNKNOWN_ERROR;
5809 }
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005810
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005811 // Verify offlineSessionInfo
5812 std::vector<int32_t> offlineStreamIds;
5813 offlineStreamIds.reserve(offlineSessionInfo.offlineStreams.size());
5814 for (auto offlineStream : offlineSessionInfo.offlineStreams) {
5815 // verify stream IDs
5816 int32_t id = offlineStream.id;
5817 if (std::find(streamIds.begin(), streamIds.end(), id) == streamIds.end()) {
5818 SET_ERR("stream ID %d not found!", id);
5819 return UNKNOWN_ERROR;
5820 }
5821
5822 // When not using HAL buf manager, only allow streams requested by app to be preserved
5823 if (!mUseHalBufManager) {
5824 if (std::find(streamsToKeep.begin(), streamsToKeep.end(), id) == streamsToKeep.end()) {
5825 SET_ERR("stream ID %d must not be switched to offline!", id);
5826 return UNKNOWN_ERROR;
5827 }
5828 }
5829
5830 offlineStreamIds.push_back(id);
5831 sp<Camera3StreamInterface> stream = (id == inputStreamId) ?
5832 static_cast<sp<Camera3StreamInterface>>(mInputStream) :
5833 static_cast<sp<Camera3StreamInterface>>(mOutputStreams.get(id));
5834 // Verify number of outstanding buffers
5835 if (stream->getOutstandingBuffersCount() != offlineStream.numOutstandingBuffers) {
5836 SET_ERR("Offline stream %d # of remaining buffer mismatch: (%zu,%d) (service/HAL)",
5837 id, stream->getOutstandingBuffersCount(), offlineStream.numOutstandingBuffers);
5838 return UNKNOWN_ERROR;
5839 }
5840 }
5841
5842 // Verify all streams to be deleted don't have any outstanding buffers
5843 if (hasInputStream && std::find(offlineStreamIds.begin(), offlineStreamIds.end(),
5844 inputStreamId) == offlineStreamIds.end()) {
5845 if (mInputStream->hasOutstandingBuffers()) {
5846 SET_ERR("Input stream %d still has %zu outstanding buffer!",
5847 inputStreamId, mInputStream->getOutstandingBuffersCount());
5848 return UNKNOWN_ERROR;
5849 }
5850 }
5851
5852 for (const auto& outStreamId : outputStreamIds) {
5853 if (std::find(offlineStreamIds.begin(), offlineStreamIds.end(),
5854 outStreamId) == offlineStreamIds.end()) {
5855 auto outStream = mOutputStreams.get(outStreamId);
5856 if (outStream->hasOutstandingBuffers()) {
5857 SET_ERR("Output stream %d still has %zu outstanding buffer!",
5858 outStreamId, outStream->getOutstandingBuffersCount());
5859 return UNKNOWN_ERROR;
5860 }
5861 }
5862 }
5863
5864 InFlightRequestMap offlineReqs;
5865 // Verify inflight requests and their pending buffers
5866 {
5867 std::lock_guard<std::mutex> l(mInFlightLock);
5868 for (auto offlineReq : offlineSessionInfo.offlineRequests) {
5869 int idx = mInFlightMap.indexOfKey(offlineReq.frameNumber);
5870 if (idx == NAME_NOT_FOUND) {
5871 SET_ERR("Offline request frame number %d not found!", offlineReq.frameNumber);
5872 return UNKNOWN_ERROR;
5873 }
5874
5875 const auto& inflightReq = mInFlightMap.valueAt(idx);
5876 // TODO: check specific stream IDs
5877 size_t numBuffersLeft = static_cast<size_t>(inflightReq.numBuffersLeft);
5878 if (numBuffersLeft != offlineReq.pendingStreams.size()) {
5879 SET_ERR("Offline request # of remaining buffer mismatch: (%d,%d) (service/HAL)",
5880 inflightReq.numBuffersLeft, offlineReq.pendingStreams.size());
5881 return UNKNOWN_ERROR;
5882 }
5883 offlineReqs.add(offlineReq.frameNumber, inflightReq);
5884 }
5885 }
5886
5887 // Create Camera3OfflineSession and transfer object ownership
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005888 // (streams, inflight requests, buffer caches)
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005889 camera3::StreamSet offlineStreamSet;
5890 sp<camera3::Camera3Stream> inputStream;
5891 for (auto offlineStream : offlineSessionInfo.offlineStreams) {
5892 int32_t id = offlineStream.id;
5893 if (mInputStream != nullptr && id == mInputStream->getId()) {
5894 inputStream = mInputStream;
5895 } else {
5896 offlineStreamSet.add(id, mOutputStreams.get(id));
5897 }
5898 }
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005899
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005900 // TODO: check if we need to lock before copying states
5901 // though technically no other thread should be talking to Camera3Device at this point
5902 Camera3OfflineStates offlineStates(
5903 mTagMonitor, mVendorTagId, mUseHalBufManager, mNeedFixupMonochromeTags,
5904 mUsePartialResult, mNumPartialResults, mNextResultFrameNumber,
5905 mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
5906 mNextShutterFrameNumber, mNextReprocessShutterFrameNumber,
5907 mNextZslStillShutterFrameNumber, mDeviceInfo, mPhysicalDeviceInfoMap,
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08005908 mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers);
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005909
5910 *session = new Camera3OfflineSession(mId, inputStream, offlineStreamSet,
5911 std::move(bufferRecords), offlineReqs, offlineStates, offlineSession);
5912
5913 // Delete all streams that has been transferred to offline session
5914 Mutex::Autolock l(mLock);
5915 for (auto offlineStream : offlineSessionInfo.offlineStreams) {
5916 int32_t id = offlineStream.id;
5917 if (mInputStream != nullptr && id == mInputStream->getId()) {
5918 mInputStream.clear();
5919 } else {
5920 mOutputStreams.remove(id);
5921 }
5922 }
5923
5924 // disconnect all other streams and switch to UNCONFIGURED state
5925 if (mInputStream != nullptr) {
5926 ret = mInputStream->disconnect();
5927 if (ret != OK) {
5928 SET_ERR_L("disconnect input stream failed!");
5929 return UNKNOWN_ERROR;
5930 }
5931 }
5932
5933 for (auto streamId : mOutputStreams.getStreamIds()) {
5934 sp<Camera3StreamInterface> stream = mOutputStreams.get(streamId);
5935 ret = stream->disconnect();
5936 if (ret != OK) {
5937 SET_ERR_L("disconnect output stream %d failed!", streamId);
5938 return UNKNOWN_ERROR;
5939 }
5940 }
5941
5942 mInputStream.clear();
5943 mOutputStreams.clear();
5944 mNeedConfig = true;
5945 internalUpdateStatusLocked(STATUS_UNCONFIGURED);
5946 mOperatingMode = NO_MODE;
5947 mIsConstrainedHighSpeedConfiguration = false;
Emilian Peevc0fe54c2020-03-11 14:05:07 -07005948 mRequestThread->clearPreviousRequest();
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005949
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005950 return OK;
Yin-Chia Yeh5fd603e2019-11-20 11:22:27 -08005951 // TO be done by CameraDeviceClient/Camera3OfflineSession
5952 // register the offline client to camera service
5953 // Setup result passthing threads etc
5954 // Initialize offline session so HAL can start sending callback to it (result Fmq)
5955 // TODO: check how many onIdle callback will be sent
5956 // Java side to make sure the CameraCaptureSession is properly closed
Yin-Chia Yehb978c382019-10-30 00:22:37 -07005957}
5958
Emilian Peevcc0b7952020-01-07 13:54:47 -08005959void Camera3Device::getOfflineStreamIds(std::vector<int> *offlineStreamIds) {
5960 ATRACE_CALL();
5961
5962 if (offlineStreamIds == nullptr) {
5963 return;
5964 }
5965
5966 Mutex::Autolock il(mInterfaceLock);
5967
5968 auto streamIds = mOutputStreams.getStreamIds();
5969 bool hasInputStream = mInputStream != nullptr;
5970 if (hasInputStream && mInputStream->getOfflineProcessingSupport()) {
5971 offlineStreamIds->push_back(mInputStream->getId());
5972 }
5973
5974 for (const auto & streamId : streamIds) {
5975 sp<camera3::Camera3OutputStreamInterface> stream = mOutputStreams.get(streamId);
5976 // Streams that use the camera buffer manager are currently not supported in
5977 // offline mode
5978 if (stream->getOfflineProcessingSupport() &&
5979 (stream->getStreamSetId() == CAMERA3_STREAM_SET_ID_INVALID)) {
5980 offlineStreamIds->push_back(streamId);
5981 }
5982 }
5983}
5984
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -08005985status_t Camera3Device::setRotateAndCropAutoBehavior(
5986 camera_metadata_enum_android_scaler_rotate_and_crop_t rotateAndCropValue) {
5987 ATRACE_CALL();
5988 Mutex::Autolock il(mInterfaceLock);
5989 Mutex::Autolock l(mLock);
5990 if (mRequestThread == nullptr) {
5991 return INVALID_OPERATION;
5992 }
5993 return mRequestThread->setRotateAndCropAutoBehavior(rotateAndCropValue);
5994}
5995
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08005996}; // namespace android