blob: bd15620f36b41af4ef2158654ca69bbbe9fc9b01 [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
32// Convenience macros for transitioning to the error state
33#define SET_ERR(fmt, ...) setErrorState( \
34 "%s: " fmt, __FUNCTION__, \
35 ##__VA_ARGS__)
36#define SET_ERR_L(fmt, ...) setErrorStateLocked( \
37 "%s: " fmt, __FUNCTION__, \
38 ##__VA_ARGS__)
39
Colin Crosse5729fa2014-03-21 15:04:25 -070040#include <inttypes.h>
41
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -080042#include <utils/Log.h>
43#include <utils/Trace.h>
44#include <utils/Timers.h>
Zhijun He90f7c372016-08-16 16:19:43 -070045#include <cutils/properties.h>
Eino-Ville Talvala7b82efe2013-07-25 17:12:35 -070046
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -080047#include <android/hardware/camera2/ICameraDeviceUser.h>
48
Igor Murashkinff3e31d2013-10-23 16:40:06 -070049#include "utils/CameraTraces.h"
Eino-Ville Talvalaf99498e2015-09-25 16:52:55 -070050#include "mediautils/SchedulingPolicyService.h"
Eino-Ville Talvala7b82efe2013-07-25 17:12:35 -070051#include "device3/Camera3Device.h"
52#include "device3/Camera3OutputStream.h"
53#include "device3/Camera3InputStream.h"
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -070054#include "device3/Camera3DummyStream.h"
Shuzhen Wang0129d522016-10-30 22:43:41 -070055#include "device3/Camera3SharedOutputStream.h"
Eino-Ville Talvalaf67e23e2014-07-23 17:17:59 -070056#include "CameraService.h"
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -080057
Emilian Peev5fbe0ba2017-10-20 15:45:45 +010058#include <android/hardware/camera/device/3.4/ICameraDeviceSession.h>
59
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -080060using namespace android::camera3;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -080061using namespace android::hardware::camera;
62using namespace android::hardware::camera::device::V3_2;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -080063
64namespace android {
65
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -080066Camera3Device::Camera3Device(const String8 &id):
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -080067 mId(id),
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -080068 mOperatingMode(NO_MODE),
Eino-Ville Talvala9a179412015-06-09 13:15:16 -070069 mIsConstrainedHighSpeedConfiguration(false),
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -070070 mStatus(STATUS_UNINITIALIZED),
Ruben Brunk183f0562015-08-12 12:55:02 -070071 mStatusWaiters(0),
Zhijun He204e3292014-07-14 17:09:23 -070072 mUsePartialResult(false),
73 mNumPartialResults(1),
Shuzhen Wangc28dccc2016-02-11 23:48:46 -080074 mTimestampOffset(0),
Eino-Ville Talvala42368d92013-04-09 14:13:50 -070075 mNextResultFrameNumber(0),
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -070076 mNextReprocessResultFrameNumber(0),
Eino-Ville Talvala42368d92013-04-09 14:13:50 -070077 mNextShutterFrameNumber(0),
Chien-Yu Chen3df11ce2015-09-30 14:13:30 -070078 mNextReprocessShutterFrameNumber(0),
Emilian Peev71c73a22017-03-21 16:35:51 +000079 mListener(NULL),
80 mVendorTagId(CAMERA_METADATA_INVALID_VENDOR_ID)
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -080081{
82 ATRACE_CALL();
83 camera3_callback_ops::notify = &sNotify;
84 camera3_callback_ops::process_capture_result = &sProcessCaptureResult;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -080085 ALOGV("%s: Created device for camera %s", __FUNCTION__, mId.string());
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -080086}
87
88Camera3Device::~Camera3Device()
89{
90 ATRACE_CALL();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -080091 ALOGV("%s: Tearing down for camera id %s", __FUNCTION__, mId.string());
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -080092 disconnect();
93}
94
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -080095const String8& Camera3Device::getId() const {
Igor Murashkin71381052013-03-04 14:53:08 -080096 return mId;
97}
98
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -080099status_t Camera3Device::initialize(sp<CameraProviderManager> manager) {
100 ATRACE_CALL();
101 Mutex::Autolock il(mInterfaceLock);
102 Mutex::Autolock l(mLock);
103
104 ALOGV("%s: Initializing HIDL device for camera %s", __FUNCTION__, mId.string());
105 if (mStatus != STATUS_UNINITIALIZED) {
106 CLOGE("Already initialized!");
107 return INVALID_OPERATION;
108 }
109 if (manager == nullptr) return INVALID_OPERATION;
110
111 sp<ICameraDeviceSession> session;
112 ATRACE_BEGIN("CameraHal::openSession");
Steven Moreland5ff9c912017-03-09 23:13:00 -0800113 status_t res = manager->openSession(mId.string(), this,
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800114 /*out*/ &session);
115 ATRACE_END();
116 if (res != OK) {
117 SET_ERR_L("Could not open camera session: %s (%d)", strerror(-res), res);
118 return res;
119 }
120
Steven Moreland5ff9c912017-03-09 23:13:00 -0800121 res = manager->getCameraCharacteristics(mId.string(), &mDeviceInfo);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800122 if (res != OK) {
123 SET_ERR_L("Could not retrive camera characteristics: %s (%d)", strerror(-res), res);
124 session->close();
125 return res;
126 }
Yin-Chia Yeh52778d42016-12-22 18:20:43 -0800127
Yifan Hongf79b5542017-04-11 14:44:25 -0700128 std::shared_ptr<RequestMetadataQueue> queue;
Yifan Honga640c5a2017-04-12 16:30:31 -0700129 auto requestQueueRet = session->getCaptureRequestMetadataQueue(
130 [&queue](const auto& descriptor) {
131 queue = std::make_shared<RequestMetadataQueue>(descriptor);
132 if (!queue->isValid() || queue->availableToWrite() <= 0) {
133 ALOGE("HAL returns empty request metadata fmq, not use it");
134 queue = nullptr;
135 // don't use the queue onwards.
136 }
137 });
138 if (!requestQueueRet.isOk()) {
139 ALOGE("Transaction error when getting request metadata fmq: %s, not use it",
140 requestQueueRet.description().c_str());
Eino-Ville Talvalac5cbb872017-04-27 12:48:33 -0700141 return DEAD_OBJECT;
Yifan Hongf79b5542017-04-11 14:44:25 -0700142 }
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700143
144 std::unique_ptr<ResultMetadataQueue>& resQueue = mResultMetadataQueue;
Yifan Honga640c5a2017-04-12 16:30:31 -0700145 auto resultQueueRet = session->getCaptureResultMetadataQueue(
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700146 [&resQueue](const auto& descriptor) {
147 resQueue = std::make_unique<ResultMetadataQueue>(descriptor);
148 if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
Yifan Honga640c5a2017-04-12 16:30:31 -0700149 ALOGE("HAL returns empty result metadata fmq, not use it");
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700150 resQueue = nullptr;
151 // Don't use the resQueue onwards.
Yifan Honga640c5a2017-04-12 16:30:31 -0700152 }
153 });
154 if (!resultQueueRet.isOk()) {
155 ALOGE("Transaction error when getting result metadata queue from camera session: %s",
156 resultQueueRet.description().c_str());
Eino-Ville Talvalac5cbb872017-04-27 12:48:33 -0700157 return DEAD_OBJECT;
Yifan Honga640c5a2017-04-12 16:30:31 -0700158 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -0700159 IF_ALOGV() {
160 session->interfaceChain([](
161 ::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
162 ALOGV("Session interface chain:");
163 for (auto iface : interfaceChain) {
164 ALOGV(" %s", iface.c_str());
165 }
166 });
167 }
Yifan Hongf79b5542017-04-11 14:44:25 -0700168
Yin-Chia Yehdb1e8642017-07-14 15:19:30 -0700169 mInterface = new HalInterface(session, queue);
Emilian Peev71c73a22017-03-21 16:35:51 +0000170 std::string providerType;
171 mVendorTagId = manager->getProviderTagIdLocked(mId.string());
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800172
173 return initializeCommonLocked();
174}
175
176status_t Camera3Device::initializeCommonLocked() {
177
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700178 /** Start up status tracker thread */
179 mStatusTracker = new StatusTracker(this);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800180 status_t res = mStatusTracker->run(String8::format("C3Dev-%s-Status", mId.string()).string());
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700181 if (res != OK) {
182 SET_ERR_L("Unable to start status tracking thread: %s (%d)",
183 strerror(-res), res);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800184 mInterface->close();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700185 mStatusTracker.clear();
186 return res;
187 }
188
Eino-Ville Talvala24b366e2016-07-21 12:53:07 -0700189 /** Register in-flight map to the status tracker */
190 mInFlightStatusId = mStatusTracker->addComponent();
191
Zhijun He125684a2015-12-26 15:07:30 -0800192 /** Create buffer manager */
193 mBufferManager = new Camera3BufferManager();
194
Emilian Peev71c73a22017-03-21 16:35:51 +0000195 mTagMonitor.initialize(mVendorTagId);
196
Emilian Peevac3ce6c2017-12-12 15:27:02 +0000197 Vector<int32_t> sessionParamKeys;
198 camera_metadata_entry_t sessionKeysEntry = mDeviceInfo.find(
199 ANDROID_REQUEST_AVAILABLE_SESSION_KEYS);
200 if (sessionKeysEntry.count > 0) {
201 sessionParamKeys.insertArrayAt(sessionKeysEntry.data.i32, 0, sessionKeysEntry.count);
202 }
Chien-Yu Chenab5135b2015-06-30 11:20:58 -0700203 /** Start up request queue thread */
Emilian Peevac3ce6c2017-12-12 15:27:02 +0000204 mRequestThread = new RequestThread(this, mStatusTracker, mInterface, sessionParamKeys);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800205 res = mRequestThread->run(String8::format("C3Dev-%s-ReqQueue", mId.string()).string());
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800206 if (res != OK) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -0700207 SET_ERR_L("Unable to start request queue thread: %s (%d)",
208 strerror(-res), res);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800209 mInterface->close();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800210 mRequestThread.clear();
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800211 return res;
212 }
213
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -0700214 mPreparerThread = new PreparerThread();
215
Ruben Brunk183f0562015-08-12 12:55:02 -0700216 internalUpdateStatusLocked(STATUS_UNCONFIGURED);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800217 mNextStreamId = 0;
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -0700218 mDummyStreamId = NO_STREAM;
Eino-Ville Talvalaea26c772013-06-11 16:04:06 -0700219 mNeedConfig = true;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700220 mPauseStateNotify = false;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800221
Shuzhen Wangc28dccc2016-02-11 23:48:46 -0800222 // Measure the clock domain offset between camera and video/hw_composer
223 camera_metadata_entry timestampSource =
224 mDeviceInfo.find(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE);
225 if (timestampSource.count > 0 && timestampSource.data.u8[0] ==
226 ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME) {
227 mTimestampOffset = getMonoToBoottimeOffset();
228 }
229
Eino-Ville Talvalafd6ecdd2013-10-11 09:51:09 -0700230 // Will the HAL be sending in early partial result metadata?
Emilian Peev08dd2452017-04-06 16:55:14 +0100231 camera_metadata_entry partialResultsCount =
232 mDeviceInfo.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
233 if (partialResultsCount.count > 0) {
234 mNumPartialResults = partialResultsCount.data.i32[0];
235 mUsePartialResult = (mNumPartialResults > 1);
Eino-Ville Talvalafd6ecdd2013-10-11 09:51:09 -0700236 }
237
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700238 camera_metadata_entry configs =
239 mDeviceInfo.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
240 for (uint32_t i = 0; i < configs.count; i += 4) {
241 if (configs.data.i32[i] == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED &&
242 configs.data.i32[i + 3] ==
243 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT) {
244 mSupportedOpaqueInputSizes.add(Size(configs.data.i32[i + 1],
245 configs.data.i32[i + 2]));
246 }
247 }
248
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800249 return OK;
250}
251
252status_t Camera3Device::disconnect() {
253 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700254 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800255
Yin-Chia Yehe1c80632016-08-08 14:48:05 -0700256 ALOGI("%s: E", __FUNCTION__);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800257
Eino-Ville Talvala214a17f2013-06-13 12:20:02 -0700258 status_t res = OK;
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700259 std::vector<wp<Camera3StreamInterface>> streams;
Yin-Chia Yeh598fc602017-07-24 11:37:23 -0700260 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700261 {
262 Mutex::Autolock l(mLock);
263 if (mStatus == STATUS_UNINITIALIZED) return res;
264
265 if (mStatus == STATUS_ACTIVE ||
266 (mStatus == STATUS_ERROR && mRequestThread != NULL)) {
267 res = mRequestThread->clearRepeatingRequests();
Eino-Ville Talvala214a17f2013-06-13 12:20:02 -0700268 if (res != OK) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700269 SET_ERR_L("Can't stop streaming");
Eino-Ville Talvala214a17f2013-06-13 12:20:02 -0700270 // Continue to close device even in case of error
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700271 } else {
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -0700272 res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700273 if (res != OK) {
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -0700274 SET_ERR_L("Timeout waiting for HAL to drain (% " PRIi64 " ns)",
275 maxExpectedDuration);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700276 // Continue to close device even in case of error
277 }
Eino-Ville Talvala214a17f2013-06-13 12:20:02 -0700278 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800279 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800280
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700281 if (mStatus == STATUS_ERROR) {
282 CLOGE("Shutting down in an error state");
Eino-Ville Talvala214a17f2013-06-13 12:20:02 -0700283 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700284
285 if (mStatusTracker != NULL) {
286 mStatusTracker->requestExit();
287 }
288
289 if (mRequestThread != NULL) {
290 mRequestThread->requestExit();
291 }
292
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700293 streams.reserve(mOutputStreams.size() + (mInputStream != nullptr ? 1 : 0));
294 for (size_t i = 0; i < mOutputStreams.size(); i++) {
295 streams.push_back(mOutputStreams[i]);
296 }
297 if (mInputStream != nullptr) {
298 streams.push_back(mInputStream);
299 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700300 }
301
302 // Joining done without holding mLock, otherwise deadlocks may ensue
303 // as the threads try to access parent state
304 if (mRequestThread != NULL && mStatus != STATUS_ERROR) {
305 // HAL may be in a bad state, so waiting for request thread
306 // (which may be stuck in the HAL processCaptureRequest call)
307 // could be dangerous.
308 mRequestThread->join();
309 }
310
311 if (mStatusTracker != NULL) {
312 mStatusTracker->join();
313 }
314
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800315 HalInterface* interface;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700316 {
317 Mutex::Autolock l(mLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800318 mRequestThread.clear();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700319 mStatusTracker.clear();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800320 interface = mInterface.get();
Eino-Ville Talvalaefff1c42015-08-28 16:27:27 -0700321 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800322
Eino-Ville Talvalaefff1c42015-08-28 16:27:27 -0700323 // Call close without internal mutex held, as the HAL close may need to
324 // wait on assorted callbacks,etc, to complete before it can return.
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800325 interface->close();
Eino-Ville Talvalaefff1c42015-08-28 16:27:27 -0700326
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700327 flushInflightRequests();
328
Eino-Ville Talvalaefff1c42015-08-28 16:27:27 -0700329 {
330 Mutex::Autolock l(mLock);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800331 mInterface->clear();
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700332 mOutputStreams.clear();
333 mInputStream.clear();
Yin-Chia Yeh5090c732017-07-20 16:05:29 -0700334 mDeletedStreams.clear();
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700335 mBufferManager.clear();
Ruben Brunk183f0562015-08-12 12:55:02 -0700336 internalUpdateStatusLocked(STATUS_UNINITIALIZED);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700337 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800338
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700339 for (auto& weakStream : streams) {
340 sp<Camera3StreamInterface> stream = weakStream.promote();
341 if (stream != nullptr) {
342 ALOGE("%s: Stream %d leaked! strong reference (%d)!",
343 __FUNCTION__, stream->getId(), stream->getStrongCount() - 1);
344 }
345 }
346
Yin-Chia Yehe1c80632016-08-08 14:48:05 -0700347 ALOGI("%s: X", __FUNCTION__);
Eino-Ville Talvala214a17f2013-06-13 12:20:02 -0700348 return res;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800349}
350
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700351// For dumping/debugging only -
352// try to acquire a lock a few times, eventually give up to proceed with
353// debug/dump operations
354bool Camera3Device::tryLockSpinRightRound(Mutex& lock) {
355 bool gotLock = false;
356 for (size_t i = 0; i < kDumpLockAttempts; ++i) {
357 if (lock.tryLock() == NO_ERROR) {
358 gotLock = true;
359 break;
360 } else {
361 usleep(kDumpSleepDuration);
362 }
363 }
364 return gotLock;
365}
366
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700367Camera3Device::Size Camera3Device::getMaxJpegResolution() const {
368 int32_t maxJpegWidth = 0, maxJpegHeight = 0;
Emilian Peev08dd2452017-04-06 16:55:14 +0100369 const int STREAM_CONFIGURATION_SIZE = 4;
370 const int STREAM_FORMAT_OFFSET = 0;
371 const int STREAM_WIDTH_OFFSET = 1;
372 const int STREAM_HEIGHT_OFFSET = 2;
373 const int STREAM_IS_INPUT_OFFSET = 3;
374 camera_metadata_ro_entry_t availableStreamConfigs =
375 mDeviceInfo.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
376 if (availableStreamConfigs.count == 0 ||
377 availableStreamConfigs.count % STREAM_CONFIGURATION_SIZE != 0) {
378 return Size(0, 0);
379 }
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700380
Emilian Peev08dd2452017-04-06 16:55:14 +0100381 // Get max jpeg size (area-wise).
382 for (size_t i=0; i < availableStreamConfigs.count; i+= STREAM_CONFIGURATION_SIZE) {
383 int32_t format = availableStreamConfigs.data.i32[i + STREAM_FORMAT_OFFSET];
384 int32_t width = availableStreamConfigs.data.i32[i + STREAM_WIDTH_OFFSET];
385 int32_t height = availableStreamConfigs.data.i32[i + STREAM_HEIGHT_OFFSET];
386 int32_t isInput = availableStreamConfigs.data.i32[i + STREAM_IS_INPUT_OFFSET];
387 if (isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT
388 && format == HAL_PIXEL_FORMAT_BLOB &&
389 (width * height > maxJpegWidth * maxJpegHeight)) {
390 maxJpegWidth = width;
391 maxJpegHeight = height;
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700392 }
393 }
Emilian Peev08dd2452017-04-06 16:55:14 +0100394
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700395 return Size(maxJpegWidth, maxJpegHeight);
396}
397
Shuzhen Wangc28dccc2016-02-11 23:48:46 -0800398nsecs_t Camera3Device::getMonoToBoottimeOffset() {
399 // try three times to get the clock offset, choose the one
400 // with the minimum gap in measurements.
401 const int tries = 3;
402 nsecs_t bestGap, measured;
403 for (int i = 0; i < tries; ++i) {
404 const nsecs_t tmono = systemTime(SYSTEM_TIME_MONOTONIC);
405 const nsecs_t tbase = systemTime(SYSTEM_TIME_BOOTTIME);
406 const nsecs_t tmono2 = systemTime(SYSTEM_TIME_MONOTONIC);
407 const nsecs_t gap = tmono2 - tmono;
408 if (i == 0 || gap < bestGap) {
409 bestGap = gap;
410 measured = tbase - ((tmono + tmono2) >> 1);
411 }
412 }
413 return measured;
414}
415
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800416hardware::graphics::common::V1_0::PixelFormat Camera3Device::mapToPixelFormat(
417 int frameworkFormat) {
418 return (hardware::graphics::common::V1_0::PixelFormat) frameworkFormat;
419}
420
421DataspaceFlags Camera3Device::mapToHidlDataspace(
422 android_dataspace dataSpace) {
423 return dataSpace;
424}
425
Chia-I Wu67a0c0e2017-04-06 13:37:01 -0700426BufferUsageFlags Camera3Device::mapToConsumerUsage(
Emilian Peev050f5dc2017-05-18 14:43:56 +0100427 uint64_t usage) {
Yin-Chia Yeh47cf8e62017-04-04 13:00:03 -0700428 return usage;
429}
430
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800431StreamRotation Camera3Device::mapToStreamRotation(camera3_stream_rotation_t rotation) {
432 switch (rotation) {
433 case CAMERA3_STREAM_ROTATION_0:
434 return StreamRotation::ROTATION_0;
435 case CAMERA3_STREAM_ROTATION_90:
436 return StreamRotation::ROTATION_90;
437 case CAMERA3_STREAM_ROTATION_180:
438 return StreamRotation::ROTATION_180;
439 case CAMERA3_STREAM_ROTATION_270:
440 return StreamRotation::ROTATION_270;
441 }
442 ALOGE("%s: Unknown stream rotation %d", __FUNCTION__, rotation);
443 return StreamRotation::ROTATION_0;
444}
445
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -0800446status_t Camera3Device::mapToStreamConfigurationMode(
447 camera3_stream_configuration_mode_t operationMode, StreamConfigurationMode *mode) {
448 if (mode == nullptr) return BAD_VALUE;
449 if (operationMode < CAMERA3_VENDOR_STREAM_CONFIGURATION_MODE_START) {
450 switch(operationMode) {
451 case CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE:
452 *mode = StreamConfigurationMode::NORMAL_MODE;
453 break;
454 case CAMERA3_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE:
455 *mode = StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE;
456 break;
457 default:
458 ALOGE("%s: Unknown stream configuration mode %d", __FUNCTION__, operationMode);
459 return BAD_VALUE;
460 }
461 } else {
462 *mode = static_cast<StreamConfigurationMode>(operationMode);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800463 }
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -0800464 return OK;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800465}
466
467camera3_buffer_status_t Camera3Device::mapHidlBufferStatus(BufferStatus status) {
468 switch (status) {
469 case BufferStatus::OK: return CAMERA3_BUFFER_STATUS_OK;
470 case BufferStatus::ERROR: return CAMERA3_BUFFER_STATUS_ERROR;
471 }
472 return CAMERA3_BUFFER_STATUS_ERROR;
473}
474
475int Camera3Device::mapToFrameworkFormat(
476 hardware::graphics::common::V1_0::PixelFormat pixelFormat) {
477 return static_cast<uint32_t>(pixelFormat);
478}
479
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -0700480android_dataspace Camera3Device::mapToFrameworkDataspace(
481 DataspaceFlags dataSpace) {
482 return static_cast<android_dataspace>(dataSpace);
483}
484
Emilian Peev050f5dc2017-05-18 14:43:56 +0100485uint64_t Camera3Device::mapConsumerToFrameworkUsage(
Chia-I Wu67a0c0e2017-04-06 13:37:01 -0700486 BufferUsageFlags usage) {
Yin-Chia Yeh47cf8e62017-04-04 13:00:03 -0700487 return usage;
488}
489
Emilian Peev050f5dc2017-05-18 14:43:56 +0100490uint64_t Camera3Device::mapProducerToFrameworkUsage(
Chia-I Wu67a0c0e2017-04-06 13:37:01 -0700491 BufferUsageFlags usage) {
Yin-Chia Yeh47cf8e62017-04-04 13:00:03 -0700492 return usage;
493}
494
Zhijun Hef7da0962014-04-24 13:27:56 -0700495ssize_t Camera3Device::getJpegBufferSize(uint32_t width, uint32_t height) const {
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700496 // Get max jpeg size (area-wise).
497 Size maxJpegResolution = getMaxJpegResolution();
498 if (maxJpegResolution.width == 0) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800499 ALOGE("%s: Camera %s: Can't find valid available jpeg sizes in static metadata!",
500 __FUNCTION__, mId.string());
Zhijun Hef7da0962014-04-24 13:27:56 -0700501 return BAD_VALUE;
502 }
503
Zhijun Hef7da0962014-04-24 13:27:56 -0700504 // Get max jpeg buffer size
505 ssize_t maxJpegBufferSize = 0;
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700506 camera_metadata_ro_entry jpegBufMaxSize = mDeviceInfo.find(ANDROID_JPEG_MAX_SIZE);
507 if (jpegBufMaxSize.count == 0) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800508 ALOGE("%s: Camera %s: Can't find maximum JPEG size in static metadata!", __FUNCTION__,
509 mId.string());
Zhijun Hef7da0962014-04-24 13:27:56 -0700510 return BAD_VALUE;
511 }
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700512 maxJpegBufferSize = jpegBufMaxSize.data.i32[0];
Yin-Chia Yeh0c4e56d2015-01-09 15:21:27 -0800513 assert(kMinJpegBufferSize < maxJpegBufferSize);
Zhijun Hef7da0962014-04-24 13:27:56 -0700514
515 // Calculate final jpeg buffer size for the given resolution.
Yin-Chia Yehcd8fce82014-06-18 10:51:34 -0700516 float scaleFactor = ((float) (width * height)) /
517 (maxJpegResolution.width * maxJpegResolution.height);
Yin-Chia Yeh0c4e56d2015-01-09 15:21:27 -0800518 ssize_t jpegBufferSize = scaleFactor * (maxJpegBufferSize - kMinJpegBufferSize) +
519 kMinJpegBufferSize;
Zhijun Hef7da0962014-04-24 13:27:56 -0700520 if (jpegBufferSize > maxJpegBufferSize) {
521 jpegBufferSize = maxJpegBufferSize;
Zhijun Hef7da0962014-04-24 13:27:56 -0700522 }
523
524 return jpegBufferSize;
525}
526
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -0700527ssize_t Camera3Device::getPointCloudBufferSize() const {
528 const int FLOATS_PER_POINT=4;
529 camera_metadata_ro_entry maxPointCount = mDeviceInfo.find(ANDROID_DEPTH_MAX_DEPTH_SAMPLES);
530 if (maxPointCount.count == 0) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800531 ALOGE("%s: Camera %s: Can't find maximum depth point cloud size in static metadata!",
532 __FUNCTION__, mId.string());
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -0700533 return BAD_VALUE;
534 }
535 ssize_t maxBytesForPointCloud = sizeof(android_depth_points) +
536 maxPointCount.data.i32[0] * sizeof(float) * FLOATS_PER_POINT;
537 return maxBytesForPointCloud;
538}
539
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800540ssize_t Camera3Device::getRawOpaqueBufferSize(int32_t width, int32_t height) const {
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800541 const int PER_CONFIGURATION_SIZE = 3;
542 const int WIDTH_OFFSET = 0;
543 const int HEIGHT_OFFSET = 1;
544 const int SIZE_OFFSET = 2;
545 camera_metadata_ro_entry rawOpaqueSizes =
546 mDeviceInfo.find(ANDROID_SENSOR_OPAQUE_RAW_SIZE);
Aurimas Liutikasbc57b122016-02-16 09:59:16 -0800547 size_t count = rawOpaqueSizes.count;
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800548 if (count == 0 || (count % PER_CONFIGURATION_SIZE)) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800549 ALOGE("%s: Camera %s: bad opaque RAW size static metadata length(%zu)!",
550 __FUNCTION__, mId.string(), count);
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800551 return BAD_VALUE;
552 }
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -0700553
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800554 for (size_t i = 0; i < count; i += PER_CONFIGURATION_SIZE) {
555 if (width == rawOpaqueSizes.data.i32[i + WIDTH_OFFSET] &&
556 height == rawOpaqueSizes.data.i32[i + HEIGHT_OFFSET]) {
557 return rawOpaqueSizes.data.i32[i + SIZE_OFFSET];
558 }
559 }
560
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800561 ALOGE("%s: Camera %s: cannot find size for %dx%d opaque RAW image!",
562 __FUNCTION__, mId.string(), width, height);
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -0800563 return BAD_VALUE;
564}
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -0700565
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800566status_t Camera3Device::dump(int fd, const Vector<String16> &args) {
567 ATRACE_CALL();
568 (void)args;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700569
570 // Try to lock, but continue in case of failure (to avoid blocking in
571 // deadlocks)
572 bool gotInterfaceLock = tryLockSpinRightRound(mInterfaceLock);
573 bool gotLock = tryLockSpinRightRound(mLock);
574
575 ALOGW_IF(!gotInterfaceLock,
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800576 "Camera %s: %s: Unable to lock interface lock, proceeding anyway",
577 mId.string(), __FUNCTION__);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700578 ALOGW_IF(!gotLock,
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800579 "Camera %s: %s: Unable to lock main lock, proceeding anyway",
580 mId.string(), __FUNCTION__);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700581
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800582 bool dumpTemplates = false;
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700583
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800584 String16 templatesOption("-t");
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700585 String16 monitorOption("-m");
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800586 int n = args.size();
587 for (int i = 0; i < n; i++) {
588 if (args[i] == templatesOption) {
589 dumpTemplates = true;
590 }
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700591 if (args[i] == monitorOption) {
592 if (i + 1 < n) {
593 String8 monitorTags = String8(args[i + 1]);
594 if (monitorTags == "off") {
595 mTagMonitor.disableMonitoring();
596 } else {
597 mTagMonitor.parseTagsToMonitor(monitorTags);
598 }
599 } else {
600 mTagMonitor.disableMonitoring();
601 }
602 }
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800603 }
604
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800605 String8 lines;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800606
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800607 const char *status =
608 mStatus == STATUS_ERROR ? "ERROR" :
609 mStatus == STATUS_UNINITIALIZED ? "UNINITIALIZED" :
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700610 mStatus == STATUS_UNCONFIGURED ? "UNCONFIGURED" :
611 mStatus == STATUS_CONFIGURED ? "CONFIGURED" :
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800612 mStatus == STATUS_ACTIVE ? "ACTIVE" :
613 "Unknown";
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700614
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800615 lines.appendFormat(" Device status: %s\n", status);
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -0700616 if (mStatus == STATUS_ERROR) {
617 lines.appendFormat(" Error cause: %s\n", mErrorCause.string());
618 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800619 lines.appendFormat(" Stream configuration:\n");
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -0800620 const char *mode =
621 mOperatingMode == static_cast<int>(StreamConfigurationMode::NORMAL_MODE) ? "NORMAL" :
622 mOperatingMode == static_cast<int>(
623 StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE) ? "CONSTRAINED_HIGH_SPEED" :
624 "CUSTOM";
625 lines.appendFormat(" Operation mode: %s (%d) \n", mode, mOperatingMode);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800626
627 if (mInputStream != NULL) {
628 write(fd, lines.string(), lines.size());
629 mInputStream->dump(fd, args);
630 } else {
631 lines.appendFormat(" No input stream.\n");
632 write(fd, lines.string(), lines.size());
633 }
634 for (size_t i = 0; i < mOutputStreams.size(); i++) {
635 mOutputStreams[i]->dump(fd,args);
636 }
637
Zhijun He431503c2016-03-07 17:30:16 -0800638 if (mBufferManager != NULL) {
639 lines = String8(" Camera3 Buffer Manager:\n");
640 write(fd, lines.string(), lines.size());
641 mBufferManager->dump(fd, args);
642 }
Zhijun He125684a2015-12-26 15:07:30 -0800643
Eino-Ville Talvala42368d92013-04-09 14:13:50 -0700644 lines = String8(" In-flight requests:\n");
645 if (mInFlightMap.size() == 0) {
646 lines.append(" None\n");
647 } else {
648 for (size_t i = 0; i < mInFlightMap.size(); i++) {
649 InFlightRequest r = mInFlightMap.valueAt(i);
Colin Crosse5729fa2014-03-21 15:04:25 -0700650 lines.appendFormat(" Frame %d | Timestamp: %" PRId64 ", metadata"
Eino-Ville Talvala42368d92013-04-09 14:13:50 -0700651 " arrived: %s, buffers left: %d\n", mInFlightMap.keyAt(i),
Chien-Yu Chen43e69a62014-11-25 16:38:33 -0800652 r.shutterTimestamp, r.haveResultMetadata ? "true" : "false",
Eino-Ville Talvala42368d92013-04-09 14:13:50 -0700653 r.numBuffersLeft);
654 }
655 }
656 write(fd, lines.string(), lines.size());
657
Shuzhen Wang686f6442017-06-20 16:16:04 -0700658 if (mRequestThread != NULL) {
659 mRequestThread->dumpCaptureRequestLatency(fd,
660 " ProcessCaptureRequest latency histogram:");
661 }
662
Igor Murashkin1e479c02013-09-06 16:55:14 -0700663 {
664 lines = String8(" Last request sent:\n");
665 write(fd, lines.string(), lines.size());
666
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700667 CameraMetadata lastRequest = getLatestRequestLocked();
Igor Murashkin1e479c02013-09-06 16:55:14 -0700668 lastRequest.dump(fd, /*verbosity*/2, /*indentation*/6);
669 }
670
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800671 if (dumpTemplates) {
672 const char *templateNames[] = {
673 "TEMPLATE_PREVIEW",
674 "TEMPLATE_STILL_CAPTURE",
675 "TEMPLATE_VIDEO_RECORD",
676 "TEMPLATE_VIDEO_SNAPSHOT",
677 "TEMPLATE_ZERO_SHUTTER_LAG",
678 "TEMPLATE_MANUAL"
679 };
680
681 for (int i = 1; i < CAMERA3_TEMPLATE_COUNT; i++) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800682 camera_metadata_t *templateRequest = nullptr;
683 mInterface->constructDefaultRequestSettings(
684 (camera3_request_template_t) i, &templateRequest);
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800685 lines = String8::format(" HAL Request %s:\n", templateNames[i-1]);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800686 if (templateRequest == nullptr) {
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800687 lines.append(" Not supported\n");
688 write(fd, lines.string(), lines.size());
689 } else {
690 write(fd, lines.string(), lines.size());
691 dump_indented_camera_metadata(templateRequest,
692 fd, /*verbosity*/2, /*indentation*/8);
693 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800694 free_camera_metadata(templateRequest);
Eino-Ville Talvala7e7a62d2015-11-04 14:49:43 -0800695 }
696 }
697
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700698 mTagMonitor.dumpMonitoredMetadata(fd);
699
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800700 if (mInterface->valid()) {
Eino-Ville Talvalad00111e2017-01-31 11:59:12 -0800701 lines = String8(" HAL device dump:\n");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800702 write(fd, lines.string(), lines.size());
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800703 mInterface->dump(fd);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800704 }
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800705
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700706 if (gotLock) mLock.unlock();
707 if (gotInterfaceLock) mInterfaceLock.unlock();
708
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800709 return OK;
710}
711
712const CameraMetadata& Camera3Device::info() const {
713 ALOGVV("%s: E", __FUNCTION__);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800714 if (CC_UNLIKELY(mStatus == STATUS_UNINITIALIZED ||
715 mStatus == STATUS_ERROR)) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -0700716 ALOGW("%s: Access to static info %s!", __FUNCTION__,
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -0800717 mStatus == STATUS_ERROR ?
718 "when in error state" : "before init");
719 }
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800720 return mDeviceInfo;
721}
722
Jianing Wei90e59c92014-03-12 18:29:36 -0700723status_t Camera3Device::checkStatusOkToCaptureLocked() {
724 switch (mStatus) {
725 case STATUS_ERROR:
726 CLOGE("Device has encountered a serious error");
727 return INVALID_OPERATION;
728 case STATUS_UNINITIALIZED:
729 CLOGE("Device not initialized");
730 return INVALID_OPERATION;
731 case STATUS_UNCONFIGURED:
732 case STATUS_CONFIGURED:
733 case STATUS_ACTIVE:
734 // OK
735 break;
736 default:
737 SET_ERR_L("Unexpected status: %d", mStatus);
738 return INVALID_OPERATION;
739 }
740 return OK;
741}
742
743status_t Camera3Device::convertMetadataListToRequestListLocked(
Shuzhen Wang0129d522016-10-30 22:43:41 -0700744 const List<const CameraMetadata> &metadataList,
745 const std::list<const SurfaceMap> &surfaceMaps,
746 bool repeating,
Shuzhen Wang9d066012016-09-30 11:30:20 -0700747 RequestList *requestList) {
Jianing Wei90e59c92014-03-12 18:29:36 -0700748 if (requestList == NULL) {
749 CLOGE("requestList cannot be NULL.");
750 return BAD_VALUE;
751 }
752
Jianing Weicb0652e2014-03-12 18:29:36 -0700753 int32_t burstId = 0;
Shuzhen Wang0129d522016-10-30 22:43:41 -0700754 List<const CameraMetadata>::const_iterator metadataIt = metadataList.begin();
755 std::list<const SurfaceMap>::const_iterator surfaceMapIt = surfaceMaps.begin();
756 for (; metadataIt != metadataList.end() && surfaceMapIt != surfaceMaps.end();
757 ++metadataIt, ++surfaceMapIt) {
758 sp<CaptureRequest> newRequest = setUpRequestLocked(*metadataIt, *surfaceMapIt);
Jianing Wei90e59c92014-03-12 18:29:36 -0700759 if (newRequest == 0) {
760 CLOGE("Can't create capture request");
761 return BAD_VALUE;
762 }
Jianing Weicb0652e2014-03-12 18:29:36 -0700763
Shuzhen Wang9d066012016-09-30 11:30:20 -0700764 newRequest->mRepeating = repeating;
765
Jianing Weicb0652e2014-03-12 18:29:36 -0700766 // Setup burst Id and request Id
767 newRequest->mResultExtras.burstId = burstId++;
Shuzhen Wang0129d522016-10-30 22:43:41 -0700768 if (metadataIt->exists(ANDROID_REQUEST_ID)) {
769 if (metadataIt->find(ANDROID_REQUEST_ID).count == 0) {
Jianing Weicb0652e2014-03-12 18:29:36 -0700770 CLOGE("RequestID entry exists; but must not be empty in metadata");
771 return BAD_VALUE;
772 }
Shuzhen Wang0129d522016-10-30 22:43:41 -0700773 newRequest->mResultExtras.requestId = metadataIt->find(ANDROID_REQUEST_ID).data.i32[0];
Jianing Weicb0652e2014-03-12 18:29:36 -0700774 } else {
775 CLOGE("RequestID does not exist in metadata");
776 return BAD_VALUE;
777 }
778
Jianing Wei90e59c92014-03-12 18:29:36 -0700779 requestList->push_back(newRequest);
Jianing Wei2d6bb3f2014-04-11 10:00:31 -0700780
781 ALOGV("%s: requestId = %" PRId32, __FUNCTION__, newRequest->mResultExtras.requestId);
Jianing Wei90e59c92014-03-12 18:29:36 -0700782 }
Shuzhen Wang0129d522016-10-30 22:43:41 -0700783 if (metadataIt != metadataList.end() || surfaceMapIt != surfaceMaps.end()) {
784 ALOGE("%s: metadataList and surfaceMaps are not the same size!", __FUNCTION__);
785 return BAD_VALUE;
786 }
Chien-Yu Chen85a64552015-08-28 15:46:12 -0700787
788 // Setup batch size if this is a high speed video recording request.
789 if (mIsConstrainedHighSpeedConfiguration && requestList->size() > 0) {
790 auto firstRequest = requestList->begin();
791 for (auto& outputStream : (*firstRequest)->mOutputStreams) {
792 if (outputStream->isVideoStream()) {
793 (*firstRequest)->mBatchSize = requestList->size();
794 break;
795 }
796 }
797 }
798
Jianing Wei90e59c92014-03-12 18:29:36 -0700799 return OK;
800}
801
Jianing Weicb0652e2014-03-12 18:29:36 -0700802status_t Camera3Device::capture(CameraMetadata &request, int64_t* /*lastFrameNumber*/) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800803 ATRACE_CALL();
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800804
Jianing Wei2d6bb3f2014-04-11 10:00:31 -0700805 List<const CameraMetadata> requests;
Shuzhen Wang0129d522016-10-30 22:43:41 -0700806 std::list<const SurfaceMap> surfaceMaps;
807 convertToRequestList(requests, surfaceMaps, request);
808
809 return captureList(requests, surfaceMaps, /*lastFrameNumber*/NULL);
810}
811
812void Camera3Device::convertToRequestList(List<const CameraMetadata>& requests,
813 std::list<const SurfaceMap>& surfaceMaps,
814 const CameraMetadata& request) {
Jianing Wei2d6bb3f2014-04-11 10:00:31 -0700815 requests.push_back(request);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700816
817 SurfaceMap surfaceMap;
818 camera_metadata_ro_entry streams = request.find(ANDROID_REQUEST_OUTPUT_STREAMS);
819 // With no surface list passed in, stream and surface will have 1-to-1
820 // mapping. So the surface index is 0 for each stream in the surfaceMap.
821 for (size_t i = 0; i < streams.count; i++) {
822 surfaceMap[streams.data.i32[i]].push_back(0);
823 }
824 surfaceMaps.push_back(surfaceMap);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -0800825}
826
Jianing Wei90e59c92014-03-12 18:29:36 -0700827status_t Camera3Device::submitRequestsHelper(
Shuzhen Wang0129d522016-10-30 22:43:41 -0700828 const List<const CameraMetadata> &requests,
829 const std::list<const SurfaceMap> &surfaceMaps,
830 bool repeating,
Jianing Wei2d6bb3f2014-04-11 10:00:31 -0700831 /*out*/
832 int64_t *lastFrameNumber) {
Jianing Wei90e59c92014-03-12 18:29:36 -0700833 ATRACE_CALL();
834 Mutex::Autolock il(mInterfaceLock);
835 Mutex::Autolock l(mLock);
836
837 status_t res = checkStatusOkToCaptureLocked();
838 if (res != OK) {
839 // error logged by previous call
840 return res;
841 }
842
843 RequestList requestList;
844
Shuzhen Wang0129d522016-10-30 22:43:41 -0700845 res = convertMetadataListToRequestListLocked(requests, surfaceMaps,
846 repeating, /*out*/&requestList);
Jianing Wei90e59c92014-03-12 18:29:36 -0700847 if (res != OK) {
848 // error logged by previous call
849 return res;
850 }
851
852 if (repeating) {
Jianing Wei2d6bb3f2014-04-11 10:00:31 -0700853 res = mRequestThread->setRepeatingRequests(requestList, lastFrameNumber);
Jianing Wei90e59c92014-03-12 18:29:36 -0700854 } else {
Jianing Wei2d6bb3f2014-04-11 10:00:31 -0700855 res = mRequestThread->queueRequestList(requestList, lastFrameNumber);
Jianing Wei90e59c92014-03-12 18:29:36 -0700856 }
857
858 if (res == OK) {
859 waitUntilStateThenRelock(/*active*/true, kActiveTimeout);
860 if (res != OK) {
861 SET_ERR_L("Can't transition to active in %f seconds!",
862 kActiveTimeout/1e9);
863 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800864 ALOGV("Camera %s: Capture request %" PRId32 " enqueued", mId.string(),
Jianing Wei2d6bb3f2014-04-11 10:00:31 -0700865 (*(requestList.begin()))->mResultExtras.requestId);
Jianing Wei90e59c92014-03-12 18:29:36 -0700866 } else {
867 CLOGE("Cannot queue request. Impossible.");
868 return BAD_VALUE;
869 }
870
871 return res;
872}
873
Yifan Honga640c5a2017-04-12 16:30:31 -0700874// Only one processCaptureResult should be called at a time, so
875// the locks won't block. The locks are present here simply to enforce this.
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800876hardware::Return<void> Camera3Device::processCaptureResult(
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -0800877 const hardware::hidl_vec<
878 hardware::camera::device::V3_2::CaptureResult>& results) {
Yin-Chia Yeh657c1872017-07-18 18:09:57 -0700879 // Ideally we should grab mLock, but that can lead to deadlock, and
880 // it's not super important to get up to date value of mStatus for this
881 // warning print, hence skipping the lock here
882 if (mStatus == STATUS_ERROR) {
883 // Per API contract, HAL should act as closed after device error
884 // But mStatus can be set to error by framework as well, so just log
885 // a warning here.
886 ALOGW("%s: received capture result in error state.", __FUNCTION__);
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -0700887 }
Yifan Honga640c5a2017-04-12 16:30:31 -0700888
889 if (mProcessCaptureResultLock.tryLock() != OK) {
890 // This should never happen; it indicates a wrong client implementation
891 // that doesn't follow the contract. But, we can be tolerant here.
892 ALOGE("%s: callback overlapped! waiting 1s...",
893 __FUNCTION__);
894 if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
895 ALOGE("%s: cannot acquire lock in 1s, dropping results",
896 __FUNCTION__);
897 // really don't know what to do, so bail out.
898 return hardware::Void();
899 }
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -0800900 }
Yifan Honga640c5a2017-04-12 16:30:31 -0700901 for (const auto& result : results) {
902 processOneCaptureResultLocked(result);
903 }
904 mProcessCaptureResultLock.unlock();
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -0800905 return hardware::Void();
906}
907
Yifan Honga640c5a2017-04-12 16:30:31 -0700908void Camera3Device::processOneCaptureResultLocked(
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -0800909 const hardware::camera::device::V3_2::CaptureResult& result) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800910 camera3_capture_result r;
911 status_t res;
912 r.frame_number = result.frameNumber;
Yifan Honga640c5a2017-04-12 16:30:31 -0700913
914 hardware::camera::device::V3_2::CameraMetadata resultMetadata;
915 if (result.fmqResultSize > 0) {
916 resultMetadata.resize(result.fmqResultSize);
917 if (mResultMetadataQueue == nullptr) {
918 return; // logged in initialize()
919 }
920 if (!mResultMetadataQueue->read(resultMetadata.data(), result.fmqResultSize)) {
921 ALOGE("%s: Frame %d: Cannot read camera metadata from fmq, size = %" PRIu64,
922 __FUNCTION__, result.frameNumber, result.fmqResultSize);
923 return;
924 }
925 } else {
926 resultMetadata.setToExternal(const_cast<uint8_t *>(result.result.data()),
927 result.result.size());
928 }
929
930 if (resultMetadata.size() != 0) {
931 r.result = reinterpret_cast<const camera_metadata_t*>(resultMetadata.data());
932 size_t expected_metadata_size = resultMetadata.size();
Yin-Chia Yeh52778d42016-12-22 18:20:43 -0800933 if ((res = validate_camera_metadata_structure(r.result, &expected_metadata_size)) != OK) {
934 ALOGE("%s: Frame %d: Invalid camera metadata received by camera service from HAL: %s (%d)",
935 __FUNCTION__, result.frameNumber, strerror(-res), res);
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -0800936 return;
Yin-Chia Yeh52778d42016-12-22 18:20:43 -0800937 }
938 } else {
939 r.result = nullptr;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800940 }
941
942 std::vector<camera3_stream_buffer_t> outputBuffers(result.outputBuffers.size());
943 std::vector<buffer_handle_t> outputBufferHandles(result.outputBuffers.size());
944 for (size_t i = 0; i < result.outputBuffers.size(); i++) {
945 auto& bDst = outputBuffers[i];
946 const StreamBuffer &bSrc = result.outputBuffers[i];
947
948 ssize_t idx = mOutputStreams.indexOfKey(bSrc.streamId);
Emilian Peevbe3d40c2017-03-27 13:03:10 +0100949 if (idx == NAME_NOT_FOUND) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800950 ALOGE("%s: Frame %d: Buffer %zu: Invalid output stream id %d",
951 __FUNCTION__, result.frameNumber, i, bSrc.streamId);
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -0800952 return;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800953 }
954 bDst.stream = mOutputStreams.valueAt(idx)->asHalStream();
955
956 buffer_handle_t *buffer;
Yin-Chia Yehf4650602017-01-10 13:13:39 -0800957 res = mInterface->popInflightBuffer(result.frameNumber, bSrc.streamId, &buffer);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800958 if (res != OK) {
959 ALOGE("%s: Frame %d: Buffer %zu: No in-flight buffer for stream %d",
960 __FUNCTION__, result.frameNumber, i, bSrc.streamId);
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -0800961 return;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800962 }
963 bDst.buffer = buffer;
964 bDst.status = mapHidlBufferStatus(bSrc.status);
965 bDst.acquire_fence = -1;
966 if (bSrc.releaseFence == nullptr) {
967 bDst.release_fence = -1;
968 } else if (bSrc.releaseFence->numFds == 1) {
969 bDst.release_fence = dup(bSrc.releaseFence->data[0]);
970 } else {
971 ALOGE("%s: Frame %d: Invalid release fence for buffer %zu, fd count is %d, not 1",
972 __FUNCTION__, result.frameNumber, i, bSrc.releaseFence->numFds);
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -0800973 return;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800974 }
975 }
976 r.num_output_buffers = outputBuffers.size();
977 r.output_buffers = outputBuffers.data();
978
979 camera3_stream_buffer_t inputBuffer;
Yin-Chia Yeh52778d42016-12-22 18:20:43 -0800980 if (result.inputBuffer.streamId == -1) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800981 r.input_buffer = nullptr;
982 } else {
983 if (mInputStream->getId() != result.inputBuffer.streamId) {
984 ALOGE("%s: Frame %d: Invalid input stream id %d", __FUNCTION__,
985 result.frameNumber, result.inputBuffer.streamId);
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -0800986 return;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800987 }
988 inputBuffer.stream = mInputStream->asHalStream();
989 buffer_handle_t *buffer;
990 res = mInterface->popInflightBuffer(result.frameNumber, result.inputBuffer.streamId,
991 &buffer);
992 if (res != OK) {
993 ALOGE("%s: Frame %d: Input buffer: No in-flight buffer for stream %d",
994 __FUNCTION__, result.frameNumber, result.inputBuffer.streamId);
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -0800995 return;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -0800996 }
997 inputBuffer.buffer = buffer;
998 inputBuffer.status = mapHidlBufferStatus(result.inputBuffer.status);
999 inputBuffer.acquire_fence = -1;
1000 if (result.inputBuffer.releaseFence == nullptr) {
1001 inputBuffer.release_fence = -1;
1002 } else if (result.inputBuffer.releaseFence->numFds == 1) {
1003 inputBuffer.release_fence = dup(result.inputBuffer.releaseFence->data[0]);
1004 } else {
1005 ALOGE("%s: Frame %d: Invalid release fence for input buffer, fd count is %d, not 1",
1006 __FUNCTION__, result.frameNumber, result.inputBuffer.releaseFence->numFds);
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001007 return;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001008 }
1009 r.input_buffer = &inputBuffer;
1010 }
1011
1012 r.partial_result = result.partialResult;
1013
1014 processCaptureResult(&r);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001015}
1016
1017hardware::Return<void> Camera3Device::notify(
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001018 const hardware::hidl_vec<hardware::camera::device::V3_2::NotifyMsg>& msgs) {
Yin-Chia Yeh657c1872017-07-18 18:09:57 -07001019 // Ideally we should grab mLock, but that can lead to deadlock, and
1020 // it's not super important to get up to date value of mStatus for this
1021 // warning print, hence skipping the lock here
1022 if (mStatus == STATUS_ERROR) {
1023 // Per API contract, HAL should act as closed after device error
1024 // But mStatus can be set to error by framework as well, so just log
1025 // a warning here.
1026 ALOGW("%s: received notify message in error state.", __FUNCTION__);
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07001027 }
Yin-Chia Yeh657c1872017-07-18 18:09:57 -07001028
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001029 for (const auto& msg : msgs) {
1030 notify(msg);
1031 }
1032 return hardware::Void();
1033}
1034
1035void Camera3Device::notify(
1036 const hardware::camera::device::V3_2::NotifyMsg& msg) {
1037
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001038 camera3_notify_msg m;
1039 switch (msg.type) {
1040 case MsgType::ERROR:
1041 m.type = CAMERA3_MSG_ERROR;
1042 m.message.error.frame_number = msg.msg.error.frameNumber;
1043 if (msg.msg.error.errorStreamId >= 0) {
1044 ssize_t idx = mOutputStreams.indexOfKey(msg.msg.error.errorStreamId);
Emilian Peevbe3d40c2017-03-27 13:03:10 +01001045 if (idx == NAME_NOT_FOUND) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001046 ALOGE("%s: Frame %d: Invalid error stream id %d",
1047 __FUNCTION__, m.message.error.frame_number, msg.msg.error.errorStreamId);
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08001048 return;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001049 }
1050 m.message.error.error_stream = mOutputStreams.valueAt(idx)->asHalStream();
1051 } else {
1052 m.message.error.error_stream = nullptr;
1053 }
1054 switch (msg.msg.error.errorCode) {
1055 case ErrorCode::ERROR_DEVICE:
1056 m.message.error.error_code = CAMERA3_MSG_ERROR_DEVICE;
1057 break;
1058 case ErrorCode::ERROR_REQUEST:
1059 m.message.error.error_code = CAMERA3_MSG_ERROR_REQUEST;
1060 break;
1061 case ErrorCode::ERROR_RESULT:
1062 m.message.error.error_code = CAMERA3_MSG_ERROR_RESULT;
1063 break;
1064 case ErrorCode::ERROR_BUFFER:
1065 m.message.error.error_code = CAMERA3_MSG_ERROR_BUFFER;
1066 break;
1067 }
1068 break;
1069 case MsgType::SHUTTER:
1070 m.type = CAMERA3_MSG_SHUTTER;
1071 m.message.shutter.frame_number = msg.msg.shutter.frameNumber;
1072 m.message.shutter.timestamp = msg.msg.shutter.timestamp;
1073 break;
1074 }
1075 notify(&m);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001076}
1077
Jianing Weicb0652e2014-03-12 18:29:36 -07001078status_t Camera3Device::captureList(const List<const CameraMetadata> &requests,
Shuzhen Wang0129d522016-10-30 22:43:41 -07001079 const std::list<const SurfaceMap> &surfaceMaps,
Jianing Weicb0652e2014-03-12 18:29:36 -07001080 int64_t *lastFrameNumber) {
Jianing Wei90e59c92014-03-12 18:29:36 -07001081 ATRACE_CALL();
1082
Shuzhen Wang0129d522016-10-30 22:43:41 -07001083 return submitRequestsHelper(requests, surfaceMaps, /*repeating*/false, lastFrameNumber);
Jianing Wei90e59c92014-03-12 18:29:36 -07001084}
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001085
Jianing Weicb0652e2014-03-12 18:29:36 -07001086status_t Camera3Device::setStreamingRequest(const CameraMetadata &request,
1087 int64_t* /*lastFrameNumber*/) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001088 ATRACE_CALL();
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001089
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07001090 List<const CameraMetadata> requests;
Shuzhen Wang0129d522016-10-30 22:43:41 -07001091 std::list<const SurfaceMap> surfaceMaps;
1092 convertToRequestList(requests, surfaceMaps, request);
1093
1094 return setStreamingRequestList(requests, /*surfaceMap*/surfaceMaps,
1095 /*lastFrameNumber*/NULL);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001096}
1097
Jianing Weicb0652e2014-03-12 18:29:36 -07001098status_t Camera3Device::setStreamingRequestList(const List<const CameraMetadata> &requests,
Shuzhen Wang0129d522016-10-30 22:43:41 -07001099 const std::list<const SurfaceMap> &surfaceMaps,
Jianing Weicb0652e2014-03-12 18:29:36 -07001100 int64_t *lastFrameNumber) {
Jianing Wei90e59c92014-03-12 18:29:36 -07001101 ATRACE_CALL();
1102
Shuzhen Wang0129d522016-10-30 22:43:41 -07001103 return submitRequestsHelper(requests, surfaceMaps, /*repeating*/true, lastFrameNumber);
Jianing Wei90e59c92014-03-12 18:29:36 -07001104}
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001105
1106sp<Camera3Device::CaptureRequest> Camera3Device::setUpRequestLocked(
Shuzhen Wang0129d522016-10-30 22:43:41 -07001107 const CameraMetadata &request, const SurfaceMap &surfaceMap) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001108 status_t res;
1109
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001110 if (mStatus == STATUS_UNCONFIGURED || mNeedConfig) {
Eino-Ville Talvalae7091aa2017-03-07 15:23:06 -08001111 // This point should only be reached via API1 (API2 must explicitly call configureStreams)
1112 // so unilaterally select normal operating mode.
Emilian Peevac3ce6c2017-12-12 15:27:02 +00001113 res = filterParamsAndConfigureLocked(request, CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE);
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07001114 // Stream configuration failed. Client might try other configuraitons.
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001115 if (res != OK) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07001116 CLOGE("Can't set up streams: %s (%d)", strerror(-res), res);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001117 return NULL;
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07001118 } else if (mStatus == STATUS_UNCONFIGURED) {
1119 // Stream configuration successfully configure to empty stream configuration.
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001120 CLOGE("No streams configured");
1121 return NULL;
1122 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001123 }
1124
Shuzhen Wang0129d522016-10-30 22:43:41 -07001125 sp<CaptureRequest> newRequest = createCaptureRequest(request, surfaceMap);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001126 return newRequest;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001127}
1128
Jianing Weicb0652e2014-03-12 18:29:36 -07001129status_t Camera3Device::clearStreamingRequest(int64_t *lastFrameNumber) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001130 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001131 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001132 Mutex::Autolock l(mLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001133
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001134 switch (mStatus) {
1135 case STATUS_ERROR:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001136 CLOGE("Device has encountered a serious error");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001137 return INVALID_OPERATION;
1138 case STATUS_UNINITIALIZED:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001139 CLOGE("Device not initialized");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001140 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001141 case STATUS_UNCONFIGURED:
1142 case STATUS_CONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001143 case STATUS_ACTIVE:
1144 // OK
1145 break;
1146 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001147 SET_ERR_L("Unexpected status: %d", mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001148 return INVALID_OPERATION;
1149 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001150 ALOGV("Camera %s: Clearing repeating request", mId.string());
Jianing Weicb0652e2014-03-12 18:29:36 -07001151
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07001152 return mRequestThread->clearRepeatingRequests(lastFrameNumber);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001153}
1154
1155status_t Camera3Device::waitUntilRequestReceived(int32_t requestId, nsecs_t timeout) {
1156 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001157 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001158
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001159 return mRequestThread->waitUntilRequestProcessed(requestId, timeout);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001160}
1161
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001162status_t Camera3Device::createInputStream(
1163 uint32_t width, uint32_t height, int format, int *id) {
1164 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001165 Mutex::Autolock il(mInterfaceLock);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001166 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001167 Mutex::Autolock l(mLock);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001168 ALOGV("Camera %s: Creating new input stream %d: %d x %d, format %d",
1169 mId.string(), mNextStreamId, width, height, format);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001170
1171 status_t res;
1172 bool wasActive = false;
1173
1174 switch (mStatus) {
1175 case STATUS_ERROR:
1176 ALOGE("%s: Device has encountered a serious error", __FUNCTION__);
1177 return INVALID_OPERATION;
1178 case STATUS_UNINITIALIZED:
1179 ALOGE("%s: Device not initialized", __FUNCTION__);
1180 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001181 case STATUS_UNCONFIGURED:
1182 case STATUS_CONFIGURED:
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001183 // OK
1184 break;
1185 case STATUS_ACTIVE:
1186 ALOGV("%s: Stopping activity to reconfigure streams", __FUNCTION__);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001187 res = internalPauseAndWaitLocked(maxExpectedDuration);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001188 if (res != OK) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001189 SET_ERR_L("Can't pause captures to reconfigure streams!");
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001190 return res;
1191 }
1192 wasActive = true;
1193 break;
1194 default:
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001195 SET_ERR_L("%s: Unexpected status: %d", mStatus);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001196 return INVALID_OPERATION;
1197 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001198 assert(mStatus != STATUS_ACTIVE);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001199
1200 if (mInputStream != 0) {
1201 ALOGE("%s: Cannot create more than 1 input stream", __FUNCTION__);
1202 return INVALID_OPERATION;
1203 }
1204
1205 sp<Camera3InputStream> newStream = new Camera3InputStream(mNextStreamId,
1206 width, height, format);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001207 newStream->setStatusTracker(mStatusTracker);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001208
1209 mInputStream = newStream;
1210
1211 *id = mNextStreamId++;
1212
1213 // Continue captures if active at start
1214 if (wasActive) {
1215 ALOGV("%s: Restarting activity to reconfigure streams", __FUNCTION__);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001216 // Reuse current operating mode and session parameters for new stream config
1217 res = configureStreamsLocked(mOperatingMode, mSessionParams);
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001218 if (res != OK) {
1219 ALOGE("%s: Can't reconfigure device for new stream %d: %s (%d)",
1220 __FUNCTION__, mNextStreamId, strerror(-res), res);
1221 return res;
1222 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001223 internalResumeLocked();
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001224 }
1225
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001226 ALOGV("Camera %s: Created input stream", mId.string());
Igor Murashkin5a269fa2013-04-15 14:59:22 -07001227 return OK;
1228}
1229
Eino-Ville Talvala727d1722015-06-09 13:44:19 -07001230status_t Camera3Device::createStream(sp<Surface> consumer,
Shuzhen Wang0129d522016-10-30 22:43:41 -07001231 uint32_t width, uint32_t height, int format,
1232 android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001233 const String8& physicalCameraId,
Emilian Peev40ead602017-09-26 15:46:36 +01001234 std::vector<int> *surfaceIds, int streamSetId, bool isShared, uint64_t consumerUsage) {
Shuzhen Wang0129d522016-10-30 22:43:41 -07001235 ATRACE_CALL();
1236
1237 if (consumer == nullptr) {
1238 ALOGE("%s: consumer must not be null", __FUNCTION__);
1239 return BAD_VALUE;
1240 }
1241
1242 std::vector<sp<Surface>> consumers;
1243 consumers.push_back(consumer);
1244
1245 return createStream(consumers, /*hasDeferredConsumer*/ false, width, height,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001246 format, dataSpace, rotation, id, physicalCameraId, surfaceIds, streamSetId,
1247 isShared, consumerUsage);
Shuzhen Wang0129d522016-10-30 22:43:41 -07001248}
1249
1250status_t Camera3Device::createStream(const std::vector<sp<Surface>>& consumers,
1251 bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
1252 android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001253 const String8& physicalCameraId,
Emilian Peev40ead602017-09-26 15:46:36 +01001254 std::vector<int> *surfaceIds, int streamSetId, bool isShared, uint64_t consumerUsage) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001255 ATRACE_CALL();
Emilian Peev40ead602017-09-26 15:46:36 +01001256
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001257 Mutex::Autolock il(mInterfaceLock);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001258 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001259 Mutex::Autolock l(mLock);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001260 ALOGV("Camera %s: Creating new stream %d: %d x %d, format %d, dataspace %d rotation %d"
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001261 " consumer usage %" PRIu64 ", isShared %d, physicalCameraId %s", mId.string(),
1262 mNextStreamId, width, height, format, dataSpace, rotation, consumerUsage, isShared,
1263 physicalCameraId.string());
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001264
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001265 status_t res;
1266 bool wasActive = false;
1267
1268 switch (mStatus) {
1269 case STATUS_ERROR:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001270 CLOGE("Device has encountered a serious error");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001271 return INVALID_OPERATION;
1272 case STATUS_UNINITIALIZED:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001273 CLOGE("Device not initialized");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001274 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001275 case STATUS_UNCONFIGURED:
1276 case STATUS_CONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001277 // OK
1278 break;
1279 case STATUS_ACTIVE:
1280 ALOGV("%s: Stopping activity to reconfigure streams", __FUNCTION__);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001281 res = internalPauseAndWaitLocked(maxExpectedDuration);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001282 if (res != OK) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001283 SET_ERR_L("Can't pause captures to reconfigure streams!");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001284 return res;
1285 }
1286 wasActive = true;
1287 break;
1288 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001289 SET_ERR_L("Unexpected status: %d", mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001290 return INVALID_OPERATION;
1291 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001292 assert(mStatus != STATUS_ACTIVE);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001293
1294 sp<Camera3OutputStream> newStream;
Zhijun He5d677d12016-05-29 16:52:39 -07001295
Shuzhen Wang0129d522016-10-30 22:43:41 -07001296 if (consumers.size() == 0 && !hasDeferredConsumer) {
1297 ALOGE("%s: Number of consumers cannot be smaller than 1", __FUNCTION__);
1298 return BAD_VALUE;
1299 }
Zhijun He5d677d12016-05-29 16:52:39 -07001300
Shuzhen Wang0129d522016-10-30 22:43:41 -07001301 if (hasDeferredConsumer && format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
Zhijun He5d677d12016-05-29 16:52:39 -07001302 ALOGE("Deferred consumer stream creation only support IMPLEMENTATION_DEFINED format");
1303 return BAD_VALUE;
1304 }
1305
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001306 if (format == HAL_PIXEL_FORMAT_BLOB) {
Eino-Ville Talvala95a1d0f2015-08-11 15:08:53 -07001307 ssize_t blobBufferSize;
1308 if (dataSpace != HAL_DATASPACE_DEPTH) {
1309 blobBufferSize = getJpegBufferSize(width, height);
1310 if (blobBufferSize <= 0) {
1311 SET_ERR_L("Invalid jpeg buffer size %zd", blobBufferSize);
1312 return BAD_VALUE;
1313 }
1314 } else {
1315 blobBufferSize = getPointCloudBufferSize();
1316 if (blobBufferSize <= 0) {
1317 SET_ERR_L("Invalid point cloud buffer size %zd", blobBufferSize);
1318 return BAD_VALUE;
1319 }
Zhijun Hef7da0962014-04-24 13:27:56 -07001320 }
Shuzhen Wang0129d522016-10-30 22:43:41 -07001321 newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
Shuzhen Wangc28dccc2016-02-11 23:48:46 -08001322 width, height, blobBufferSize, format, dataSpace, rotation,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001323 mTimestampOffset, physicalCameraId, streamSetId);
Yin-Chia Yehe9154ce2015-12-07 14:38:04 -08001324 } else if (format == HAL_PIXEL_FORMAT_RAW_OPAQUE) {
1325 ssize_t rawOpaqueBufferSize = getRawOpaqueBufferSize(width, height);
1326 if (rawOpaqueBufferSize <= 0) {
1327 SET_ERR_L("Invalid RAW opaque buffer size %zd", rawOpaqueBufferSize);
1328 return BAD_VALUE;
1329 }
Shuzhen Wang0129d522016-10-30 22:43:41 -07001330 newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
Shuzhen Wangc28dccc2016-02-11 23:48:46 -08001331 width, height, rawOpaqueBufferSize, format, dataSpace, rotation,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001332 mTimestampOffset, physicalCameraId, streamSetId);
Shuzhen Wang758c2152017-01-10 18:26:18 -08001333 } else if (isShared) {
1334 newStream = new Camera3SharedOutputStream(mNextStreamId, consumers,
1335 width, height, format, consumerUsage, dataSpace, rotation,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001336 mTimestampOffset, physicalCameraId, streamSetId);
Shuzhen Wang0129d522016-10-30 22:43:41 -07001337 } else if (consumers.size() == 0 && hasDeferredConsumer) {
Zhijun He5d677d12016-05-29 16:52:39 -07001338 newStream = new Camera3OutputStream(mNextStreamId,
1339 width, height, format, consumerUsage, dataSpace, rotation,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001340 mTimestampOffset, physicalCameraId, streamSetId);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001341 } else {
Shuzhen Wang0129d522016-10-30 22:43:41 -07001342 newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
Shuzhen Wangc28dccc2016-02-11 23:48:46 -08001343 width, height, format, dataSpace, rotation,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08001344 mTimestampOffset, physicalCameraId, streamSetId);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001345 }
Emilian Peev40ead602017-09-26 15:46:36 +01001346
1347 size_t consumerCount = consumers.size();
1348 for (size_t i = 0; i < consumerCount; i++) {
1349 int id = newStream->getSurfaceId(consumers[i]);
1350 if (id < 0) {
1351 SET_ERR_L("Invalid surface id");
1352 return BAD_VALUE;
1353 }
1354 if (surfaceIds != nullptr) {
1355 surfaceIds->push_back(id);
1356 }
1357 }
1358
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001359 newStream->setStatusTracker(mStatusTracker);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001360
Emilian Peev08dd2452017-04-06 16:55:14 +01001361 newStream->setBufferManager(mBufferManager);
Zhijun He125684a2015-12-26 15:07:30 -08001362
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001363 res = mOutputStreams.add(mNextStreamId, newStream);
1364 if (res < 0) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001365 SET_ERR_L("Can't add new stream to set: %s (%d)", strerror(-res), res);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001366 return res;
1367 }
1368
1369 *id = mNextStreamId++;
Eino-Ville Talvalaea26c772013-06-11 16:04:06 -07001370 mNeedConfig = true;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001371
1372 // Continue captures if active at start
1373 if (wasActive) {
1374 ALOGV("%s: Restarting activity to reconfigure streams", __FUNCTION__);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001375 // Reuse current operating mode and session parameters for new stream config
1376 res = configureStreamsLocked(mOperatingMode, mSessionParams);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001377 if (res != OK) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001378 CLOGE("Can't reconfigure device for new stream %d: %s (%d)",
1379 mNextStreamId, strerror(-res), res);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001380 return res;
1381 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001382 internalResumeLocked();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001383 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001384 ALOGV("Camera %s: Created new stream", mId.string());
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001385 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001386}
1387
Emilian Peev710c1422017-08-30 11:19:38 +01001388status_t Camera3Device::getStreamInfo(int id, StreamInfo *streamInfo) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001389 ATRACE_CALL();
Emilian Peev710c1422017-08-30 11:19:38 +01001390 if (nullptr == streamInfo) {
1391 return BAD_VALUE;
1392 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001393 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001394 Mutex::Autolock l(mLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001395
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001396 switch (mStatus) {
1397 case STATUS_ERROR:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001398 CLOGE("Device has encountered a serious error");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001399 return INVALID_OPERATION;
1400 case STATUS_UNINITIALIZED:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001401 CLOGE("Device not initialized!");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001402 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001403 case STATUS_UNCONFIGURED:
1404 case STATUS_CONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001405 case STATUS_ACTIVE:
1406 // OK
1407 break;
1408 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001409 SET_ERR_L("Unexpected status: %d", mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001410 return INVALID_OPERATION;
1411 }
1412
1413 ssize_t idx = mOutputStreams.indexOfKey(id);
1414 if (idx == NAME_NOT_FOUND) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001415 CLOGE("Stream %d is unknown", id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001416 return idx;
1417 }
1418
Emilian Peev710c1422017-08-30 11:19:38 +01001419 streamInfo->width = mOutputStreams[idx]->getWidth();
1420 streamInfo->height = mOutputStreams[idx]->getHeight();
1421 streamInfo->format = mOutputStreams[idx]->getFormat();
1422 streamInfo->dataSpace = mOutputStreams[idx]->getDataSpace();
1423 streamInfo->formatOverridden = mOutputStreams[idx]->isFormatOverridden();
1424 streamInfo->originalFormat = mOutputStreams[idx]->getOriginalFormat();
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07001425 streamInfo->dataSpaceOverridden = mOutputStreams[idx]->isDataSpaceOverridden();
1426 streamInfo->originalDataSpace = mOutputStreams[idx]->getOriginalDataSpace();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001427 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001428}
1429
1430status_t Camera3Device::setStreamTransform(int id,
1431 int transform) {
1432 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001433 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001434 Mutex::Autolock l(mLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001435
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001436 switch (mStatus) {
1437 case STATUS_ERROR:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001438 CLOGE("Device has encountered a serious error");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001439 return INVALID_OPERATION;
1440 case STATUS_UNINITIALIZED:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001441 CLOGE("Device not initialized");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001442 return INVALID_OPERATION;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001443 case STATUS_UNCONFIGURED:
1444 case STATUS_CONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001445 case STATUS_ACTIVE:
1446 // OK
1447 break;
1448 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001449 SET_ERR_L("Unexpected status: %d", mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001450 return INVALID_OPERATION;
1451 }
1452
1453 ssize_t idx = mOutputStreams.indexOfKey(id);
1454 if (idx == NAME_NOT_FOUND) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001455 CLOGE("Stream %d does not exist",
1456 id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001457 return BAD_VALUE;
1458 }
1459
1460 return mOutputStreams.editValueAt(idx)->setTransform(transform);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001461}
1462
1463status_t Camera3Device::deleteStream(int id) {
1464 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001465 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001466 Mutex::Autolock l(mLock);
1467 status_t res;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001468
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001469 ALOGV("%s: Camera %s: Deleting stream %d", __FUNCTION__, mId.string(), id);
Igor Murashkine2172be2013-05-28 15:31:39 -07001470
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001471 // CameraDevice semantics require device to already be idle before
1472 // deleteStream is called, unlike for createStream.
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001473 if (mStatus == STATUS_ACTIVE) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001474 ALOGV("%s: Camera %s: Device not idle", __FUNCTION__, mId.string());
Igor Murashkin52827132013-05-13 14:53:44 -07001475 return -EBUSY;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001476 }
1477
Yin-Chia Yeh5090c732017-07-20 16:05:29 -07001478 if (mStatus == STATUS_ERROR) {
1479 ALOGW("%s: Camera %s: deleteStream not allowed in ERROR state",
1480 __FUNCTION__, mId.string());
1481 return -EBUSY;
1482 }
1483
Igor Murashkin2fba5842013-04-22 14:03:54 -07001484 sp<Camera3StreamInterface> deletedStream;
Zhijun He5f446352014-01-22 09:49:33 -08001485 ssize_t outputStreamIdx = mOutputStreams.indexOfKey(id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001486 if (mInputStream != NULL && id == mInputStream->getId()) {
1487 deletedStream = mInputStream;
1488 mInputStream.clear();
1489 } else {
Zhijun He5f446352014-01-22 09:49:33 -08001490 if (outputStreamIdx == NAME_NOT_FOUND) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001491 CLOGE("Stream %d does not exist", id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001492 return BAD_VALUE;
1493 }
Zhijun He5f446352014-01-22 09:49:33 -08001494 }
1495
1496 // Delete output stream or the output part of a bi-directional stream.
1497 if (outputStreamIdx != NAME_NOT_FOUND) {
1498 deletedStream = mOutputStreams.editValueAt(outputStreamIdx);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001499 mOutputStreams.removeItem(id);
1500 }
1501
1502 // Free up the stream endpoint so that it can be used by some other stream
1503 res = deletedStream->disconnect();
1504 if (res != OK) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001505 SET_ERR_L("Can't disconnect deleted stream %d", id);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001506 // fall through since we want to still list the stream as deleted.
1507 }
1508 mDeletedStreams.add(deletedStream);
Eino-Ville Talvalaea26c772013-06-11 16:04:06 -07001509 mNeedConfig = true;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001510
1511 return res;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001512}
1513
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001514status_t Camera3Device::configureStreams(const CameraMetadata& sessionParams, int operatingMode) {
Igor Murashkine2d167e2014-08-19 16:19:59 -07001515 ATRACE_CALL();
1516 ALOGV("%s: E", __FUNCTION__);
1517
1518 Mutex::Autolock il(mInterfaceLock);
1519 Mutex::Autolock l(mLock);
Chien-Yu Chen17338fc2015-06-18 16:30:12 -07001520
Emilian Peevac3ce6c2017-12-12 15:27:02 +00001521 return filterParamsAndConfigureLocked(sessionParams, operatingMode);
1522}
1523
1524status_t Camera3Device::filterParamsAndConfigureLocked(const CameraMetadata& sessionParams,
1525 int operatingMode) {
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001526 //Filter out any incoming session parameters
1527 const CameraMetadata params(sessionParams);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001528 camera_metadata_entry_t availableSessionKeys = mDeviceInfo.find(
1529 ANDROID_REQUEST_AVAILABLE_SESSION_KEYS);
Emilian Peevac3ce6c2017-12-12 15:27:02 +00001530 CameraMetadata filteredParams(availableSessionKeys.count);
1531 camera_metadata_t *meta = const_cast<camera_metadata_t *>(
1532 filteredParams.getAndLock());
1533 set_camera_metadata_vendor_id(meta, mVendorTagId);
1534 filteredParams.unlock(meta);
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01001535 if (availableSessionKeys.count > 0) {
1536 for (size_t i = 0; i < availableSessionKeys.count; i++) {
1537 camera_metadata_ro_entry entry = params.find(
1538 availableSessionKeys.data.i32[i]);
1539 if (entry.count > 0) {
1540 filteredParams.update(entry);
1541 }
1542 }
1543 }
1544
1545 return configureStreamsLocked(operatingMode, filteredParams);
Igor Murashkine2d167e2014-08-19 16:19:59 -07001546}
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001547
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -07001548status_t Camera3Device::getInputBufferProducer(
1549 sp<IGraphicBufferProducer> *producer) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07001550 ATRACE_CALL();
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -07001551 Mutex::Autolock il(mInterfaceLock);
1552 Mutex::Autolock l(mLock);
1553
1554 if (producer == NULL) {
1555 return BAD_VALUE;
1556 } else if (mInputStream == NULL) {
1557 return INVALID_OPERATION;
1558 }
1559
1560 return mInputStream->getInputBufferProducer(producer);
1561}
1562
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001563status_t Camera3Device::createDefaultRequest(int templateId,
1564 CameraMetadata *request) {
1565 ATRACE_CALL();
Alex Rayfe7e0c62013-05-30 00:12:13 -07001566 ALOGV("%s: for template %d", __FUNCTION__, templateId);
Chien-Yu Chen9cd14022016-03-09 12:21:01 -08001567
1568 if (templateId <= 0 || templateId >= CAMERA3_TEMPLATE_COUNT) {
1569 android_errorWriteWithInfoLog(CameraService::SN_EVENT_LOG_ID, "26866110",
1570 IPCThreadState::self()->getCallingUid(), nullptr, 0);
1571 return BAD_VALUE;
1572 }
1573
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001574 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001575
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001576 {
1577 Mutex::Autolock l(mLock);
1578 switch (mStatus) {
1579 case STATUS_ERROR:
1580 CLOGE("Device has encountered a serious error");
1581 return INVALID_OPERATION;
1582 case STATUS_UNINITIALIZED:
1583 CLOGE("Device is not initialized!");
1584 return INVALID_OPERATION;
1585 case STATUS_UNCONFIGURED:
1586 case STATUS_CONFIGURED:
1587 case STATUS_ACTIVE:
1588 // OK
1589 break;
1590 default:
1591 SET_ERR_L("Unexpected status: %d", mStatus);
1592 return INVALID_OPERATION;
1593 }
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001594
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001595 if (!mRequestTemplateCache[templateId].isEmpty()) {
1596 *request = mRequestTemplateCache[templateId];
1597 return OK;
1598 }
Zhijun Hea1530f12014-09-14 12:44:20 -07001599 }
1600
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001601 camera_metadata_t *rawRequest;
1602 status_t res = mInterface->constructDefaultRequestSettings(
1603 (camera3_request_template_t) templateId, &rawRequest);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001604
1605 {
1606 Mutex::Autolock l(mLock);
1607 if (res == BAD_VALUE) {
1608 ALOGI("%s: template %d is not supported on this camera device",
1609 __FUNCTION__, templateId);
1610 return res;
1611 } else if (res != OK) {
1612 CLOGE("Unable to construct request template %d: %s (%d)",
1613 templateId, strerror(-res), res);
1614 return res;
1615 }
1616
1617 set_camera_metadata_vendor_id(rawRequest, mVendorTagId);
1618 mRequestTemplateCache[templateId].acquire(rawRequest);
1619
1620 *request = mRequestTemplateCache[templateId];
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001621 }
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001622 return OK;
1623}
1624
1625status_t Camera3Device::waitUntilDrained() {
1626 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001627 Mutex::Autolock il(mInterfaceLock);
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001628 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001629 Mutex::Autolock l(mLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001630
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001631 return waitUntilDrainedLocked(maxExpectedDuration);
Zhijun He69a37482014-03-23 18:44:49 -07001632}
1633
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001634status_t Camera3Device::waitUntilDrainedLocked(nsecs_t maxExpectedDuration) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001635 switch (mStatus) {
1636 case STATUS_UNINITIALIZED:
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001637 case STATUS_UNCONFIGURED:
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001638 ALOGV("%s: Already idle", __FUNCTION__);
1639 return OK;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001640 case STATUS_CONFIGURED:
1641 // To avoid race conditions, check with tracker to be sure
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001642 case STATUS_ERROR:
1643 case STATUS_ACTIVE:
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001644 // Need to verify shut down
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001645 break;
1646 default:
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07001647 SET_ERR_L("Unexpected status: %d",mStatus);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001648 return INVALID_OPERATION;
1649 }
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07001650 ALOGV("%s: Camera %s: Waiting until idle (%" PRIi64 "ns)", __FUNCTION__, mId.string(),
1651 maxExpectedDuration);
1652 status_t res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration);
Eino-Ville Talvala9c8a0912014-09-14 14:52:19 -07001653 if (res != OK) {
1654 SET_ERR_L("Error waiting for HAL to drain: %s (%d)", strerror(-res),
1655 res);
1656 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001657 return res;
1658}
1659
Ruben Brunk183f0562015-08-12 12:55:02 -07001660
1661void Camera3Device::internalUpdateStatusLocked(Status status) {
1662 mStatus = status;
1663 mRecentStatusUpdates.add(mStatus);
1664 mStatusChanged.broadcast();
1665}
1666
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001667// Pause to reconfigure
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07001668status_t Camera3Device::internalPauseAndWaitLocked(nsecs_t maxExpectedDuration) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001669 mRequestThread->setPaused(true);
1670 mPauseStateNotify = true;
1671
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07001672 ALOGV("%s: Camera %s: Internal wait until idle (% " PRIi64 " ns)", __FUNCTION__, mId.string(),
1673 maxExpectedDuration);
1674 status_t res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001675 if (res != OK) {
1676 SET_ERR_L("Can't idle device in %f seconds!",
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07001677 maxExpectedDuration/1e9);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001678 }
1679
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001680 return res;
1681}
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001682
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001683// Resume after internalPauseAndWaitLocked
1684status_t Camera3Device::internalResumeLocked() {
1685 status_t res;
1686
1687 mRequestThread->setPaused(false);
1688
1689 res = waitUntilStateThenRelock(/*active*/ true, kActiveTimeout);
1690 if (res != OK) {
1691 SET_ERR_L("Can't transition to active in %f seconds!",
1692 kActiveTimeout/1e9);
1693 }
1694 mPauseStateNotify = false;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001695 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001696}
1697
Ruben Brunk183f0562015-08-12 12:55:02 -07001698status_t Camera3Device::waitUntilStateThenRelock(bool active, nsecs_t timeout) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001699 status_t res = OK;
Ruben Brunk183f0562015-08-12 12:55:02 -07001700
1701 size_t startIndex = 0;
1702 if (mStatusWaiters == 0) {
1703 // Clear the list of recent statuses if there are no existing threads waiting on updates to
1704 // this status list
1705 mRecentStatusUpdates.clear();
1706 } else {
1707 // If other threads are waiting on updates to this status list, set the position of the
1708 // first element that this list will check rather than clearing the list.
1709 startIndex = mRecentStatusUpdates.size();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001710 }
1711
Ruben Brunk183f0562015-08-12 12:55:02 -07001712 mStatusWaiters++;
1713
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001714 bool stateSeen = false;
1715 do {
Ruben Brunk183f0562015-08-12 12:55:02 -07001716 if (active == (mStatus == STATUS_ACTIVE)) {
1717 // Desired state is current
1718 break;
1719 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001720
1721 res = mStatusChanged.waitRelative(mLock, timeout);
1722 if (res != OK) break;
1723
Ruben Brunk183f0562015-08-12 12:55:02 -07001724 // This is impossible, but if not, could result in subtle deadlocks and invalid state
1725 // transitions.
1726 LOG_ALWAYS_FATAL_IF(startIndex > mRecentStatusUpdates.size(),
1727 "%s: Skipping status updates in Camera3Device, may result in deadlock.",
1728 __FUNCTION__);
1729
1730 // Encountered desired state since we began waiting
1731 for (size_t i = startIndex; i < mRecentStatusUpdates.size(); i++) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001732 if (active == (mRecentStatusUpdates[i] == STATUS_ACTIVE) ) {
1733 stateSeen = true;
1734 break;
1735 }
1736 }
1737 } while (!stateSeen);
1738
Ruben Brunk183f0562015-08-12 12:55:02 -07001739 mStatusWaiters--;
1740
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001741 return res;
1742}
1743
1744
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07001745status_t Camera3Device::setNotifyCallback(wp<NotificationListener> listener) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001746 ATRACE_CALL();
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001747 Mutex::Autolock l(mOutputLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001748
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001749 if (listener != NULL && mListener != NULL) {
1750 ALOGW("%s: Replacing old callback listener", __FUNCTION__);
1751 }
1752 mListener = listener;
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07001753 mRequestThread->setNotificationListener(listener);
1754 mPreparerThread->setNotificationListener(listener);
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001755
1756 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001757}
1758
Eino-Ville Talvala46910bd2013-07-18 19:15:17 -07001759bool Camera3Device::willNotify3A() {
1760 return false;
1761}
1762
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001763status_t Camera3Device::waitForNextFrame(nsecs_t timeout) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07001764 ATRACE_CALL();
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001765 status_t res;
1766 Mutex::Autolock l(mOutputLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001767
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001768 while (mResultQueue.empty()) {
1769 res = mResultSignal.waitRelative(mOutputLock, timeout);
1770 if (res == TIMED_OUT) {
1771 return res;
1772 } else if (res != OK) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001773 ALOGW("%s: Camera %s: No frame in %" PRId64 " ns: %s (%d)",
1774 __FUNCTION__, mId.string(), timeout, strerror(-res), res);
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001775 return res;
1776 }
1777 }
1778 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001779}
1780
Jianing Weicb0652e2014-03-12 18:29:36 -07001781status_t Camera3Device::getNextResult(CaptureResult *frame) {
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001782 ATRACE_CALL();
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001783 Mutex::Autolock l(mOutputLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001784
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001785 if (mResultQueue.empty()) {
1786 return NOT_ENOUGH_DATA;
1787 }
1788
Jianing Weicb0652e2014-03-12 18:29:36 -07001789 if (frame == NULL) {
1790 ALOGE("%s: argument cannot be NULL", __FUNCTION__);
1791 return BAD_VALUE;
1792 }
1793
1794 CaptureResult &result = *(mResultQueue.begin());
1795 frame->mResultExtras = result.mResultExtras;
1796 frame->mMetadata.acquire(result.mMetadata);
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07001797 mResultQueue.erase(mResultQueue.begin());
1798
1799 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001800}
1801
1802status_t Camera3Device::triggerAutofocus(uint32_t id) {
1803 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001804 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001805
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001806 ALOGV("%s: Triggering autofocus, id %d", __FUNCTION__, id);
1807 // Mix-in this trigger into the next request and only the next request.
1808 RequestTrigger trigger[] = {
1809 {
1810 ANDROID_CONTROL_AF_TRIGGER,
1811 ANDROID_CONTROL_AF_TRIGGER_START
1812 },
1813 {
1814 ANDROID_CONTROL_AF_TRIGGER_ID,
1815 static_cast<int32_t>(id)
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07001816 }
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001817 };
1818
1819 return mRequestThread->queueTrigger(trigger,
1820 sizeof(trigger)/sizeof(trigger[0]));
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001821}
1822
1823status_t Camera3Device::triggerCancelAutofocus(uint32_t id) {
1824 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001825 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001826
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001827 ALOGV("%s: Triggering cancel autofocus, id %d", __FUNCTION__, id);
1828 // Mix-in this trigger into the next request and only the next request.
1829 RequestTrigger trigger[] = {
1830 {
1831 ANDROID_CONTROL_AF_TRIGGER,
1832 ANDROID_CONTROL_AF_TRIGGER_CANCEL
1833 },
1834 {
1835 ANDROID_CONTROL_AF_TRIGGER_ID,
1836 static_cast<int32_t>(id)
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07001837 }
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001838 };
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001839
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001840 return mRequestThread->queueTrigger(trigger,
1841 sizeof(trigger)/sizeof(trigger[0]));
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001842}
1843
1844status_t Camera3Device::triggerPrecaptureMetering(uint32_t id) {
1845 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001846 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001847
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001848 ALOGV("%s: Triggering precapture metering, id %d", __FUNCTION__, id);
1849 // Mix-in this trigger into the next request and only the next request.
1850 RequestTrigger trigger[] = {
1851 {
1852 ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
1853 ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_START
1854 },
1855 {
1856 ANDROID_CONTROL_AE_PRECAPTURE_ID,
1857 static_cast<int32_t>(id)
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07001858 }
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001859 };
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001860
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07001861 return mRequestThread->queueTrigger(trigger,
1862 sizeof(trigger)/sizeof(trigger[0]));
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08001863}
1864
Jianing Weicb0652e2014-03-12 18:29:36 -07001865status_t Camera3Device::flush(int64_t *frameNumber) {
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07001866 ATRACE_CALL();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001867 ALOGV("%s: Camera %s: Flushing all requests", __FUNCTION__, mId.string());
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001868 Mutex::Autolock il(mInterfaceLock);
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07001869
Zhijun He7ef20392014-04-21 16:04:17 -07001870 {
1871 Mutex::Autolock l(mLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07001872 mRequestThread->clear(/*out*/frameNumber);
Zhijun He7ef20392014-04-21 16:04:17 -07001873 }
1874
Emilian Peev08dd2452017-04-06 16:55:14 +01001875 return mRequestThread->flush();
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07001876}
1877
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07001878status_t Camera3Device::prepare(int streamId) {
Ruben Brunkc78ac262015-08-13 17:58:46 -07001879 return prepare(camera3::Camera3StreamInterface::ALLOCATE_PIPELINE_MAX, streamId);
1880}
1881
1882status_t Camera3Device::prepare(int maxCount, int streamId) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07001883 ATRACE_CALL();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001884 ALOGV("%s: Camera %s: Preparing stream %d", __FUNCTION__, mId.string(), streamId);
Eino-Ville Talvala261394e2015-05-13 14:28:38 -07001885 Mutex::Autolock il(mInterfaceLock);
1886 Mutex::Autolock l(mLock);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07001887
1888 sp<Camera3StreamInterface> stream;
1889 ssize_t outputStreamIdx = mOutputStreams.indexOfKey(streamId);
1890 if (outputStreamIdx == NAME_NOT_FOUND) {
1891 CLOGE("Stream %d does not exist", streamId);
1892 return BAD_VALUE;
1893 }
1894
1895 stream = mOutputStreams.editValueAt(outputStreamIdx);
1896
1897 if (stream->isUnpreparable() || stream->hasOutstandingBuffers() ) {
Eino-Ville Talvala261394e2015-05-13 14:28:38 -07001898 CLOGE("Stream %d has already been a request target", streamId);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07001899 return BAD_VALUE;
1900 }
1901
1902 if (mRequestThread->isStreamPending(stream)) {
Eino-Ville Talvala261394e2015-05-13 14:28:38 -07001903 CLOGE("Stream %d is already a target in a pending request", streamId);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07001904 return BAD_VALUE;
1905 }
1906
Ruben Brunkc78ac262015-08-13 17:58:46 -07001907 return mPreparerThread->prepare(maxCount, stream);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07001908}
1909
Eino-Ville Talvalab25e3c82015-07-15 16:04:27 -07001910status_t Camera3Device::tearDown(int streamId) {
1911 ATRACE_CALL();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001912 ALOGV("%s: Camera %s: Tearing down stream %d", __FUNCTION__, mId.string(), streamId);
Eino-Ville Talvalab25e3c82015-07-15 16:04:27 -07001913 Mutex::Autolock il(mInterfaceLock);
1914 Mutex::Autolock l(mLock);
1915
Eino-Ville Talvalab25e3c82015-07-15 16:04:27 -07001916 sp<Camera3StreamInterface> stream;
1917 ssize_t outputStreamIdx = mOutputStreams.indexOfKey(streamId);
1918 if (outputStreamIdx == NAME_NOT_FOUND) {
1919 CLOGE("Stream %d does not exist", streamId);
1920 return BAD_VALUE;
1921 }
1922
1923 stream = mOutputStreams.editValueAt(outputStreamIdx);
1924
1925 if (stream->hasOutstandingBuffers() || mRequestThread->isStreamPending(stream)) {
1926 CLOGE("Stream %d is a target of a in-progress request", streamId);
1927 return BAD_VALUE;
1928 }
1929
1930 return stream->tearDown();
1931}
1932
Shuzhen Wangb0fdc1e2016-03-20 23:21:39 -07001933status_t Camera3Device::addBufferListenerForStream(int streamId,
1934 wp<Camera3StreamBufferListener> listener) {
1935 ATRACE_CALL();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001936 ALOGV("%s: Camera %s: Adding buffer listener for stream %d", __FUNCTION__, mId.string(), streamId);
Shuzhen Wangb0fdc1e2016-03-20 23:21:39 -07001937 Mutex::Autolock il(mInterfaceLock);
1938 Mutex::Autolock l(mLock);
1939
1940 sp<Camera3StreamInterface> stream;
1941 ssize_t outputStreamIdx = mOutputStreams.indexOfKey(streamId);
1942 if (outputStreamIdx == NAME_NOT_FOUND) {
1943 CLOGE("Stream %d does not exist", streamId);
1944 return BAD_VALUE;
1945 }
1946
1947 stream = mOutputStreams.editValueAt(outputStreamIdx);
1948 stream->addBufferListener(listener);
1949
1950 return OK;
1951}
1952
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08001953/**
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001954 * Methods called by subclasses
1955 */
1956
1957void Camera3Device::notifyStatus(bool idle) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07001958 ATRACE_CALL();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001959 {
1960 // Need mLock to safely update state and synchronize to current
1961 // state of methods in flight.
1962 Mutex::Autolock l(mLock);
1963 // We can get various system-idle notices from the status tracker
1964 // while starting up. Only care about them if we've actually sent
1965 // in some requests recently.
1966 if (mStatus != STATUS_ACTIVE && mStatus != STATUS_CONFIGURED) {
1967 return;
1968 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08001969 ALOGV("%s: Camera %s: Now %s", __FUNCTION__, mId.string(),
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001970 idle ? "idle" : "active");
Ruben Brunk183f0562015-08-12 12:55:02 -07001971 internalUpdateStatusLocked(idle ? STATUS_CONFIGURED : STATUS_ACTIVE);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001972
1973 // Skip notifying listener if we're doing some user-transparent
1974 // state changes
1975 if (mPauseStateNotify) return;
1976 }
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07001977
1978 sp<NotificationListener> listener;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001979 {
1980 Mutex::Autolock l(mOutputLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07001981 listener = mListener.promote();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07001982 }
1983 if (idle && listener != NULL) {
1984 listener->notifyIdle();
1985 }
1986}
1987
Shuzhen Wang758c2152017-01-10 18:26:18 -08001988status_t Camera3Device::setConsumerSurfaces(int streamId,
Emilian Peev40ead602017-09-26 15:46:36 +01001989 const std::vector<sp<Surface>>& consumers, std::vector<int> *surfaceIds) {
Zhijun He5d677d12016-05-29 16:52:39 -07001990 ATRACE_CALL();
Shuzhen Wang758c2152017-01-10 18:26:18 -08001991 ALOGV("%s: Camera %s: set consumer surface for stream %d",
1992 __FUNCTION__, mId.string(), streamId);
Emilian Peev40ead602017-09-26 15:46:36 +01001993
1994 if (surfaceIds == nullptr) {
1995 return BAD_VALUE;
1996 }
1997
Zhijun He5d677d12016-05-29 16:52:39 -07001998 Mutex::Autolock il(mInterfaceLock);
1999 Mutex::Autolock l(mLock);
2000
Shuzhen Wang758c2152017-01-10 18:26:18 -08002001 if (consumers.size() == 0) {
2002 CLOGE("No consumer is passed!");
Zhijun He5d677d12016-05-29 16:52:39 -07002003 return BAD_VALUE;
2004 }
2005
2006 ssize_t idx = mOutputStreams.indexOfKey(streamId);
2007 if (idx == NAME_NOT_FOUND) {
2008 CLOGE("Stream %d is unknown", streamId);
2009 return idx;
2010 }
2011 sp<Camera3OutputStreamInterface> stream = mOutputStreams[idx];
Shuzhen Wang758c2152017-01-10 18:26:18 -08002012 status_t res = stream->setConsumers(consumers);
Zhijun He5d677d12016-05-29 16:52:39 -07002013 if (res != OK) {
2014 CLOGE("Stream %d set consumer failed (error %d %s) ", streamId, res, strerror(-res));
2015 return res;
2016 }
2017
Emilian Peev40ead602017-09-26 15:46:36 +01002018 for (auto &consumer : consumers) {
2019 int id = stream->getSurfaceId(consumer);
2020 if (id < 0) {
2021 CLOGE("Invalid surface id!");
2022 return BAD_VALUE;
2023 }
2024 surfaceIds->push_back(id);
2025 }
2026
Shuzhen Wang0129d522016-10-30 22:43:41 -07002027 if (stream->isConsumerConfigurationDeferred()) {
2028 if (!stream->isConfiguring()) {
2029 CLOGE("Stream %d was already fully configured.", streamId);
2030 return INVALID_OPERATION;
2031 }
Zhijun He5d677d12016-05-29 16:52:39 -07002032
Shuzhen Wang0129d522016-10-30 22:43:41 -07002033 res = stream->finishConfiguration();
2034 if (res != OK) {
2035 SET_ERR_L("Can't finish configuring output stream %d: %s (%d)",
2036 stream->getId(), strerror(-res), res);
2037 return res;
2038 }
Zhijun He5d677d12016-05-29 16:52:39 -07002039 }
2040
2041 return OK;
2042}
2043
Emilian Peev40ead602017-09-26 15:46:36 +01002044status_t Camera3Device::updateStream(int streamId, const std::vector<sp<Surface>> &newSurfaces,
2045 const std::vector<OutputStreamInfo> &outputInfo,
2046 const std::vector<size_t> &removedSurfaceIds, KeyedVector<sp<Surface>, size_t> *outputMap) {
2047 Mutex::Autolock il(mInterfaceLock);
2048 Mutex::Autolock l(mLock);
2049
2050 ssize_t idx = mOutputStreams.indexOfKey(streamId);
2051 if (idx == NAME_NOT_FOUND) {
2052 CLOGE("Stream %d is unknown", streamId);
2053 return idx;
2054 }
2055
2056 for (const auto &it : removedSurfaceIds) {
2057 if (mRequestThread->isOutputSurfacePending(streamId, it)) {
2058 CLOGE("Shared surface still part of a pending request!");
2059 return -EBUSY;
2060 }
2061 }
2062
2063 sp<Camera3OutputStreamInterface> stream = mOutputStreams[idx];
2064 status_t res = stream->updateStream(newSurfaces, outputInfo, removedSurfaceIds, outputMap);
2065 if (res != OK) {
2066 CLOGE("Stream %d failed to update stream (error %d %s) ",
2067 streamId, res, strerror(-res));
2068 if (res == UNKNOWN_ERROR) {
2069 SET_ERR_L("%s: Stream update failed to revert to previous output configuration!",
2070 __FUNCTION__);
2071 }
2072 return res;
2073 }
2074
2075 return res;
2076}
2077
Chien-Yu Chena936ac22017-10-23 15:59:49 -07002078status_t Camera3Device::dropStreamBuffers(bool dropping, int streamId) {
2079 Mutex::Autolock il(mInterfaceLock);
2080 Mutex::Autolock l(mLock);
2081
2082 int idx = mOutputStreams.indexOfKey(streamId);
2083 if (idx == NAME_NOT_FOUND) {
2084 ALOGE("%s: Stream %d is not found.", __FUNCTION__, streamId);
2085 return BAD_VALUE;
2086 }
2087
2088 sp<Camera3OutputStreamInterface> stream = mOutputStreams.editValueAt(idx);
2089 return stream->dropBuffers(dropping);
2090}
2091
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002092/**
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002093 * Camera3Device private methods
2094 */
2095
2096sp<Camera3Device::CaptureRequest> Camera3Device::createCaptureRequest(
Shuzhen Wang0129d522016-10-30 22:43:41 -07002097 const CameraMetadata &request, const SurfaceMap &surfaceMap) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002098 ATRACE_CALL();
2099 status_t res;
2100
2101 sp<CaptureRequest> newRequest = new CaptureRequest;
2102 newRequest->mSettings = request;
2103
2104 camera_metadata_entry_t inputStreams =
2105 newRequest->mSettings.find(ANDROID_REQUEST_INPUT_STREAMS);
2106 if (inputStreams.count > 0) {
2107 if (mInputStream == NULL ||
Zhijun Hed1d64672013-09-06 15:00:01 -07002108 mInputStream->getId() != inputStreams.data.i32[0]) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002109 CLOGE("Request references unknown input stream %d",
2110 inputStreams.data.u8[0]);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002111 return NULL;
2112 }
2113 // Lazy completion of stream configuration (allocation/registration)
2114 // on first use
2115 if (mInputStream->isConfiguring()) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002116 res = mInputStream->finishConfiguration();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002117 if (res != OK) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002118 SET_ERR_L("Unable to finish configuring input stream %d:"
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002119 " %s (%d)",
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002120 mInputStream->getId(), strerror(-res), res);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002121 return NULL;
2122 }
2123 }
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002124 // Check if stream is being prepared
2125 if (mInputStream->isPreparing()) {
2126 CLOGE("Request references an input stream that's being prepared!");
2127 return NULL;
2128 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002129
2130 newRequest->mInputStream = mInputStream;
2131 newRequest->mSettings.erase(ANDROID_REQUEST_INPUT_STREAMS);
2132 }
2133
2134 camera_metadata_entry_t streams =
2135 newRequest->mSettings.find(ANDROID_REQUEST_OUTPUT_STREAMS);
2136 if (streams.count == 0) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002137 CLOGE("Zero output streams specified!");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002138 return NULL;
2139 }
2140
2141 for (size_t i = 0; i < streams.count; i++) {
Zhijun Hed1d64672013-09-06 15:00:01 -07002142 int idx = mOutputStreams.indexOfKey(streams.data.i32[i]);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002143 if (idx == NAME_NOT_FOUND) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002144 CLOGE("Request references unknown stream %d",
2145 streams.data.u8[i]);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002146 return NULL;
2147 }
Igor Murashkin2fba5842013-04-22 14:03:54 -07002148 sp<Camera3OutputStreamInterface> stream =
2149 mOutputStreams.editValueAt(idx);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002150
Zhijun He5d677d12016-05-29 16:52:39 -07002151 // It is illegal to include a deferred consumer output stream into a request
Shuzhen Wang0129d522016-10-30 22:43:41 -07002152 auto iter = surfaceMap.find(streams.data.i32[i]);
2153 if (iter != surfaceMap.end()) {
2154 const std::vector<size_t>& surfaces = iter->second;
2155 for (const auto& surface : surfaces) {
2156 if (stream->isConsumerConfigurationDeferred(surface)) {
2157 CLOGE("Stream %d surface %zu hasn't finished configuration yet "
2158 "due to deferred consumer", stream->getId(), surface);
2159 return NULL;
2160 }
2161 }
2162 newRequest->mOutputSurfaces[i] = surfaces;
Zhijun He5d677d12016-05-29 16:52:39 -07002163 }
2164
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002165 // Lazy completion of stream configuration (allocation/registration)
2166 // on first use
2167 if (stream->isConfiguring()) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002168 res = stream->finishConfiguration();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002169 if (res != OK) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002170 SET_ERR_L("Unable to finish configuring stream %d: %s (%d)",
2171 stream->getId(), strerror(-res), res);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002172 return NULL;
2173 }
2174 }
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07002175 // Check if stream is being prepared
2176 if (stream->isPreparing()) {
2177 CLOGE("Request references an output stream that's being prepared!");
2178 return NULL;
2179 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002180
2181 newRequest->mOutputStreams.push(stream);
2182 }
2183 newRequest->mSettings.erase(ANDROID_REQUEST_OUTPUT_STREAMS);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07002184 newRequest->mBatchSize = 1;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002185
2186 return newRequest;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002187}
2188
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -07002189bool Camera3Device::isOpaqueInputSizeSupported(uint32_t width, uint32_t height) {
2190 for (uint32_t i = 0; i < mSupportedOpaqueInputSizes.size(); i++) {
2191 Size size = mSupportedOpaqueInputSizes[i];
2192 if (size.width == width && size.height == height) {
2193 return true;
2194 }
2195 }
2196
2197 return false;
2198}
2199
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002200void Camera3Device::cancelStreamsConfigurationLocked() {
2201 int res = OK;
2202 if (mInputStream != NULL && mInputStream->isConfiguring()) {
2203 res = mInputStream->cancelConfiguration();
2204 if (res != OK) {
2205 CLOGE("Can't cancel configuring input stream %d: %s (%d)",
2206 mInputStream->getId(), strerror(-res), res);
2207 }
2208 }
2209
2210 for (size_t i = 0; i < mOutputStreams.size(); i++) {
2211 sp<Camera3OutputStreamInterface> outputStream = mOutputStreams.editValueAt(i);
2212 if (outputStream->isConfiguring()) {
2213 res = outputStream->cancelConfiguration();
2214 if (res != OK) {
2215 CLOGE("Can't cancel configuring output stream %d: %s (%d)",
2216 outputStream->getId(), strerror(-res), res);
2217 }
2218 }
2219 }
2220
2221 // Return state to that at start of call, so that future configures
2222 // properly clean things up
2223 internalUpdateStatusLocked(STATUS_UNCONFIGURED);
2224 mNeedConfig = true;
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002225
2226 res = mPreparerThread->resume();
2227 if (res != OK) {
2228 ALOGE("%s: Camera %s: Preparer thread failed to resume!", __FUNCTION__, mId.string());
2229 }
2230}
2231
2232bool Camera3Device::reconfigureCamera(const CameraMetadata& sessionParams) {
2233 ATRACE_CALL();
2234 bool ret = false;
2235
2236 Mutex::Autolock il(mInterfaceLock);
2237 nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
2238
2239 Mutex::Autolock l(mLock);
2240 auto rc = internalPauseAndWaitLocked(maxExpectedDuration);
2241 if (rc == NO_ERROR) {
2242 mNeedConfig = true;
2243 rc = configureStreamsLocked(mOperatingMode, sessionParams, /*notifyRequestThread*/ false);
2244 if (rc == NO_ERROR) {
2245 ret = true;
2246 mPauseStateNotify = false;
2247 //Moving to active state while holding 'mLock' is important.
2248 //There could be pending calls to 'create-/deleteStream' which
2249 //will trigger another stream configuration while the already
2250 //present streams end up with outstanding buffers that will
2251 //not get drained.
2252 internalUpdateStatusLocked(STATUS_ACTIVE);
2253 } else {
2254 setErrorStateLocked("%s: Failed to re-configure camera: %d",
2255 __FUNCTION__, rc);
2256 }
2257 } else {
2258 ALOGE("%s: Failed to pause streaming: %d", __FUNCTION__, rc);
2259 }
2260
2261 return ret;
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002262}
2263
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01002264status_t Camera3Device::configureStreamsLocked(int operatingMode,
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002265 const CameraMetadata& sessionParams, bool notifyRequestThread) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002266 ATRACE_CALL();
2267 status_t res;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002268
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002269 if (mStatus != STATUS_UNCONFIGURED && mStatus != STATUS_CONFIGURED) {
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002270 CLOGE("Not idle");
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002271 return INVALID_OPERATION;
2272 }
2273
Eino-Ville Talvalae7091aa2017-03-07 15:23:06 -08002274 if (operatingMode < 0) {
2275 CLOGE("Invalid operating mode: %d", operatingMode);
2276 return BAD_VALUE;
2277 }
2278
2279 bool isConstrainedHighSpeed =
2280 static_cast<int>(StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE) ==
2281 operatingMode;
2282
2283 if (mOperatingMode != operatingMode) {
2284 mNeedConfig = true;
2285 mIsConstrainedHighSpeedConfiguration = isConstrainedHighSpeed;
2286 mOperatingMode = operatingMode;
2287 }
2288
Eino-Ville Talvalaea26c772013-06-11 16:04:06 -07002289 if (!mNeedConfig) {
2290 ALOGV("%s: Skipping config, no stream changes", __FUNCTION__);
2291 return OK;
2292 }
2293
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002294 // Workaround for device HALv3.2 or older spec bug - zero streams requires
2295 // adding a dummy stream instead.
2296 // TODO: Bug: 17321404 for fixing the HAL spec and removing this workaround.
2297 if (mOutputStreams.size() == 0) {
2298 addDummyStreamLocked();
2299 } else {
2300 tryRemoveDummyStreamLocked();
2301 }
2302
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002303 // Start configuring the streams
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002304 ALOGV("%s: Camera %s: Starting stream configuration", __FUNCTION__, mId.string());
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002305
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002306 mPreparerThread->pause();
2307
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002308 camera3_stream_configuration config;
Eino-Ville Talvalabbbbe842017-02-28 17:50:56 -08002309 config.operation_mode = mOperatingMode;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002310 config.num_streams = (mInputStream != NULL) + mOutputStreams.size();
2311
2312 Vector<camera3_stream_t*> streams;
2313 streams.setCapacity(config.num_streams);
2314
2315 if (mInputStream != NULL) {
2316 camera3_stream_t *inputStream;
2317 inputStream = mInputStream->startConfiguration();
2318 if (inputStream == NULL) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002319 CLOGE("Can't start input stream configuration");
2320 cancelStreamsConfigurationLocked();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002321 return INVALID_OPERATION;
2322 }
2323 streams.add(inputStream);
2324 }
2325
2326 for (size_t i = 0; i < mOutputStreams.size(); i++) {
Igor Murashkin2fba5842013-04-22 14:03:54 -07002327
2328 // Don't configure bidi streams twice, nor add them twice to the list
2329 if (mOutputStreams[i].get() ==
2330 static_cast<Camera3StreamInterface*>(mInputStream.get())) {
2331
2332 config.num_streams--;
2333 continue;
2334 }
2335
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002336 camera3_stream_t *outputStream;
2337 outputStream = mOutputStreams.editValueAt(i)->startConfiguration();
2338 if (outputStream == NULL) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002339 CLOGE("Can't start output stream configuration");
2340 cancelStreamsConfigurationLocked();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002341 return INVALID_OPERATION;
2342 }
2343 streams.add(outputStream);
2344 }
2345
2346 config.streams = streams.editArray();
2347
2348 // Do the HAL configuration; will potentially touch stream
2349 // max_buffers, usage, priv fields.
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002350
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01002351 const camera_metadata_t *sessionBuffer = sessionParams.getAndLock();
2352 res = mInterface->configureStreams(sessionBuffer, &config);
2353 sessionParams.unlock(sessionBuffer);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002354
Eino-Ville Talvala17543512014-08-06 14:32:02 -07002355 if (res == BAD_VALUE) {
2356 // HAL rejected this set of streams as unsupported, clean up config
2357 // attempt and return to unconfigured state
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002358 CLOGE("Set of requested inputs/outputs not supported by HAL");
2359 cancelStreamsConfigurationLocked();
Eino-Ville Talvala17543512014-08-06 14:32:02 -07002360 return BAD_VALUE;
2361 } else if (res != OK) {
2362 // Some other kind of error from configure_streams - this is not
2363 // expected
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002364 SET_ERR_L("Unable to configure streams with HAL: %s (%d)",
2365 strerror(-res), res);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002366 return res;
2367 }
2368
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002369 // Finish all stream configuration immediately.
2370 // TODO: Try to relax this later back to lazy completion, which should be
2371 // faster
2372
Igor Murashkin073f8572013-05-02 14:59:28 -07002373 if (mInputStream != NULL && mInputStream->isConfiguring()) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002374 res = mInputStream->finishConfiguration();
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002375 if (res != OK) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002376 CLOGE("Can't finish configuring input stream %d: %s (%d)",
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002377 mInputStream->getId(), strerror(-res), res);
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002378 cancelStreamsConfigurationLocked();
2379 return BAD_VALUE;
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002380 }
2381 }
2382
2383 for (size_t i = 0; i < mOutputStreams.size(); i++) {
Igor Murashkin073f8572013-05-02 14:59:28 -07002384 sp<Camera3OutputStreamInterface> outputStream =
2385 mOutputStreams.editValueAt(i);
Zhijun He5d677d12016-05-29 16:52:39 -07002386 if (outputStream->isConfiguring() && !outputStream->isConsumerConfigurationDeferred()) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002387 res = outputStream->finishConfiguration();
Igor Murashkin073f8572013-05-02 14:59:28 -07002388 if (res != OK) {
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002389 CLOGE("Can't finish configuring output stream %d: %s (%d)",
Igor Murashkin073f8572013-05-02 14:59:28 -07002390 outputStream->getId(), strerror(-res), res);
Chien-Yu Chen9b5860b2016-06-10 13:39:09 -07002391 cancelStreamsConfigurationLocked();
2392 return BAD_VALUE;
Igor Murashkin073f8572013-05-02 14:59:28 -07002393 }
Eino-Ville Talvala4c956762013-04-19 17:26:13 -07002394 }
2395 }
2396
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002397 // Request thread needs to know to avoid using repeat-last-settings protocol
2398 // across configure_streams() calls
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002399 if (notifyRequestThread) {
2400 mRequestThread->configurationComplete(mIsConstrainedHighSpeedConfiguration, sessionParams);
2401 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002402
Zhijun He90f7c372016-08-16 16:19:43 -07002403 char value[PROPERTY_VALUE_MAX];
2404 property_get("camera.fifo.disable", value, "0");
2405 int32_t disableFifo = atoi(value);
2406 if (disableFifo != 1) {
2407 // Boost priority of request thread to SCHED_FIFO.
2408 pid_t requestThreadTid = mRequestThread->getTid();
2409 res = requestPriority(getpid(), requestThreadTid,
Mikhail Naganov83f04272017-02-07 10:45:09 -08002410 kRequestThreadPriority, /*isForApp*/ false, /*asynchronous*/ false);
Zhijun He90f7c372016-08-16 16:19:43 -07002411 if (res != OK) {
2412 ALOGW("Can't set realtime priority for request processing thread: %s (%d)",
2413 strerror(-res), res);
2414 } else {
2415 ALOGD("Set real time priority for request queue thread (tid %d)", requestThreadTid);
2416 }
Eino-Ville Talvalaf99498e2015-09-25 16:52:55 -07002417 }
2418
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002419 // Update device state
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01002420 const camera_metadata_t *newSessionParams = sessionParams.getAndLock();
2421 const camera_metadata_t *currentSessionParams = mSessionParams.getAndLock();
2422 bool updateSessionParams = (newSessionParams != currentSessionParams) ? true : false;
2423 sessionParams.unlock(newSessionParams);
2424 mSessionParams.unlock(currentSessionParams);
2425 if (updateSessionParams) {
2426 mSessionParams = sessionParams;
2427 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002428
Eino-Ville Talvalaea26c772013-06-11 16:04:06 -07002429 mNeedConfig = false;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002430
Ruben Brunk183f0562015-08-12 12:55:02 -07002431 internalUpdateStatusLocked((mDummyStreamId == NO_STREAM) ?
2432 STATUS_CONFIGURED : STATUS_UNCONFIGURED);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002433
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002434 ALOGV("%s: Camera %s: Stream configuration complete", __FUNCTION__, mId.string());
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07002435
Zhijun He0a210512014-07-24 13:45:15 -07002436 // tear down the deleted streams after configure streams.
2437 mDeletedStreams.clear();
2438
Emilian Peevac3ce6c2017-12-12 15:27:02 +00002439 auto rc = mPreparerThread->resume();
2440 if (rc != OK) {
2441 SET_ERR_L("%s: Camera %s: Preparer thread failed to resume!", __FUNCTION__, mId.string());
2442 return rc;
2443 }
2444
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002445 return OK;
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002446}
2447
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002448status_t Camera3Device::addDummyStreamLocked() {
2449 ATRACE_CALL();
2450 status_t res;
2451
2452 if (mDummyStreamId != NO_STREAM) {
2453 // Should never be adding a second dummy stream when one is already
2454 // active
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002455 SET_ERR_L("%s: Camera %s: A dummy stream already exists!",
2456 __FUNCTION__, mId.string());
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002457 return INVALID_OPERATION;
2458 }
2459
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002460 ALOGV("%s: Camera %s: Adding a dummy stream", __FUNCTION__, mId.string());
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002461
2462 sp<Camera3OutputStreamInterface> dummyStream =
2463 new Camera3DummyStream(mNextStreamId);
2464
2465 res = mOutputStreams.add(mNextStreamId, dummyStream);
2466 if (res < 0) {
2467 SET_ERR_L("Can't add dummy stream to set: %s (%d)", strerror(-res), res);
2468 return res;
2469 }
2470
2471 mDummyStreamId = mNextStreamId;
2472 mNextStreamId++;
2473
2474 return OK;
2475}
2476
2477status_t Camera3Device::tryRemoveDummyStreamLocked() {
2478 ATRACE_CALL();
2479 status_t res;
2480
2481 if (mDummyStreamId == NO_STREAM) return OK;
2482 if (mOutputStreams.size() == 1) return OK;
2483
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002484 ALOGV("%s: Camera %s: Removing the dummy stream", __FUNCTION__, mId.string());
Eino-Ville Talvala16a2ada2014-08-27 14:41:33 -07002485
2486 // Ok, have a dummy stream and there's at least one other output stream,
2487 // so remove the dummy
2488
2489 sp<Camera3StreamInterface> deletedStream;
2490 ssize_t outputStreamIdx = mOutputStreams.indexOfKey(mDummyStreamId);
2491 if (outputStreamIdx == NAME_NOT_FOUND) {
2492 SET_ERR_L("Dummy stream %d does not appear to exist", mDummyStreamId);
2493 return INVALID_OPERATION;
2494 }
2495
2496 deletedStream = mOutputStreams.editValueAt(outputStreamIdx);
2497 mOutputStreams.removeItemsAt(outputStreamIdx);
2498
2499 // Free up the stream endpoint so that it can be used by some other stream
2500 res = deletedStream->disconnect();
2501 if (res != OK) {
2502 SET_ERR_L("Can't disconnect deleted dummy stream %d", mDummyStreamId);
2503 // fall through since we want to still list the stream as deleted.
2504 }
2505 mDeletedStreams.add(deletedStream);
2506 mDummyStreamId = NO_STREAM;
2507
2508 return res;
2509}
2510
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002511void Camera3Device::setErrorState(const char *fmt, ...) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07002512 ATRACE_CALL();
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002513 Mutex::Autolock l(mLock);
2514 va_list args;
2515 va_start(args, fmt);
2516
2517 setErrorStateLockedV(fmt, args);
2518
2519 va_end(args);
2520}
2521
2522void Camera3Device::setErrorStateV(const char *fmt, va_list args) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07002523 ATRACE_CALL();
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002524 Mutex::Autolock l(mLock);
2525 setErrorStateLockedV(fmt, args);
2526}
2527
2528void Camera3Device::setErrorStateLocked(const char *fmt, ...) {
2529 va_list args;
2530 va_start(args, fmt);
2531
2532 setErrorStateLockedV(fmt, args);
2533
2534 va_end(args);
2535}
2536
2537void Camera3Device::setErrorStateLockedV(const char *fmt, va_list args) {
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002538 // Print out all error messages to log
2539 String8 errorCause = String8::formatV(fmt, args);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08002540 ALOGE("Camera %s: %s", mId.string(), errorCause.string());
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002541
2542 // But only do error state transition steps for the first error
Zhijun Heb05eeae2013-06-06 13:51:22 -07002543 if (mStatus == STATUS_ERROR || mStatus == STATUS_UNINITIALIZED) return;
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002544
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002545 mErrorCause = errorCause;
2546
Yin-Chia Yeh3d145ae2017-07-27 12:47:03 -07002547 if (mRequestThread != nullptr) {
2548 mRequestThread->setPaused(true);
2549 }
Ruben Brunk183f0562015-08-12 12:55:02 -07002550 internalUpdateStatusLocked(STATUS_ERROR);
Eino-Ville Talvala17543512014-08-06 14:32:02 -07002551
2552 // Notify upstream about a device error
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07002553 sp<NotificationListener> listener = mListener.promote();
2554 if (listener != NULL) {
2555 listener->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
Eino-Ville Talvala17543512014-08-06 14:32:02 -07002556 CaptureResultExtras());
2557 }
2558
2559 // Save stack trace. View by dumping it later.
2560 CameraTraces::saveTrace();
2561 // TODO: consider adding errorCause and client pid/procname
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07002562}
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002563
2564/**
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002565 * In-flight request management
2566 */
2567
Jianing Weicb0652e2014-03-12 18:29:36 -07002568status_t Camera3Device::registerInFlight(uint32_t frameNumber,
Chien-Yu Chend196d612015-06-22 19:49:01 -07002569 int32_t numBuffers, CaptureResultExtras resultExtras, bool hasInput,
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07002570 bool hasAppCallback, nsecs_t maxExpectedDuration) {
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002571 ATRACE_CALL();
2572 Mutex::Autolock l(mInFlightLock);
2573
2574 ssize_t res;
Chien-Yu Chend196d612015-06-22 19:49:01 -07002575 res = mInFlightMap.add(frameNumber, InFlightRequest(numBuffers, resultExtras, hasInput,
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07002576 hasAppCallback, maxExpectedDuration));
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002577 if (res < 0) return res;
2578
Eino-Ville Talvala24b366e2016-07-21 12:53:07 -07002579 if (mInFlightMap.size() == 1) {
Yin-Chia Yeh38dfde52017-06-27 17:13:33 -07002580 // hold mLock to prevent race with disconnect
2581 Mutex::Autolock l(mLock);
2582 if (mStatusTracker != nullptr) {
2583 mStatusTracker->markComponentActive(mInFlightStatusId);
2584 }
Eino-Ville Talvala24b366e2016-07-21 12:53:07 -07002585 }
2586
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07002587 mExpectedInflightDuration += maxExpectedDuration;
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002588 return OK;
2589}
2590
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08002591void Camera3Device::returnOutputBuffers(
2592 const camera3_stream_buffer_t *outputBuffers, size_t numBuffers,
2593 nsecs_t timestamp) {
2594 for (size_t i = 0; i < numBuffers; i++)
2595 {
2596 Camera3Stream *stream = Camera3Stream::cast(outputBuffers[i].stream);
2597 status_t res = stream->returnBuffer(outputBuffers[i], timestamp);
2598 // Note: stream may be deallocated at this point, if this buffer was
2599 // the last reference to it.
2600 if (res != OK) {
2601 ALOGE("Can't return buffer to its stream: %s (%d)",
2602 strerror(-res), res);
2603 }
2604 }
2605}
2606
Shuzhen Wangcadb3302016-11-04 14:17:56 -07002607void Camera3Device::removeInFlightMapEntryLocked(int idx) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07002608 ATRACE_CALL();
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07002609 nsecs_t duration = mInFlightMap.valueAt(idx).maxExpectedDuration;
Shuzhen Wangcadb3302016-11-04 14:17:56 -07002610 mInFlightMap.removeItemsAt(idx, 1);
2611
2612 // Indicate idle inFlightMap to the status tracker
2613 if (mInFlightMap.size() == 0) {
Yin-Chia Yeh38dfde52017-06-27 17:13:33 -07002614 // hold mLock to prevent race with disconnect
2615 Mutex::Autolock l(mLock);
2616 if (mStatusTracker != nullptr) {
2617 mStatusTracker->markComponentIdle(mInFlightStatusId, Fence::NO_FENCE);
2618 }
Shuzhen Wangcadb3302016-11-04 14:17:56 -07002619 }
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07002620 mExpectedInflightDuration -= duration;
Shuzhen Wangcadb3302016-11-04 14:17:56 -07002621}
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08002622
2623void Camera3Device::removeInFlightRequestIfReadyLocked(int idx) {
2624
2625 const InFlightRequest &request = mInFlightMap.valueAt(idx);
2626 const uint32_t frameNumber = mInFlightMap.keyAt(idx);
2627
2628 nsecs_t sensorTimestamp = request.sensorTimestamp;
2629 nsecs_t shutterTimestamp = request.shutterTimestamp;
2630
2631 // Check if it's okay to remove the request from InFlightMap:
2632 // In the case of a successful request:
2633 // all input and output buffers, all result metadata, shutter callback
2634 // arrived.
2635 // In the case of a unsuccessful request:
2636 // all input and output buffers arrived.
2637 if (request.numBuffersLeft == 0 &&
Shuzhen Wang20f57342017-08-24 15:39:05 -07002638 (request.skipResultMetadata ||
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08002639 (request.haveResultMetadata && shutterTimestamp != 0))) {
2640 ATRACE_ASYNC_END("frame capture", frameNumber);
2641
Shuzhen Wang403044a2017-02-26 23:29:04 -08002642 // Sanity check - if sensor timestamp matches shutter timestamp in the
2643 // case of request having callback.
2644 if (request.hasCallback && request.requestStatus == OK &&
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08002645 sensorTimestamp != shutterTimestamp) {
2646 SET_ERR("sensor timestamp (%" PRId64
2647 ") for frame %d doesn't match shutter timestamp (%" PRId64 ")",
2648 sensorTimestamp, frameNumber, shutterTimestamp);
2649 }
2650
2651 // for an unsuccessful request, it may have pending output buffers to
2652 // return.
2653 assert(request.requestStatus != OK ||
2654 request.pendingOutputBuffers.size() == 0);
2655 returnOutputBuffers(request.pendingOutputBuffers.array(),
2656 request.pendingOutputBuffers.size(), 0);
2657
Shuzhen Wangcadb3302016-11-04 14:17:56 -07002658 removeInFlightMapEntryLocked(idx);
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08002659 ALOGVV("%s: removed frame %d from InFlightMap", __FUNCTION__, frameNumber);
2660 }
2661
2662 // Sanity check - if we have too many in-flight frames, something has
2663 // likely gone wrong
Chien-Yu Chenc96ac8d2015-08-12 16:46:24 -07002664 if (!mIsConstrainedHighSpeedConfiguration && mInFlightMap.size() > kInFlightWarnLimit) {
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08002665 CLOGE("In-flight list too large: %zu", mInFlightMap.size());
Chien-Yu Chenc96ac8d2015-08-12 16:46:24 -07002666 } else if (mIsConstrainedHighSpeedConfiguration && mInFlightMap.size() >
2667 kInFlightWarnLimitHighSpeed) {
2668 CLOGE("In-flight list too large for high speed configuration: %zu",
2669 mInFlightMap.size());
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08002670 }
2671}
2672
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07002673void Camera3Device::flushInflightRequests() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07002674 ATRACE_CALL();
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07002675 { // First return buffers cached in mInFlightMap
2676 Mutex::Autolock l(mInFlightLock);
2677 for (size_t idx = 0; idx < mInFlightMap.size(); idx++) {
2678 const InFlightRequest &request = mInFlightMap.valueAt(idx);
2679 returnOutputBuffers(request.pendingOutputBuffers.array(),
2680 request.pendingOutputBuffers.size(), 0);
2681 }
2682 mInFlightMap.clear();
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07002683 mExpectedInflightDuration = 0;
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07002684 }
2685
2686 // Then return all inflight buffers not returned by HAL
2687 std::vector<std::pair<int32_t, int32_t>> inflightKeys;
2688 mInterface->getInflightBufferKeys(&inflightKeys);
2689
2690 int32_t inputStreamId = (mInputStream != nullptr) ? mInputStream->getId() : -1;
2691 for (auto& pair : inflightKeys) {
2692 int32_t frameNumber = pair.first;
2693 int32_t streamId = pair.second;
2694 buffer_handle_t* buffer;
2695 status_t res = mInterface->popInflightBuffer(frameNumber, streamId, &buffer);
2696 if (res != OK) {
2697 ALOGE("%s: Frame %d: No in-flight buffer for stream %d",
2698 __FUNCTION__, frameNumber, streamId);
2699 continue;
2700 }
2701
2702 camera3_stream_buffer_t streamBuffer;
2703 streamBuffer.buffer = buffer;
2704 streamBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
2705 streamBuffer.acquire_fence = -1;
2706 streamBuffer.release_fence = -1;
Yin-Chia Yeh5090c732017-07-20 16:05:29 -07002707
2708 // First check if the buffer belongs to deleted stream
2709 bool streamDeleted = false;
2710 for (auto& stream : mDeletedStreams) {
2711 if (streamId == stream->getId()) {
2712 streamDeleted = true;
2713 // Return buffer to deleted stream
2714 camera3_stream* halStream = stream->asHalStream();
2715 streamBuffer.stream = halStream;
2716 switch (halStream->stream_type) {
2717 case CAMERA3_STREAM_OUTPUT:
2718 res = stream->returnBuffer(streamBuffer, /*timestamp*/ 0);
2719 if (res != OK) {
2720 ALOGE("%s: Can't return output buffer for frame %d to"
2721 " stream %d: %s (%d)", __FUNCTION__,
2722 frameNumber, streamId, strerror(-res), res);
2723 }
2724 break;
2725 case CAMERA3_STREAM_INPUT:
2726 res = stream->returnInputBuffer(streamBuffer);
2727 if (res != OK) {
2728 ALOGE("%s: Can't return input buffer for frame %d to"
2729 " stream %d: %s (%d)", __FUNCTION__,
2730 frameNumber, streamId, strerror(-res), res);
2731 }
2732 break;
2733 default: // Bi-direcitonal stream is deprecated
2734 ALOGE("%s: stream %d has unknown stream type %d",
2735 __FUNCTION__, streamId, halStream->stream_type);
2736 break;
2737 }
2738 break;
2739 }
2740 }
2741 if (streamDeleted) {
2742 continue;
2743 }
2744
2745 // Then check against configured streams
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07002746 if (streamId == inputStreamId) {
2747 streamBuffer.stream = mInputStream->asHalStream();
2748 res = mInputStream->returnInputBuffer(streamBuffer);
2749 if (res != OK) {
2750 ALOGE("%s: Can't return input buffer for frame %d to"
Yin-Chia Yeh5090c732017-07-20 16:05:29 -07002751 " stream %d: %s (%d)", __FUNCTION__,
2752 frameNumber, streamId, strerror(-res), res);
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07002753 }
2754 } else {
Yin-Chia Yeh5090c732017-07-20 16:05:29 -07002755 ssize_t idx = mOutputStreams.indexOfKey(streamId);
2756 if (idx == NAME_NOT_FOUND) {
2757 ALOGE("%s: Output stream id %d not found!", __FUNCTION__, streamId);
2758 continue;
2759 }
2760 streamBuffer.stream = mOutputStreams.valueAt(idx)->asHalStream();
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07002761 returnOutputBuffers(&streamBuffer, /*size*/1, /*timestamp*/ 0);
2762 }
2763 }
2764}
2765
Emilian Peev7e25e5e2017-04-07 15:48:49 +01002766void Camera3Device::insertResultLocked(CaptureResult *result,
2767 uint32_t frameNumber) {
Chien-Yu Chen5cd8d642016-03-08 14:46:58 -08002768 if (result == nullptr) return;
2769
Emilian Peev71c73a22017-03-21 16:35:51 +00002770 camera_metadata_t *meta = const_cast<camera_metadata_t *>(
2771 result->mMetadata.getAndLock());
2772 set_camera_metadata_vendor_id(meta, mVendorTagId);
2773 result->mMetadata.unlock(meta);
2774
Chien-Yu Chen5cd8d642016-03-08 14:46:58 -08002775 if (result->mMetadata.update(ANDROID_REQUEST_FRAME_COUNT,
2776 (int32_t*)&frameNumber, 1) != OK) {
2777 SET_ERR("Failed to set frame number %d in metadata", frameNumber);
2778 return;
2779 }
2780
2781 if (result->mMetadata.update(ANDROID_REQUEST_ID, &result->mResultExtras.requestId, 1) != OK) {
2782 SET_ERR("Failed to set request ID in metadata for frame %d", frameNumber);
2783 return;
2784 }
2785
Chien-Yu Chen5cd8d642016-03-08 14:46:58 -08002786 // Valid result, insert into queue
2787 List<CaptureResult>::iterator queuedResult =
2788 mResultQueue.insert(mResultQueue.end(), CaptureResult(*result));
2789 ALOGVV("%s: result requestId = %" PRId32 ", frameNumber = %" PRId64
2790 ", burstId = %" PRId32, __FUNCTION__,
2791 queuedResult->mResultExtras.requestId,
2792 queuedResult->mResultExtras.frameNumber,
2793 queuedResult->mResultExtras.burstId);
2794
2795 mResultSignal.signal();
2796}
2797
2798
2799void Camera3Device::sendPartialCaptureResult(const camera_metadata_t * partialResult,
Emilian Peev7e25e5e2017-04-07 15:48:49 +01002800 const CaptureResultExtras &resultExtras, uint32_t frameNumber) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07002801 ATRACE_CALL();
Chien-Yu Chen5cd8d642016-03-08 14:46:58 -08002802 Mutex::Autolock l(mOutputLock);
2803
2804 CaptureResult captureResult;
2805 captureResult.mResultExtras = resultExtras;
2806 captureResult.mMetadata = partialResult;
2807
Emilian Peev7e25e5e2017-04-07 15:48:49 +01002808 insertResultLocked(&captureResult, frameNumber);
Chien-Yu Chen5cd8d642016-03-08 14:46:58 -08002809}
2810
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08002811
2812void Camera3Device::sendCaptureResult(CameraMetadata &pendingMetadata,
2813 CaptureResultExtras &resultExtras,
2814 CameraMetadata &collectedPartialResult,
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -07002815 uint32_t frameNumber,
Emilian Peev7e25e5e2017-04-07 15:48:49 +01002816 bool reprocess) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07002817 ATRACE_CALL();
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08002818 if (pendingMetadata.isEmpty())
2819 return;
2820
2821 Mutex::Autolock l(mOutputLock);
2822
2823 // TODO: need to track errors for tighter bounds on expected frame number
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -07002824 if (reprocess) {
2825 if (frameNumber < mNextReprocessResultFrameNumber) {
2826 SET_ERR("Out-of-order reprocess capture result metadata submitted! "
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08002827 "(got frame number %d, expecting %d)",
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -07002828 frameNumber, mNextReprocessResultFrameNumber);
2829 return;
2830 }
2831 mNextReprocessResultFrameNumber = frameNumber + 1;
2832 } else {
2833 if (frameNumber < mNextResultFrameNumber) {
2834 SET_ERR("Out-of-order capture result metadata submitted! "
2835 "(got frame number %d, expecting %d)",
2836 frameNumber, mNextResultFrameNumber);
2837 return;
2838 }
2839 mNextResultFrameNumber = frameNumber + 1;
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08002840 }
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08002841
2842 CaptureResult captureResult;
2843 captureResult.mResultExtras = resultExtras;
2844 captureResult.mMetadata = pendingMetadata;
2845
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08002846 // Append any previous partials to form a complete result
2847 if (mUsePartialResult && !collectedPartialResult.isEmpty()) {
2848 captureResult.mMetadata.append(collectedPartialResult);
2849 }
2850
2851 captureResult.mMetadata.sort();
2852
2853 // Check that there's a timestamp in the result metadata
Eino-Ville Talvala4d453832016-07-15 11:56:53 -07002854 camera_metadata_entry timestamp = captureResult.mMetadata.find(ANDROID_SENSOR_TIMESTAMP);
2855 if (timestamp.count == 0) {
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08002856 SET_ERR("No timestamp provided by HAL for frame %d!",
2857 frameNumber);
2858 return;
2859 }
2860
Eino-Ville Talvala4d453832016-07-15 11:56:53 -07002861 mTagMonitor.monitorMetadata(TagMonitor::RESULT,
2862 frameNumber, timestamp.data.i64[0], captureResult.mMetadata);
2863
Emilian Peev7e25e5e2017-04-07 15:48:49 +01002864 insertResultLocked(&captureResult, frameNumber);
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08002865}
2866
Eino-Ville Talvalafd6ecdd2013-10-11 09:51:09 -07002867/**
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08002868 * Camera HAL device callback methods
2869 */
2870
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002871void Camera3Device::processCaptureResult(const camera3_capture_result *result) {
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07002872 ATRACE_CALL();
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08002873
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07002874 status_t res;
2875
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002876 uint32_t frameNumber = result->frame_number;
Zhijun Hef0d962a2014-06-30 10:24:11 -07002877 if (result->result == NULL && result->num_output_buffers == 0 &&
2878 result->input_buffer == NULL) {
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002879 SET_ERR("No result data provided by HAL for frame %d",
2880 frameNumber);
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07002881 return;
2882 }
Zhijun He204e3292014-07-14 17:09:23 -07002883
Zhijun He204e3292014-07-14 17:09:23 -07002884 if (!mUsePartialResult &&
Zhijun He204e3292014-07-14 17:09:23 -07002885 result->result != NULL &&
2886 result->partial_result != 1) {
2887 SET_ERR("Result is malformed for frame %d: partial_result %u must be 1"
2888 " if partial result is not supported",
2889 frameNumber, result->partial_result);
2890 return;
2891 }
2892
2893 bool isPartialResult = false;
2894 CameraMetadata collectedPartialResult;
Jianing Weicb0652e2014-03-12 18:29:36 -07002895 CaptureResultExtras resultExtras;
Zhijun Hec98bd8d2014-07-07 12:44:10 -07002896 bool hasInputBufferInRequest = false;
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07002897
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08002898 // Get shutter timestamp and resultExtras from list of in-flight requests,
2899 // where it was added by the shutter notification for this frame. If the
2900 // shutter timestamp isn't received yet, append the output buffers to the
2901 // in-flight request and they will be returned when the shutter timestamp
2902 // arrives. Update the in-flight status and remove the in-flight entry if
2903 // all result data and shutter timestamp have been received.
2904 nsecs_t shutterTimestamp = 0;
2905
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002906 {
2907 Mutex::Autolock l(mInFlightLock);
2908 ssize_t idx = mInFlightMap.indexOfKey(frameNumber);
2909 if (idx == NAME_NOT_FOUND) {
2910 SET_ERR("Unknown frame number for capture result: %d",
2911 frameNumber);
2912 return;
2913 }
2914 InFlightRequest &request = mInFlightMap.editValueAt(idx);
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08002915 ALOGVV("%s: got InFlightRequest requestId = %" PRId32
2916 ", frameNumber = %" PRId64 ", burstId = %" PRId32
Shuzhen Wang4a472662017-02-26 23:29:04 -08002917 ", partialResultCount = %d, hasCallback = %d",
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08002918 __FUNCTION__, request.resultExtras.requestId,
2919 request.resultExtras.frameNumber, request.resultExtras.burstId,
Shuzhen Wang4a472662017-02-26 23:29:04 -08002920 result->partial_result, request.hasCallback);
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08002921 // Always update the partial count to the latest one if it's not 0
2922 // (buffers only). When framework aggregates adjacent partial results
2923 // into one, the latest partial count will be used.
2924 if (result->partial_result != 0)
2925 request.resultExtras.partialResultCount = result->partial_result;
Eino-Ville Talvalafd6ecdd2013-10-11 09:51:09 -07002926
2927 // Check if this result carries only partial metadata
Zhijun He204e3292014-07-14 17:09:23 -07002928 if (mUsePartialResult && result->result != NULL) {
Emilian Peev08dd2452017-04-06 16:55:14 +01002929 if (result->partial_result > mNumPartialResults || result->partial_result < 1) {
2930 SET_ERR("Result is malformed for frame %d: partial_result %u must be in"
2931 " the range of [1, %d] when metadata is included in the result",
2932 frameNumber, result->partial_result, mNumPartialResults);
2933 return;
2934 }
2935 isPartialResult = (result->partial_result < mNumPartialResults);
2936 if (isPartialResult) {
2937 request.collectedPartialResult.append(result->result);
Zhijun He204e3292014-07-14 17:09:23 -07002938 }
2939
Shuzhen Wang4a472662017-02-26 23:29:04 -08002940 if (isPartialResult && request.hasCallback) {
Chien-Yu Chen5cd8d642016-03-08 14:46:58 -08002941 // Send partial capture result
Emilian Peev7e25e5e2017-04-07 15:48:49 +01002942 sendPartialCaptureResult(result->result, request.resultExtras,
2943 frameNumber);
Eino-Ville Talvalafd6ecdd2013-10-11 09:51:09 -07002944 }
2945 }
2946
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08002947 shutterTimestamp = request.shutterTimestamp;
Zhijun Hec98bd8d2014-07-07 12:44:10 -07002948 hasInputBufferInRequest = request.hasInputBuffer;
Jianing Weicb0652e2014-03-12 18:29:36 -07002949
Eino-Ville Talvalafd6ecdd2013-10-11 09:51:09 -07002950 // Did we get the (final) result metadata for this capture?
Zhijun He204e3292014-07-14 17:09:23 -07002951 if (result->result != NULL && !isPartialResult) {
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002952 if (request.haveResultMetadata) {
2953 SET_ERR("Called multiple times with metadata for frame %d",
2954 frameNumber);
2955 return;
2956 }
Zhijun He204e3292014-07-14 17:09:23 -07002957 if (mUsePartialResult &&
Chien-Yu Chen5cd8d642016-03-08 14:46:58 -08002958 !request.collectedPartialResult.isEmpty()) {
Zhijun He204e3292014-07-14 17:09:23 -07002959 collectedPartialResult.acquire(
Chien-Yu Chen5cd8d642016-03-08 14:46:58 -08002960 request.collectedPartialResult);
Eino-Ville Talvalafd6ecdd2013-10-11 09:51:09 -07002961 }
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002962 request.haveResultMetadata = true;
2963 }
2964
Zhijun Hec98bd8d2014-07-07 12:44:10 -07002965 uint32_t numBuffersReturned = result->num_output_buffers;
2966 if (result->input_buffer != NULL) {
2967 if (hasInputBufferInRequest) {
2968 numBuffersReturned += 1;
2969 } else {
2970 ALOGW("%s: Input buffer should be NULL if there is no input"
2971 " buffer sent in the request",
2972 __FUNCTION__);
2973 }
2974 }
2975 request.numBuffersLeft -= numBuffersReturned;
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002976 if (request.numBuffersLeft < 0) {
2977 SET_ERR("Too many buffers returned for frame %d",
2978 frameNumber);
2979 return;
2980 }
2981
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08002982 camera_metadata_ro_entry_t entry;
2983 res = find_camera_metadata_ro_entry(result->result,
2984 ANDROID_SENSOR_TIMESTAMP, &entry);
2985 if (res == OK && entry.count == 1) {
2986 request.sensorTimestamp = entry.data.i64[0];
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07002987 }
2988
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08002989 // If shutter event isn't received yet, append the output buffers to
2990 // the in-flight request. Otherwise, return the output buffers to
2991 // streams.
2992 if (shutterTimestamp == 0) {
2993 request.pendingOutputBuffers.appendArray(result->output_buffers,
2994 result->num_output_buffers);
Igor Murashkind2c90692013-04-02 12:32:32 -07002995 } else {
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08002996 returnOutputBuffers(result->output_buffers,
2997 result->num_output_buffers, shutterTimestamp);
Igor Murashkind2c90692013-04-02 12:32:32 -07002998 }
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07002999
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08003000 if (result->result != NULL && !isPartialResult) {
3001 if (shutterTimestamp == 0) {
3002 request.pendingMetadata = result->result;
Chien-Yu Chen5cd8d642016-03-08 14:46:58 -08003003 request.collectedPartialResult = collectedPartialResult;
Shuzhen Wang4a472662017-02-26 23:29:04 -08003004 } else if (request.hasCallback) {
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08003005 CameraMetadata metadata;
3006 metadata = result->result;
3007 sendCaptureResult(metadata, request.resultExtras,
Emilian Peev7e25e5e2017-04-07 15:48:49 +01003008 collectedPartialResult, frameNumber,
3009 hasInputBufferInRequest);
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08003010 }
Eino-Ville Talvalafd6ecdd2013-10-11 09:51:09 -07003011 }
3012
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08003013 removeInFlightRequestIfReadyLocked(idx);
3014 } // scope for mInFlightLock
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07003015
Zhijun Hef0d962a2014-06-30 10:24:11 -07003016 if (result->input_buffer != NULL) {
Zhijun Hec98bd8d2014-07-07 12:44:10 -07003017 if (hasInputBufferInRequest) {
3018 Camera3Stream *stream =
3019 Camera3Stream::cast(result->input_buffer->stream);
3020 res = stream->returnInputBuffer(*(result->input_buffer));
3021 // Note: stream may be deallocated at this point, if this buffer was the
3022 // last reference to it.
3023 if (res != OK) {
3024 ALOGE("%s: RequestThread: Can't return input buffer for frame %d to"
3025 " its stream:%s (%d)", __FUNCTION__,
3026 frameNumber, strerror(-res), res);
Zhijun He0ea8fa42014-07-07 17:05:38 -07003027 }
3028 } else {
3029 ALOGW("%s: Input buffer should be NULL if there is no input"
3030 " buffer sent in the request, skipping input buffer return.",
3031 __FUNCTION__);
Zhijun Hef0d962a2014-06-30 10:24:11 -07003032 }
3033 }
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08003034}
3035
3036void Camera3Device::notify(const camera3_notify_msg *msg) {
Eino-Ville Talvala17a61ad2013-06-03 16:53:32 -07003037 ATRACE_CALL();
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07003038 sp<NotificationListener> listener;
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07003039 {
3040 Mutex::Autolock l(mOutputLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07003041 listener = mListener.promote();
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07003042 }
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08003043
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07003044 if (msg == NULL) {
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07003045 SET_ERR("HAL sent NULL notify message!");
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07003046 return;
3047 }
3048
3049 switch (msg->type) {
3050 case CAMERA3_MSG_ERROR: {
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003051 notifyError(msg->message.error, listener);
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07003052 break;
3053 }
3054 case CAMERA3_MSG_SHUTTER: {
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003055 notifyShutter(msg->message.shutter, listener);
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07003056 break;
3057 }
3058 default:
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07003059 SET_ERR("Unknown notify message from HAL: %d",
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07003060 msg->type);
Eino-Ville Talvala7d346fa2013-03-11 14:13:50 -07003061 }
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08003062}
3063
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003064void Camera3Device::notifyError(const camera3_error_msg_t &msg,
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07003065 sp<NotificationListener> listener) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003066 ATRACE_CALL();
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003067 // Map camera HAL error codes to ICameraDeviceCallback error codes
3068 // Index into this with the HAL error code
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003069 static const int32_t halErrorMap[CAMERA3_MSG_NUM_ERRORS] = {
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003070 // 0 = Unused error code
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003071 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_INVALID_ERROR,
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003072 // 1 = CAMERA3_MSG_ERROR_DEVICE
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003073 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003074 // 2 = CAMERA3_MSG_ERROR_REQUEST
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003075 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003076 // 3 = CAMERA3_MSG_ERROR_RESULT
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003077 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT,
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003078 // 4 = CAMERA3_MSG_ERROR_BUFFER
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003079 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003080 };
3081
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003082 int32_t errorCode =
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003083 ((msg.error_code >= 0) &&
3084 (msg.error_code < CAMERA3_MSG_NUM_ERRORS)) ?
3085 halErrorMap[msg.error_code] :
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003086 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_INVALID_ERROR;
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003087
3088 int streamId = 0;
3089 if (msg.error_stream != NULL) {
3090 Camera3Stream *stream =
3091 Camera3Stream::cast(msg.error_stream);
3092 streamId = stream->getId();
3093 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003094 ALOGV("Camera %s: %s: HAL error, frame %d, stream %d: %d",
3095 mId.string(), __FUNCTION__, msg.frame_number,
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003096 streamId, msg.error_code);
3097
3098 CaptureResultExtras resultExtras;
3099 switch (errorCode) {
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003100 case hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE:
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003101 // SET_ERR calls notifyError
3102 SET_ERR("Camera HAL reported serious device error");
3103 break;
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003104 case hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST:
3105 case hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT:
3106 case hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER:
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003107 {
3108 Mutex::Autolock l(mInFlightLock);
3109 ssize_t idx = mInFlightMap.indexOfKey(msg.frame_number);
3110 if (idx >= 0) {
3111 InFlightRequest &r = mInFlightMap.editValueAt(idx);
3112 r.requestStatus = msg.error_code;
3113 resultExtras = r.resultExtras;
Shuzhen Wang20f57342017-08-24 15:39:05 -07003114 if (hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT == errorCode
3115 || hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST ==
3116 errorCode) {
3117 r.skipResultMetadata = true;
3118 }
Emilian Peevba0fac32017-03-30 09:05:34 +01003119 if (hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT ==
3120 errorCode) {
3121 // In case of missing result check whether the buffers
3122 // returned. If they returned, then remove inflight
3123 // request.
3124 removeInFlightRequestIfReadyLocked(idx);
3125 }
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003126 } else {
3127 resultExtras.frameNumber = msg.frame_number;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003128 ALOGE("Camera %s: %s: cannot find in-flight request on "
3129 "frame %" PRId64 " error", mId.string(), __FUNCTION__,
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003130 resultExtras.frameNumber);
3131 }
3132 }
Eino-Ville Talvalae95bb632016-03-06 19:55:44 -08003133 resultExtras.errorStreamId = streamId;
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003134 if (listener != NULL) {
3135 listener->notifyError(errorCode, resultExtras);
3136 } else {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003137 ALOGE("Camera %s: %s: no listener available", mId.string(), __FUNCTION__);
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003138 }
3139 break;
3140 default:
3141 // SET_ERR calls notifyError
3142 SET_ERR("Unknown error message from HAL: %d", msg.error_code);
3143 break;
3144 }
3145}
3146
3147void Camera3Device::notifyShutter(const camera3_shutter_msg_t &msg,
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07003148 sp<NotificationListener> listener) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003149 ATRACE_CALL();
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003150 ssize_t idx;
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003151
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003152 // Set timestamp for the request in the in-flight tracking
3153 // and get the request ID to send upstream
3154 {
3155 Mutex::Autolock l(mInFlightLock);
3156 idx = mInFlightMap.indexOfKey(msg.frame_number);
3157 if (idx >= 0) {
3158 InFlightRequest &r = mInFlightMap.editValueAt(idx);
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08003159
Chien-Yu Chen3df11ce2015-09-30 14:13:30 -07003160 // Verify ordering of shutter notifications
3161 {
3162 Mutex::Autolock l(mOutputLock);
3163 // TODO: need to track errors for tighter bounds on expected frame number.
3164 if (r.hasInputBuffer) {
3165 if (msg.frame_number < mNextReprocessShutterFrameNumber) {
3166 SET_ERR("Shutter notification out-of-order. Expected "
3167 "notification for frame %d, got frame %d",
3168 mNextReprocessShutterFrameNumber, msg.frame_number);
3169 return;
3170 }
3171 mNextReprocessShutterFrameNumber = msg.frame_number + 1;
3172 } else {
3173 if (msg.frame_number < mNextShutterFrameNumber) {
3174 SET_ERR("Shutter notification out-of-order. Expected "
3175 "notification for frame %d, got frame %d",
3176 mNextShutterFrameNumber, msg.frame_number);
3177 return;
3178 }
3179 mNextShutterFrameNumber = msg.frame_number + 1;
3180 }
3181 }
3182
Shuzhen Wang4a472662017-02-26 23:29:04 -08003183 r.shutterTimestamp = msg.timestamp;
3184 if (r.hasCallback) {
3185 ALOGVV("Camera %s: %s: Shutter fired for frame %d (id %d) at %" PRId64,
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003186 mId.string(), __FUNCTION__,
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08003187 msg.frame_number, r.resultExtras.requestId, msg.timestamp);
Shuzhen Wang4a472662017-02-26 23:29:04 -08003188 // Call listener, if any
3189 if (listener != NULL) {
3190 listener->notifyShutter(r.resultExtras, msg.timestamp);
3191 }
3192 // send pending result and buffers
3193 sendCaptureResult(r.pendingMetadata, r.resultExtras,
3194 r.collectedPartialResult, msg.frame_number,
Emilian Peev7e25e5e2017-04-07 15:48:49 +01003195 r.hasInputBuffer);
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08003196 }
Chien-Yu Chen43e69a62014-11-25 16:38:33 -08003197 returnOutputBuffers(r.pendingOutputBuffers.array(),
3198 r.pendingOutputBuffers.size(), r.shutterTimestamp);
3199 r.pendingOutputBuffers.clear();
3200
3201 removeInFlightRequestIfReadyLocked(idx);
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003202 }
3203 }
3204 if (idx < 0) {
3205 SET_ERR("Shutter notification for non-existent frame number %d",
3206 msg.frame_number);
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003207 }
3208}
3209
3210
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07003211CameraMetadata Camera3Device::getLatestRequestLocked() {
Igor Murashkin1e479c02013-09-06 16:55:14 -07003212 ALOGV("%s", __FUNCTION__);
3213
Igor Murashkin1e479c02013-09-06 16:55:14 -07003214 CameraMetadata retVal;
3215
3216 if (mRequestThread != NULL) {
3217 retVal = mRequestThread->getLatestRequest();
3218 }
3219
Igor Murashkin1e479c02013-09-06 16:55:14 -07003220 return retVal;
3221}
3222
Jianing Weicb0652e2014-03-12 18:29:36 -07003223
Eino-Ville Talvala4d453832016-07-15 11:56:53 -07003224void Camera3Device::monitorMetadata(TagMonitor::eventSource source,
3225 int64_t frameNumber, nsecs_t timestamp, const CameraMetadata& metadata) {
3226 mTagMonitor.monitorMetadata(source, frameNumber, timestamp, metadata);
3227}
3228
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08003229/**
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003230 * HalInterface inner class methods
3231 */
3232
Yifan Hongf79b5542017-04-11 14:44:25 -07003233Camera3Device::HalInterface::HalInterface(
3234 sp<ICameraDeviceSession> &session,
3235 std::shared_ptr<RequestMetadataQueue> queue) :
Yifan Hongf79b5542017-04-11 14:44:25 -07003236 mHidlSession(session),
3237 mRequestMetadataQueue(queue) {}
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003238
Emilian Peev31abd0a2017-05-11 18:37:46 +01003239Camera3Device::HalInterface::HalInterface() {}
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003240
3241Camera3Device::HalInterface::HalInterface(const HalInterface& other) :
Yifan Hongf79b5542017-04-11 14:44:25 -07003242 mHidlSession(other.mHidlSession),
3243 mRequestMetadataQueue(other.mRequestMetadataQueue) {}
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003244
3245bool Camera3Device::HalInterface::valid() {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003246 return (mHidlSession != nullptr);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003247}
3248
3249void Camera3Device::HalInterface::clear() {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003250 mHidlSession.clear();
3251}
3252
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003253bool Camera3Device::HalInterface::supportBatchRequest() {
3254 return mHidlSession != nullptr;
3255}
3256
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003257status_t Camera3Device::HalInterface::constructDefaultRequestSettings(
3258 camera3_request_template_t templateId,
3259 /*out*/ camera_metadata_t **requestTemplate) {
3260 ATRACE_NAME("CameraHal::constructDefaultRequestSettings");
3261 if (!valid()) return INVALID_OPERATION;
3262 status_t res = OK;
3263
Emilian Peev31abd0a2017-05-11 18:37:46 +01003264 common::V1_0::Status status;
3265 RequestTemplate id;
3266 switch (templateId) {
3267 case CAMERA3_TEMPLATE_PREVIEW:
3268 id = RequestTemplate::PREVIEW;
3269 break;
3270 case CAMERA3_TEMPLATE_STILL_CAPTURE:
3271 id = RequestTemplate::STILL_CAPTURE;
3272 break;
3273 case CAMERA3_TEMPLATE_VIDEO_RECORD:
3274 id = RequestTemplate::VIDEO_RECORD;
3275 break;
3276 case CAMERA3_TEMPLATE_VIDEO_SNAPSHOT:
3277 id = RequestTemplate::VIDEO_SNAPSHOT;
3278 break;
3279 case CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG:
3280 id = RequestTemplate::ZERO_SHUTTER_LAG;
3281 break;
3282 case CAMERA3_TEMPLATE_MANUAL:
3283 id = RequestTemplate::MANUAL;
3284 break;
3285 default:
3286 // Unknown template ID
3287 return BAD_VALUE;
3288 }
3289 auto err = mHidlSession->constructDefaultRequestSettings(id,
3290 [&status, &requestTemplate]
3291 (common::V1_0::Status s, const device::V3_2::CameraMetadata& request) {
3292 status = s;
3293 if (status == common::V1_0::Status::OK) {
3294 const camera_metadata *r =
3295 reinterpret_cast<const camera_metadata_t*>(request.data());
3296 size_t expectedSize = request.size();
3297 int ret = validate_camera_metadata_structure(r, &expectedSize);
3298 if (ret == OK || ret == CAMERA_METADATA_VALIDATION_SHIFTED) {
3299 *requestTemplate = clone_camera_metadata(r);
3300 if (*requestTemplate == nullptr) {
3301 ALOGE("%s: Unable to clone camera metadata received from HAL",
3302 __FUNCTION__);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003303 status = common::V1_0::Status::INTERNAL_ERROR;
3304 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003305 } else {
3306 ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
3307 status = common::V1_0::Status::INTERNAL_ERROR;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003308 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003309 }
3310 });
3311 if (!err.isOk()) {
3312 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3313 res = DEAD_OBJECT;
3314 } else {
3315 res = CameraProviderManager::mapToStatusT(status);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003316 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003317
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003318 return res;
3319}
3320
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01003321status_t Camera3Device::HalInterface::configureStreams(const camera_metadata_t *sessionParams,
3322 camera3_stream_configuration *config) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003323 ATRACE_NAME("CameraHal::configureStreams");
3324 if (!valid()) return INVALID_OPERATION;
3325 status_t res = OK;
3326
Emilian Peev31abd0a2017-05-11 18:37:46 +01003327 // Convert stream config to HIDL
3328 std::set<int> activeStreams;
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003329 device::V3_2::StreamConfiguration requestedConfiguration3_2;
3330 device::V3_4::StreamConfiguration requestedConfiguration3_4;
3331 requestedConfiguration3_2.streams.resize(config->num_streams);
3332 requestedConfiguration3_4.streams.resize(config->num_streams);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003333 for (size_t i = 0; i < config->num_streams; i++) {
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003334 device::V3_2::Stream &dst3_2 = requestedConfiguration3_2.streams[i];
3335 device::V3_4::Stream &dst3_4 = requestedConfiguration3_4.streams[i];
Emilian Peev31abd0a2017-05-11 18:37:46 +01003336 camera3_stream_t *src = config->streams[i];
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003337
Emilian Peev31abd0a2017-05-11 18:37:46 +01003338 Camera3Stream* cam3stream = Camera3Stream::cast(src);
3339 cam3stream->setBufferFreedListener(this);
3340 int streamId = cam3stream->getId();
3341 StreamType streamType;
3342 switch (src->stream_type) {
3343 case CAMERA3_STREAM_OUTPUT:
3344 streamType = StreamType::OUTPUT;
3345 break;
3346 case CAMERA3_STREAM_INPUT:
3347 streamType = StreamType::INPUT;
3348 break;
3349 default:
3350 ALOGE("%s: Stream %d: Unsupported stream type %d",
3351 __FUNCTION__, streamId, config->streams[i]->stream_type);
3352 return BAD_VALUE;
3353 }
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003354 dst3_2.id = streamId;
3355 dst3_2.streamType = streamType;
3356 dst3_2.width = src->width;
3357 dst3_2.height = src->height;
3358 dst3_2.format = mapToPixelFormat(src->format);
3359 dst3_2.usage = mapToConsumerUsage(cam3stream->getUsage());
3360 dst3_2.dataSpace = mapToHidlDataspace(src->data_space);
3361 dst3_2.rotation = mapToStreamRotation((camera3_stream_rotation_t) src->rotation);
3362 dst3_4.v3_2 = dst3_2;
3363 if (src->physical_camera_id != nullptr) {
3364 dst3_4.physicalCameraId = src->physical_camera_id;
3365 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003366
3367 activeStreams.insert(streamId);
3368 // Create Buffer ID map if necessary
3369 if (mBufferIdMaps.count(streamId) == 0) {
3370 mBufferIdMaps.emplace(streamId, BufferIdMap{});
3371 }
3372 }
3373 // remove BufferIdMap for deleted streams
3374 for(auto it = mBufferIdMaps.begin(); it != mBufferIdMaps.end();) {
3375 int streamId = it->first;
3376 bool active = activeStreams.count(streamId) > 0;
3377 if (!active) {
3378 it = mBufferIdMaps.erase(it);
3379 } else {
3380 ++it;
3381 }
3382 }
3383
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003384 StreamConfigurationMode operationMode;
Emilian Peev31abd0a2017-05-11 18:37:46 +01003385 res = mapToStreamConfigurationMode(
3386 (camera3_stream_configuration_mode_t) config->operation_mode,
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003387 /*out*/ &operationMode);
Emilian Peev31abd0a2017-05-11 18:37:46 +01003388 if (res != OK) {
3389 return res;
3390 }
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003391 requestedConfiguration3_2.operationMode = operationMode;
3392 requestedConfiguration3_4.operationMode = operationMode;
3393 requestedConfiguration3_4.sessionParams.setToExternal(
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01003394 reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams)),
3395 get_camera_metadata_size(sessionParams));
3396
Emilian Peev31abd0a2017-05-11 18:37:46 +01003397 // Invoke configureStreams
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003398 device::V3_3::HalStreamConfiguration finalConfiguration;
Emilian Peev31abd0a2017-05-11 18:37:46 +01003399 common::V1_0::Status status;
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003400
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01003401 // See if we have v3.4 or v3.3 HAL
3402 sp<device::V3_4::ICameraDeviceSession> hidlSession_3_4;
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003403 sp<device::V3_3::ICameraDeviceSession> hidlSession_3_3;
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01003404 auto castResult_3_4 = device::V3_4::ICameraDeviceSession::castFrom(mHidlSession);
3405 if (castResult_3_4.isOk()) {
3406 hidlSession_3_4 = castResult_3_4;
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003407 } else {
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01003408 auto castResult_3_3 = device::V3_3::ICameraDeviceSession::castFrom(mHidlSession);
3409 if (castResult_3_3.isOk()) {
3410 hidlSession_3_3 = castResult_3_3;
3411 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003412 }
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01003413
3414 if (hidlSession_3_4 != nullptr) {
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003415 // We do; use v3.4 for the call, and construct a v3.4
3416 // HalStreamConfiguration
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01003417 ALOGV("%s: v3.4 device found", __FUNCTION__);
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003418 device::V3_4::HalStreamConfiguration finalConfiguration3_4;
3419 auto err = hidlSession_3_4->configureStreams_3_4(requestedConfiguration3_4,
3420 [&status, &finalConfiguration3_4]
3421 (common::V1_0::Status s, const device::V3_4::HalStreamConfiguration& halConfiguration) {
3422 finalConfiguration3_4 = halConfiguration;
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01003423 status = s;
3424 });
3425 if (!err.isOk()) {
3426 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3427 return DEAD_OBJECT;
3428 }
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003429 finalConfiguration.streams.resize(finalConfiguration3_4.streams.size());
3430 for (size_t i = 0; i < finalConfiguration3_4.streams.size(); i++) {
3431 finalConfiguration.streams[i] = finalConfiguration3_4.streams[i].v3_3;
3432 }
Emilian Peev5fbe0ba2017-10-20 15:45:45 +01003433 } else if (hidlSession_3_3 != nullptr) {
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003434 // We do; use v3.3 for the call
3435 ALOGV("%s: v3.3 device found", __FUNCTION__);
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003436 auto err = hidlSession_3_3->configureStreams_3_3(requestedConfiguration3_2,
Emilian Peev31abd0a2017-05-11 18:37:46 +01003437 [&status, &finalConfiguration]
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003438 (common::V1_0::Status s, const device::V3_3::HalStreamConfiguration& halConfiguration) {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003439 finalConfiguration = halConfiguration;
3440 status = s;
3441 });
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003442 if (!err.isOk()) {
3443 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3444 return DEAD_OBJECT;
3445 }
3446 } else {
3447 // We don't; use v3.2 call and construct a v3.3 HalStreamConfiguration
3448 ALOGV("%s: v3.2 device found", __FUNCTION__);
3449 HalStreamConfiguration finalConfiguration_3_2;
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003450 auto err = mHidlSession->configureStreams(requestedConfiguration3_2,
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003451 [&status, &finalConfiguration_3_2]
3452 (common::V1_0::Status s, const HalStreamConfiguration& halConfiguration) {
3453 finalConfiguration_3_2 = halConfiguration;
3454 status = s;
3455 });
3456 if (!err.isOk()) {
3457 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3458 return DEAD_OBJECT;
3459 }
3460 finalConfiguration.streams.resize(finalConfiguration_3_2.streams.size());
3461 for (size_t i = 0; i < finalConfiguration_3_2.streams.size(); i++) {
3462 finalConfiguration.streams[i].v3_2 = finalConfiguration_3_2.streams[i];
3463 finalConfiguration.streams[i].overrideDataSpace =
Shuzhen Wangc28189a2017-11-27 23:05:10 -08003464 requestedConfiguration3_2.streams[i].dataSpace;
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003465 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003466 }
3467
3468 if (status != common::V1_0::Status::OK ) {
3469 return CameraProviderManager::mapToStatusT(status);
3470 }
3471
3472 // And convert output stream configuration from HIDL
3473
3474 for (size_t i = 0; i < config->num_streams; i++) {
3475 camera3_stream_t *dst = config->streams[i];
3476 int streamId = Camera3Stream::cast(dst)->getId();
3477
3478 // Start scan at i, with the assumption that the stream order matches
3479 size_t realIdx = i;
3480 bool found = false;
3481 for (size_t idx = 0; idx < finalConfiguration.streams.size(); idx++) {
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003482 if (finalConfiguration.streams[realIdx].v3_2.id == streamId) {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003483 found = true;
3484 break;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003485 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003486 realIdx = (realIdx >= finalConfiguration.streams.size()) ? 0 : realIdx + 1;
3487 }
3488 if (!found) {
3489 ALOGE("%s: Stream %d not found in stream configuration response from HAL",
3490 __FUNCTION__, streamId);
3491 return INVALID_OPERATION;
3492 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003493 device::V3_3::HalStream &src = finalConfiguration.streams[realIdx];
Yin-Chia Yeh77327052017-01-09 18:23:07 -08003494
Emilian Peev710c1422017-08-30 11:19:38 +01003495 Camera3Stream* dstStream = Camera3Stream::cast(dst);
3496 dstStream->setFormatOverride(false);
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003497 dstStream->setDataSpaceOverride(false);
3498 int overrideFormat = mapToFrameworkFormat(src.v3_2.overrideFormat);
3499 android_dataspace overrideDataSpace = mapToFrameworkDataspace(src.overrideDataSpace);
3500
Emilian Peev31abd0a2017-05-11 18:37:46 +01003501 if (dst->format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
3502 if (dst->format != overrideFormat) {
3503 ALOGE("%s: Stream %d: Format override not allowed for format 0x%x", __FUNCTION__,
3504 streamId, dst->format);
Yin-Chia Yeh77327052017-01-09 18:23:07 -08003505 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003506 if (dst->data_space != overrideDataSpace) {
3507 ALOGE("%s: Stream %d: DataSpace override not allowed for format 0x%x", __FUNCTION__,
3508 streamId, dst->format);
3509 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003510 } else {
Emilian Peev710c1422017-08-30 11:19:38 +01003511 dstStream->setFormatOverride((dst->format != overrideFormat) ? true : false);
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003512 dstStream->setDataSpaceOverride((dst->data_space != overrideDataSpace) ? true : false);
3513
Emilian Peev31abd0a2017-05-11 18:37:46 +01003514 // Override allowed with IMPLEMENTATION_DEFINED
3515 dst->format = overrideFormat;
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003516 dst->data_space = overrideDataSpace;
Yin-Chia Yeh77327052017-01-09 18:23:07 -08003517 }
3518
Emilian Peev31abd0a2017-05-11 18:37:46 +01003519 if (dst->stream_type == CAMERA3_STREAM_INPUT) {
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003520 if (src.v3_2.producerUsage != 0) {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003521 ALOGE("%s: Stream %d: INPUT streams must have 0 for producer usage",
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003522 __FUNCTION__, streamId);
3523 return INVALID_OPERATION;
3524 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003525 dstStream->setUsage(
3526 mapConsumerToFrameworkUsage(src.v3_2.consumerUsage));
Emilian Peev31abd0a2017-05-11 18:37:46 +01003527 } else {
3528 // OUTPUT
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003529 if (src.v3_2.consumerUsage != 0) {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003530 ALOGE("%s: Stream %d: OUTPUT streams must have 0 for consumer usage",
3531 __FUNCTION__, streamId);
3532 return INVALID_OPERATION;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003533 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003534 dstStream->setUsage(
3535 mapProducerToFrameworkUsage(src.v3_2.producerUsage));
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003536 }
Eino-Ville Talvala91cd3f82017-08-21 16:12:50 -07003537 dst->max_buffers = src.v3_2.maxBuffers;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003538 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003539
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003540 return res;
3541}
3542
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003543void Camera3Device::HalInterface::wrapAsHidlRequest(camera3_capture_request_t* request,
3544 /*out*/device::V3_2::CaptureRequest* captureRequest,
3545 /*out*/std::vector<native_handle_t*>* handlesCreated) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003546 ATRACE_CALL();
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003547 if (captureRequest == nullptr || handlesCreated == nullptr) {
3548 ALOGE("%s: captureRequest (%p) and handlesCreated (%p) must not be null",
3549 __FUNCTION__, captureRequest, handlesCreated);
3550 return;
3551 }
3552
3553 captureRequest->frameNumber = request->frame_number;
Yifan Hongf79b5542017-04-11 14:44:25 -07003554
3555 captureRequest->fmqSettingsSize = 0;
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003556
3557 {
3558 std::lock_guard<std::mutex> lock(mInflightLock);
3559 if (request->input_buffer != nullptr) {
3560 int32_t streamId = Camera3Stream::cast(request->input_buffer->stream)->getId();
3561 buffer_handle_t buf = *(request->input_buffer->buffer);
3562 auto pair = getBufferId(buf, streamId);
3563 bool isNewBuffer = pair.first;
3564 uint64_t bufferId = pair.second;
3565 captureRequest->inputBuffer.streamId = streamId;
3566 captureRequest->inputBuffer.bufferId = bufferId;
3567 captureRequest->inputBuffer.buffer = (isNewBuffer) ? buf : nullptr;
3568 captureRequest->inputBuffer.status = BufferStatus::OK;
3569 native_handle_t *acquireFence = nullptr;
3570 if (request->input_buffer->acquire_fence != -1) {
3571 acquireFence = native_handle_create(1,0);
3572 acquireFence->data[0] = request->input_buffer->acquire_fence;
3573 handlesCreated->push_back(acquireFence);
3574 }
3575 captureRequest->inputBuffer.acquireFence = acquireFence;
3576 captureRequest->inputBuffer.releaseFence = nullptr;
3577
3578 pushInflightBufferLocked(captureRequest->frameNumber, streamId,
3579 request->input_buffer->buffer,
3580 request->input_buffer->acquire_fence);
3581 } else {
3582 captureRequest->inputBuffer.streamId = -1;
3583 captureRequest->inputBuffer.bufferId = BUFFER_ID_NO_BUFFER;
3584 }
3585
3586 captureRequest->outputBuffers.resize(request->num_output_buffers);
3587 for (size_t i = 0; i < request->num_output_buffers; i++) {
3588 const camera3_stream_buffer_t *src = request->output_buffers + i;
3589 StreamBuffer &dst = captureRequest->outputBuffers[i];
3590 int32_t streamId = Camera3Stream::cast(src->stream)->getId();
3591 buffer_handle_t buf = *(src->buffer);
3592 auto pair = getBufferId(buf, streamId);
3593 bool isNewBuffer = pair.first;
3594 dst.streamId = streamId;
3595 dst.bufferId = pair.second;
3596 dst.buffer = isNewBuffer ? buf : nullptr;
3597 dst.status = BufferStatus::OK;
3598 native_handle_t *acquireFence = nullptr;
3599 if (src->acquire_fence != -1) {
3600 acquireFence = native_handle_create(1,0);
3601 acquireFence->data[0] = src->acquire_fence;
3602 handlesCreated->push_back(acquireFence);
3603 }
3604 dst.acquireFence = acquireFence;
3605 dst.releaseFence = nullptr;
3606
3607 pushInflightBufferLocked(captureRequest->frameNumber, streamId,
3608 src->buffer, src->acquire_fence);
3609 }
3610 }
3611}
3612
3613status_t Camera3Device::HalInterface::processBatchCaptureRequests(
3614 std::vector<camera3_capture_request_t*>& requests,/*out*/uint32_t* numRequestProcessed) {
3615 ATRACE_NAME("CameraHal::processBatchCaptureRequests");
3616 if (!valid()) return INVALID_OPERATION;
3617
3618 hardware::hidl_vec<device::V3_2::CaptureRequest> captureRequests;
3619 size_t batchSize = requests.size();
3620 captureRequests.resize(batchSize);
3621 std::vector<native_handle_t*> handlesCreated;
3622
3623 for (size_t i = 0; i < batchSize; i++) {
3624 wrapAsHidlRequest(requests[i], /*out*/&captureRequests[i], /*out*/&handlesCreated);
3625 }
3626
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003627 std::vector<device::V3_2::BufferCache> cachesToRemove;
3628 {
3629 std::lock_guard<std::mutex> lock(mBufferIdMapLock);
3630 for (auto& pair : mFreedBuffers) {
3631 // The stream might have been removed since onBufferFreed
3632 if (mBufferIdMaps.find(pair.first) != mBufferIdMaps.end()) {
3633 cachesToRemove.push_back({pair.first, pair.second});
3634 }
3635 }
3636 mFreedBuffers.clear();
3637 }
3638
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003639 common::V1_0::Status status = common::V1_0::Status::INTERNAL_ERROR;
3640 *numRequestProcessed = 0;
Yifan Hongf79b5542017-04-11 14:44:25 -07003641
3642 // Write metadata to FMQ.
3643 for (size_t i = 0; i < batchSize; i++) {
3644 camera3_capture_request_t* request = requests[i];
3645 device::V3_2::CaptureRequest* captureRequest = &captureRequests[i];
3646
3647 if (request->settings != nullptr) {
3648 size_t settingsSize = get_camera_metadata_size(request->settings);
3649 if (mRequestMetadataQueue != nullptr && mRequestMetadataQueue->write(
3650 reinterpret_cast<const uint8_t*>(request->settings), settingsSize)) {
3651 captureRequest->settings.resize(0);
3652 captureRequest->fmqSettingsSize = settingsSize;
3653 } else {
3654 if (mRequestMetadataQueue != nullptr) {
3655 ALOGW("%s: couldn't utilize fmq, fallback to hwbinder", __FUNCTION__);
3656 }
3657 captureRequest->settings.setToExternal(
3658 reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(request->settings)),
3659 get_camera_metadata_size(request->settings));
3660 captureRequest->fmqSettingsSize = 0u;
3661 }
3662 } else {
3663 // A null request settings maps to a size-0 CameraMetadata
3664 captureRequest->settings.resize(0);
3665 captureRequest->fmqSettingsSize = 0u;
3666 }
3667 }
Eino-Ville Talvalac5cbb872017-04-27 12:48:33 -07003668 auto err = mHidlSession->processCaptureRequest(captureRequests, cachesToRemove,
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003669 [&status, &numRequestProcessed] (auto s, uint32_t n) {
3670 status = s;
3671 *numRequestProcessed = n;
3672 });
Eino-Ville Talvalac5cbb872017-04-27 12:48:33 -07003673 if (!err.isOk()) {
3674 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3675 return DEAD_OBJECT;
3676 }
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08003677 if (status == common::V1_0::Status::OK && *numRequestProcessed != batchSize) {
3678 ALOGE("%s: processCaptureRequest returns OK but processed %d/%zu requests",
3679 __FUNCTION__, *numRequestProcessed, batchSize);
3680 status = common::V1_0::Status::INTERNAL_ERROR;
3681 }
3682
3683 for (auto& handle : handlesCreated) {
3684 native_handle_delete(handle);
3685 }
3686 return CameraProviderManager::mapToStatusT(status);
3687}
3688
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003689status_t Camera3Device::HalInterface::processCaptureRequest(
3690 camera3_capture_request_t *request) {
3691 ATRACE_NAME("CameraHal::processCaptureRequest");
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003692 if (!valid()) return INVALID_OPERATION;
3693 status_t res = OK;
3694
Emilian Peev31abd0a2017-05-11 18:37:46 +01003695 uint32_t numRequestProcessed = 0;
3696 std::vector<camera3_capture_request_t*> requests(1);
3697 requests[0] = request;
3698 res = processBatchCaptureRequests(requests, &numRequestProcessed);
3699
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003700 return res;
3701}
3702
3703status_t Camera3Device::HalInterface::flush() {
3704 ATRACE_NAME("CameraHal::flush");
3705 if (!valid()) return INVALID_OPERATION;
3706 status_t res = OK;
3707
Emilian Peev31abd0a2017-05-11 18:37:46 +01003708 auto err = mHidlSession->flush();
3709 if (!err.isOk()) {
3710 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
3711 res = DEAD_OBJECT;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003712 } else {
Emilian Peev31abd0a2017-05-11 18:37:46 +01003713 res = CameraProviderManager::mapToStatusT(err);
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003714 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003715
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003716 return res;
3717}
3718
Emilian Peev31abd0a2017-05-11 18:37:46 +01003719status_t Camera3Device::HalInterface::dump(int /*fd*/) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003720 ATRACE_NAME("CameraHal::dump");
3721 if (!valid()) return INVALID_OPERATION;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003722
Emilian Peev31abd0a2017-05-11 18:37:46 +01003723 // Handled by CameraProviderManager::dump
3724
3725 return OK;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003726}
3727
3728status_t Camera3Device::HalInterface::close() {
3729 ATRACE_NAME("CameraHal::close()");
3730 if (!valid()) return INVALID_OPERATION;
3731 status_t res = OK;
3732
Emilian Peev31abd0a2017-05-11 18:37:46 +01003733 auto err = mHidlSession->close();
3734 // Interface will be dead shortly anyway, so don't log errors
3735 if (!err.isOk()) {
3736 res = DEAD_OBJECT;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003737 }
Emilian Peev31abd0a2017-05-11 18:37:46 +01003738
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003739 return res;
3740}
3741
Yin-Chia Yehf3fe36f2017-07-07 18:23:18 -07003742void Camera3Device::HalInterface::getInflightBufferKeys(
3743 std::vector<std::pair<int32_t, int32_t>>* out) {
3744 std::lock_guard<std::mutex> lock(mInflightLock);
3745 out->clear();
3746 out->reserve(mInflightBufferMap.size());
3747 for (auto& pair : mInflightBufferMap) {
3748 uint64_t key = pair.first;
3749 int32_t streamId = key & 0xFFFFFFFF;
3750 int32_t frameNumber = (key >> 32) & 0xFFFFFFFF;
3751 out->push_back(std::make_pair(frameNumber, streamId));
3752 }
3753 return;
3754}
3755
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003756status_t Camera3Device::HalInterface::pushInflightBufferLocked(
Yin-Chia Yehf4650602017-01-10 13:13:39 -08003757 int32_t frameNumber, int32_t streamId, buffer_handle_t *buffer, int acquireFence) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003758 uint64_t key = static_cast<uint64_t>(frameNumber) << 32 | static_cast<uint64_t>(streamId);
Yin-Chia Yehf4650602017-01-10 13:13:39 -08003759 auto pair = std::make_pair(buffer, acquireFence);
3760 mInflightBufferMap[key] = pair;
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003761 return OK;
3762}
3763
3764status_t Camera3Device::HalInterface::popInflightBuffer(
Yin-Chia Yehf4650602017-01-10 13:13:39 -08003765 int32_t frameNumber, int32_t streamId,
3766 /*out*/ buffer_handle_t **buffer) {
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003767 std::lock_guard<std::mutex> lock(mInflightLock);
3768
3769 uint64_t key = static_cast<uint64_t>(frameNumber) << 32 | static_cast<uint64_t>(streamId);
3770 auto it = mInflightBufferMap.find(key);
3771 if (it == mInflightBufferMap.end()) return NAME_NOT_FOUND;
Yin-Chia Yehf4650602017-01-10 13:13:39 -08003772 auto pair = it->second;
3773 *buffer = pair.first;
3774 int acquireFence = pair.second;
3775 if (acquireFence > 0) {
3776 ::close(acquireFence);
3777 }
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003778 mInflightBufferMap.erase(it);
3779 return OK;
3780}
3781
Yin-Chia Yeh77327052017-01-09 18:23:07 -08003782std::pair<bool, uint64_t> Camera3Device::HalInterface::getBufferId(
3783 const buffer_handle_t& buf, int streamId) {
3784 std::lock_guard<std::mutex> lock(mBufferIdMapLock);
3785
3786 BufferIdMap& bIdMap = mBufferIdMaps.at(streamId);
3787 auto it = bIdMap.find(buf);
3788 if (it == bIdMap.end()) {
3789 bIdMap[buf] = mNextBufferId++;
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003790 ALOGV("stream %d now have %zu buffer caches, buf %p",
3791 streamId, bIdMap.size(), buf);
Yin-Chia Yeh77327052017-01-09 18:23:07 -08003792 return std::make_pair(true, mNextBufferId - 1);
3793 } else {
3794 return std::make_pair(false, it->second);
3795 }
3796}
3797
Yin-Chia Yehbe83fa72017-03-30 13:35:36 -07003798void Camera3Device::HalInterface::onBufferFreed(
3799 int streamId, const native_handle_t* handle) {
3800 std::lock_guard<std::mutex> lock(mBufferIdMapLock);
3801 uint64_t bufferId = BUFFER_ID_NO_BUFFER;
3802 auto mapIt = mBufferIdMaps.find(streamId);
3803 if (mapIt == mBufferIdMaps.end()) {
3804 // streamId might be from a deleted stream here
3805 ALOGI("%s: stream %d has been removed",
3806 __FUNCTION__, streamId);
3807 return;
3808 }
3809 BufferIdMap& bIdMap = mapIt->second;
3810 auto it = bIdMap.find(handle);
3811 if (it == bIdMap.end()) {
3812 ALOGW("%s: cannot find buffer %p in stream %d",
3813 __FUNCTION__, handle, streamId);
3814 return;
3815 } else {
3816 bufferId = it->second;
3817 bIdMap.erase(it);
3818 ALOGV("%s: stream %d now have %zu buffer caches after removing buf %p",
3819 __FUNCTION__, streamId, bIdMap.size(), handle);
3820 }
3821 mFreedBuffers.push_back(std::make_pair(streamId, bufferId));
3822}
3823
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003824/**
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003825 * RequestThread inner class methods
3826 */
3827
3828Camera3Device::RequestThread::RequestThread(wp<Camera3Device> parent,
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07003829 sp<StatusTracker> statusTracker,
Emilian Peevac3ce6c2017-12-12 15:27:02 +00003830 sp<HalInterface> interface, const Vector<int32_t>& sessionParamKeys) :
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07003831 Thread(/*canCallJava*/false),
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003832 mParent(parent),
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07003833 mStatusTracker(statusTracker),
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003834 mInterface(interface),
Eino-Ville Talvala77c1a352016-06-13 12:32:43 -07003835 mListener(nullptr),
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07003836 mId(getId(parent)),
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003837 mReconfigured(false),
3838 mDoPause(false),
3839 mPaused(true),
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003840 mFrameNumber(0),
Jianing Weicb0652e2014-03-12 18:29:36 -07003841 mLatestRequestId(NAME_NOT_FOUND),
Yin-Chia Yehc00a25c2014-08-21 14:27:44 -07003842 mCurrentAfTriggerId(0),
3843 mCurrentPreCaptureTriggerId(0),
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003844 mRepeatingLastFrameNumber(
3845 hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES),
Shuzhen Wang686f6442017-06-20 16:16:04 -07003846 mPrepareVideoStream(false),
Emilian Peevac3ce6c2017-12-12 15:27:02 +00003847 mRequestLatency(kRequestLatencyBinSize),
3848 mSessionParamKeys(sessionParamKeys),
3849 mLatestSessionParams(sessionParamKeys.size()) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07003850 mStatusId = statusTracker->addComponent();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003851}
3852
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003853Camera3Device::RequestThread::~RequestThread() {}
3854
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07003855void Camera3Device::RequestThread::setNotificationListener(
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07003856 wp<NotificationListener> listener) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003857 ATRACE_CALL();
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003858 Mutex::Autolock l(mRequestLock);
3859 mListener = listener;
3860}
3861
Emilian Peevac3ce6c2017-12-12 15:27:02 +00003862void Camera3Device::RequestThread::configurationComplete(bool isConstrainedHighSpeed,
3863 const CameraMetadata& sessionParams) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003864 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003865 Mutex::Autolock l(mRequestLock);
3866 mReconfigured = true;
Emilian Peevac3ce6c2017-12-12 15:27:02 +00003867 mLatestSessionParams = sessionParams;
Chien-Yu Chenc66969b2016-05-19 16:37:51 -07003868 // Prepare video stream for high speed recording.
3869 mPrepareVideoStream = isConstrainedHighSpeed;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003870}
3871
Jianing Wei90e59c92014-03-12 18:29:36 -07003872status_t Camera3Device::RequestThread::queueRequestList(
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003873 List<sp<CaptureRequest> > &requests,
3874 /*out*/
3875 int64_t *lastFrameNumber) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003876 ATRACE_CALL();
Jianing Wei90e59c92014-03-12 18:29:36 -07003877 Mutex::Autolock l(mRequestLock);
3878 for (List<sp<CaptureRequest> >::iterator it = requests.begin(); it != requests.end();
3879 ++it) {
3880 mRequestQueue.push_back(*it);
3881 }
3882
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003883 if (lastFrameNumber != NULL) {
3884 *lastFrameNumber = mFrameNumber + mRequestQueue.size() - 1;
3885 ALOGV("%s: requestId %d, mFrameNumber %" PRId32 ", lastFrameNumber %" PRId64 ".",
3886 __FUNCTION__, (*(requests.begin()))->mResultExtras.requestId, mFrameNumber,
3887 *lastFrameNumber);
3888 }
Jianing Weicb0652e2014-03-12 18:29:36 -07003889
Jianing Wei90e59c92014-03-12 18:29:36 -07003890 unpauseForNewRequests();
3891
3892 return OK;
3893}
3894
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003895
3896status_t Camera3Device::RequestThread::queueTrigger(
3897 RequestTrigger trigger[],
3898 size_t count) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003899 ATRACE_CALL();
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003900 Mutex::Autolock l(mTriggerMutex);
3901 status_t ret;
3902
3903 for (size_t i = 0; i < count; ++i) {
3904 ret = queueTriggerLocked(trigger[i]);
3905
3906 if (ret != OK) {
3907 return ret;
3908 }
3909 }
3910
3911 return OK;
3912}
3913
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003914const String8& Camera3Device::RequestThread::getId(const wp<Camera3Device> &device) {
3915 static String8 deadId("<DeadDevice>");
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07003916 sp<Camera3Device> d = device.promote();
Eino-Ville Talvala0b1cb142016-12-19 16:29:17 -08003917 if (d != nullptr) return d->mId;
3918 return deadId;
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07003919}
3920
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003921status_t Camera3Device::RequestThread::queueTriggerLocked(
3922 RequestTrigger trigger) {
3923
3924 uint32_t tag = trigger.metadataTag;
3925 ssize_t index = mTriggerMap.indexOfKey(tag);
3926
3927 switch (trigger.getTagType()) {
3928 case TYPE_BYTE:
3929 // fall-through
3930 case TYPE_INT32:
3931 break;
3932 default:
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07003933 ALOGE("%s: Type not supported: 0x%x", __FUNCTION__,
3934 trigger.getTagType());
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07003935 return INVALID_OPERATION;
3936 }
3937
3938 /**
3939 * Collect only the latest trigger, since we only have 1 field
3940 * in the request settings per trigger tag, and can't send more than 1
3941 * trigger per request.
3942 */
3943 if (index != NAME_NOT_FOUND) {
3944 mTriggerMap.editValueAt(index) = trigger;
3945 } else {
3946 mTriggerMap.add(tag, trigger);
3947 }
3948
3949 return OK;
3950}
3951
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003952status_t Camera3Device::RequestThread::setRepeatingRequests(
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003953 const RequestList &requests,
3954 /*out*/
3955 int64_t *lastFrameNumber) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003956 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003957 Mutex::Autolock l(mRequestLock);
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003958 if (lastFrameNumber != NULL) {
3959 *lastFrameNumber = mRepeatingLastFrameNumber;
3960 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003961 mRepeatingRequests.clear();
3962 mRepeatingRequests.insert(mRepeatingRequests.begin(),
3963 requests.begin(), requests.end());
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07003964
3965 unpauseForNewRequests();
3966
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003967 mRepeatingLastFrameNumber = hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003968 return OK;
3969}
3970
Chih-Hung Hsieh8b0b9712016-08-09 14:25:53 -07003971bool Camera3Device::RequestThread::isRepeatingRequestLocked(const sp<CaptureRequest>& requestIn) {
Yin-Chia Yeh8684b7f2014-06-13 14:53:05 -07003972 if (mRepeatingRequests.empty()) {
3973 return false;
3974 }
3975 int32_t requestId = requestIn->mResultExtras.requestId;
3976 const RequestList &repeatRequests = mRepeatingRequests;
3977 // All repeating requests are guaranteed to have same id so only check first quest
3978 const sp<CaptureRequest> firstRequest = *repeatRequests.begin();
3979 return (firstRequest->mResultExtras.requestId == requestId);
3980}
3981
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003982status_t Camera3Device::RequestThread::clearRepeatingRequests(/*out*/int64_t *lastFrameNumber) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07003983 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003984 Mutex::Autolock l(mRequestLock);
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07003985 return clearRepeatingRequestsLocked(lastFrameNumber);
3986
3987}
3988
3989status_t Camera3Device::RequestThread::clearRepeatingRequestsLocked(/*out*/int64_t *lastFrameNumber) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003990 mRepeatingRequests.clear();
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07003991 if (lastFrameNumber != NULL) {
3992 *lastFrameNumber = mRepeatingLastFrameNumber;
3993 }
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08003994 mRepeatingLastFrameNumber = hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08003995 return OK;
3996}
3997
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003998status_t Camera3Device::RequestThread::clear(
Eino-Ville Talvala17543512014-08-06 14:32:02 -07003999 /*out*/int64_t *lastFrameNumber) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004000 ATRACE_CALL();
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07004001 Mutex::Autolock l(mRequestLock);
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07004002 ALOGV("RequestThread::%s:", __FUNCTION__);
Eino-Ville Talvala17543512014-08-06 14:32:02 -07004003
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07004004 mRepeatingRequests.clear();
Yin-Chia Yeh8684b7f2014-06-13 14:53:05 -07004005
Eino-Ville Talvala17543512014-08-06 14:32:02 -07004006 // Send errors for all requests pending in the request queue, including
4007 // pending repeating requests
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07004008 sp<NotificationListener> listener = mListener.promote();
Eino-Ville Talvala17543512014-08-06 14:32:02 -07004009 if (listener != NULL) {
4010 for (RequestList::iterator it = mRequestQueue.begin();
4011 it != mRequestQueue.end(); ++it) {
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07004012 // Abort the input buffers for reprocess requests.
4013 if ((*it)->mInputStream != NULL) {
4014 camera3_stream_buffer_t inputBuffer;
Eino-Ville Talvalaba435252017-06-21 16:07:25 -07004015 status_t res = (*it)->mInputStream->getInputBuffer(&inputBuffer,
4016 /*respectHalLimit*/ false);
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07004017 if (res != OK) {
4018 ALOGW("%s: %d: couldn't get input buffer while clearing the request "
4019 "list: %s (%d)", __FUNCTION__, __LINE__, strerror(-res), res);
4020 } else {
4021 res = (*it)->mInputStream->returnInputBuffer(inputBuffer);
4022 if (res != OK) {
4023 ALOGE("%s: %d: couldn't return input buffer while clearing the request "
4024 "list: %s (%d)", __FUNCTION__, __LINE__, strerror(-res), res);
4025 }
4026 }
4027 }
Eino-Ville Talvala17543512014-08-06 14:32:02 -07004028 // Set the frame number this request would have had, if it
4029 // had been submitted; this frame number will not be reused.
4030 // The requestId and burstId fields were set when the request was
4031 // submitted originally (in convertMetadataListToRequestListLocked)
4032 (*it)->mResultExtras.frameNumber = mFrameNumber++;
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08004033 listener->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
Eino-Ville Talvala17543512014-08-06 14:32:02 -07004034 (*it)->mResultExtras);
Yin-Chia Yeh8684b7f2014-06-13 14:53:05 -07004035 }
4036 }
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07004037 mRequestQueue.clear();
Jinguang Dongb26e7a02016-11-14 16:04:02 +08004038
4039 Mutex::Autolock al(mTriggerMutex);
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07004040 mTriggerMap.clear();
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07004041 if (lastFrameNumber != NULL) {
4042 *lastFrameNumber = mRepeatingLastFrameNumber;
4043 }
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08004044 mRepeatingLastFrameNumber = hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES;
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -07004045 return OK;
4046}
4047
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004048status_t Camera3Device::RequestThread::flush() {
4049 ATRACE_CALL();
4050 Mutex::Autolock l(mFlushLock);
4051
Emilian Peev08dd2452017-04-06 16:55:14 +01004052 return mInterface->flush();
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004053}
4054
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004055void Camera3Device::RequestThread::setPaused(bool paused) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004056 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004057 Mutex::Autolock l(mPauseLock);
4058 mDoPause = paused;
4059 mDoPauseSignal.signal();
4060}
4061
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004062status_t Camera3Device::RequestThread::waitUntilRequestProcessed(
4063 int32_t requestId, nsecs_t timeout) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004064 ATRACE_CALL();
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004065 Mutex::Autolock l(mLatestRequestMutex);
4066 status_t res;
4067 while (mLatestRequestId != requestId) {
4068 nsecs_t startTime = systemTime();
4069
4070 res = mLatestRequestSignal.waitRelative(mLatestRequestMutex, timeout);
4071 if (res != OK) return res;
4072
4073 timeout -= (systemTime() - startTime);
4074 }
4075
4076 return OK;
4077}
4078
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004079void Camera3Device::RequestThread::requestExit() {
4080 // Call parent to set up shutdown
4081 Thread::requestExit();
4082 // The exit from any possible waits
4083 mDoPauseSignal.signal();
4084 mRequestSignal.signal();
Shuzhen Wang686f6442017-06-20 16:16:04 -07004085
4086 mRequestLatency.log("ProcessCaptureRequest latency histogram");
4087 mRequestLatency.reset();
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004088}
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004089
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07004090void Camera3Device::RequestThread::checkAndStopRepeatingRequest() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004091 ATRACE_CALL();
Yin-Chia Yeh473fad92016-05-23 15:54:41 -07004092 bool surfaceAbandoned = false;
4093 int64_t lastFrameNumber = 0;
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07004094 sp<NotificationListener> listener;
Yin-Chia Yeh473fad92016-05-23 15:54:41 -07004095 {
4096 Mutex::Autolock l(mRequestLock);
4097 // Check all streams needed by repeating requests are still valid. Otherwise, stop
4098 // repeating requests.
4099 for (const auto& request : mRepeatingRequests) {
4100 for (const auto& s : request->mOutputStreams) {
4101 if (s->isAbandoned()) {
4102 surfaceAbandoned = true;
4103 clearRepeatingRequestsLocked(&lastFrameNumber);
4104 break;
4105 }
4106 }
4107 if (surfaceAbandoned) {
4108 break;
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07004109 }
4110 }
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07004111 listener = mListener.promote();
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07004112 }
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07004113
4114 if (listener != NULL && surfaceAbandoned) {
4115 listener->notifyRepeatingRequestError(lastFrameNumber);
Yin-Chia Yeh473fad92016-05-23 15:54:41 -07004116 }
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07004117}
4118
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004119bool Camera3Device::RequestThread::sendRequestsBatch() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004120 ATRACE_CALL();
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004121 status_t res;
4122 size_t batchSize = mNextRequests.size();
4123 std::vector<camera3_capture_request_t*> requests(batchSize);
4124 uint32_t numRequestProcessed = 0;
4125 for (size_t i = 0; i < batchSize; i++) {
4126 requests[i] = &mNextRequests.editItemAt(i).halRequest;
4127 }
4128
4129 ATRACE_ASYNC_BEGIN("batch frame capture", mNextRequests[0].halRequest.frame_number);
4130 res = mInterface->processBatchCaptureRequests(requests, &numRequestProcessed);
4131
4132 bool triggerRemoveFailed = false;
4133 NextRequest& triggerFailedRequest = mNextRequests.editItemAt(0);
4134 for (size_t i = 0; i < numRequestProcessed; i++) {
4135 NextRequest& nextRequest = mNextRequests.editItemAt(i);
4136 nextRequest.submitted = true;
4137
4138
4139 // Update the latest request sent to HAL
4140 if (nextRequest.halRequest.settings != NULL) { // Don't update if they were unchanged
4141 Mutex::Autolock al(mLatestRequestMutex);
4142
4143 camera_metadata_t* cloned = clone_camera_metadata(nextRequest.halRequest.settings);
4144 mLatestRequest.acquire(cloned);
4145
4146 sp<Camera3Device> parent = mParent.promote();
4147 if (parent != NULL) {
4148 parent->monitorMetadata(TagMonitor::REQUEST,
4149 nextRequest.halRequest.frame_number,
4150 0, mLatestRequest);
4151 }
4152 }
4153
4154 if (nextRequest.halRequest.settings != NULL) {
4155 nextRequest.captureRequest->mSettings.unlock(nextRequest.halRequest.settings);
4156 }
4157
4158 if (!triggerRemoveFailed) {
4159 // Remove any previously queued triggers (after unlock)
4160 status_t removeTriggerRes = removeTriggers(mPrevRequest);
4161 if (removeTriggerRes != OK) {
4162 triggerRemoveFailed = true;
4163 triggerFailedRequest = nextRequest;
4164 }
4165 }
4166 }
4167
4168 if (triggerRemoveFailed) {
4169 SET_ERR("RequestThread: Unable to remove triggers "
4170 "(capture request %d, HAL device: %s (%d)",
4171 triggerFailedRequest.halRequest.frame_number, strerror(-res), res);
4172 cleanUpFailedRequests(/*sendRequestError*/ false);
4173 return false;
4174 }
4175
4176 if (res != OK) {
4177 // Should only get a failure here for malformed requests or device-level
4178 // errors, so consider all errors fatal. Bad metadata failures should
4179 // come through notify.
4180 SET_ERR("RequestThread: Unable to submit capture request %d to HAL device: %s (%d)",
4181 mNextRequests[numRequestProcessed].halRequest.frame_number,
4182 strerror(-res), res);
4183 cleanUpFailedRequests(/*sendRequestError*/ false);
4184 return false;
4185 }
4186 return true;
4187}
4188
4189bool Camera3Device::RequestThread::sendRequestsOneByOne() {
4190 status_t res;
4191
4192 for (auto& nextRequest : mNextRequests) {
4193 // Submit request and block until ready for next one
4194 ATRACE_ASYNC_BEGIN("frame capture", nextRequest.halRequest.frame_number);
4195 res = mInterface->processCaptureRequest(&nextRequest.halRequest);
4196
4197 if (res != OK) {
4198 // Should only get a failure here for malformed requests or device-level
4199 // errors, so consider all errors fatal. Bad metadata failures should
4200 // come through notify.
4201 SET_ERR("RequestThread: Unable to submit capture request %d to HAL"
4202 " device: %s (%d)", nextRequest.halRequest.frame_number, strerror(-res),
4203 res);
4204 cleanUpFailedRequests(/*sendRequestError*/ false);
4205 return false;
4206 }
4207
4208 // Mark that the request has be submitted successfully.
4209 nextRequest.submitted = true;
4210
4211 // Update the latest request sent to HAL
4212 if (nextRequest.halRequest.settings != NULL) { // Don't update if they were unchanged
4213 Mutex::Autolock al(mLatestRequestMutex);
4214
4215 camera_metadata_t* cloned = clone_camera_metadata(nextRequest.halRequest.settings);
4216 mLatestRequest.acquire(cloned);
4217
4218 sp<Camera3Device> parent = mParent.promote();
4219 if (parent != NULL) {
4220 parent->monitorMetadata(TagMonitor::REQUEST, nextRequest.halRequest.frame_number,
4221 0, mLatestRequest);
4222 }
4223 }
4224
4225 if (nextRequest.halRequest.settings != NULL) {
4226 nextRequest.captureRequest->mSettings.unlock(nextRequest.halRequest.settings);
4227 }
4228
4229 // Remove any previously queued triggers (after unlock)
4230 res = removeTriggers(mPrevRequest);
4231 if (res != OK) {
4232 SET_ERR("RequestThread: Unable to remove triggers "
4233 "(capture request %d, HAL device: %s (%d)",
4234 nextRequest.halRequest.frame_number, strerror(-res), res);
4235 cleanUpFailedRequests(/*sendRequestError*/ false);
4236 return false;
4237 }
4238 }
4239 return true;
4240}
4241
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07004242nsecs_t Camera3Device::RequestThread::calculateMaxExpectedDuration(const camera_metadata_t *request) {
4243 nsecs_t maxExpectedDuration = kDefaultExpectedDuration;
4244 camera_metadata_ro_entry_t e = camera_metadata_ro_entry_t();
4245 find_camera_metadata_ro_entry(request,
4246 ANDROID_CONTROL_AE_MODE,
4247 &e);
4248 if (e.count == 0) return maxExpectedDuration;
4249
4250 switch (e.data.u8[0]) {
4251 case ANDROID_CONTROL_AE_MODE_OFF:
4252 find_camera_metadata_ro_entry(request,
4253 ANDROID_SENSOR_EXPOSURE_TIME,
4254 &e);
4255 if (e.count > 0) {
4256 maxExpectedDuration = e.data.i64[0];
4257 }
4258 find_camera_metadata_ro_entry(request,
4259 ANDROID_SENSOR_FRAME_DURATION,
4260 &e);
4261 if (e.count > 0) {
4262 maxExpectedDuration = std::max(e.data.i64[0], maxExpectedDuration);
4263 }
4264 break;
4265 default:
4266 find_camera_metadata_ro_entry(request,
4267 ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
4268 &e);
4269 if (e.count > 1) {
4270 maxExpectedDuration = 1e9 / e.data.u8[0];
4271 }
4272 break;
4273 }
4274
4275 return maxExpectedDuration;
4276}
4277
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004278bool Camera3Device::RequestThread::updateSessionParameters(const CameraMetadata& settings) {
4279 ATRACE_CALL();
4280 bool updatesDetected = false;
4281
4282 for (auto tag : mSessionParamKeys) {
4283 camera_metadata_ro_entry entry = settings.find(tag);
4284 camera_metadata_entry lastEntry = mLatestSessionParams.find(tag);
4285
4286 if (entry.count > 0) {
4287 bool isDifferent = false;
4288 if (lastEntry.count > 0) {
4289 // Have a last value, compare to see if changed
4290 if (lastEntry.type == entry.type &&
4291 lastEntry.count == entry.count) {
4292 // Same type and count, compare values
4293 size_t bytesPerValue = camera_metadata_type_size[lastEntry.type];
4294 size_t entryBytes = bytesPerValue * lastEntry.count;
4295 int cmp = memcmp(entry.data.u8, lastEntry.data.u8, entryBytes);
4296 if (cmp != 0) {
4297 isDifferent = true;
4298 }
4299 } else {
4300 // Count or type has changed
4301 isDifferent = true;
4302 }
4303 } else {
4304 // No last entry, so always consider to be different
4305 isDifferent = true;
4306 }
4307
4308 if (isDifferent) {
4309 ALOGV("%s: Session parameter tag id %d changed", __FUNCTION__, tag);
4310 mLatestSessionParams.update(entry);
4311 updatesDetected = true;
4312 }
4313 } else if (lastEntry.count > 0) {
4314 // Value has been removed
4315 ALOGV("%s: Session parameter tag id %d removed", __FUNCTION__, tag);
4316 mLatestSessionParams.erase(tag);
4317 updatesDetected = true;
4318 }
4319 }
4320
4321 return updatesDetected;
4322}
4323
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004324bool Camera3Device::RequestThread::threadLoop() {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004325 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004326 status_t res;
4327
4328 // Handle paused state.
4329 if (waitIfPaused()) {
4330 return true;
4331 }
4332
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004333 // Wait for the next batch of requests.
4334 waitForNextRequestBatch();
4335 if (mNextRequests.size() == 0) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004336 return true;
4337 }
4338
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004339 // Get the latest request ID, if any
4340 int latestRequestId;
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004341 camera_metadata_entry_t requestIdEntry = mNextRequests[mNextRequests.size() - 1].
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004342 captureRequest->mSettings.find(ANDROID_REQUEST_ID);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004343 if (requestIdEntry.count > 0) {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004344 latestRequestId = requestIdEntry.data.i32[0];
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004345 } else {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004346 ALOGW("%s: Did not have android.request.id set in the request.", __FUNCTION__);
4347 latestRequestId = NAME_NOT_FOUND;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004348 }
4349
Emilian Peevac3ce6c2017-12-12 15:27:02 +00004350 // 'mNextRequests' will at this point contain either a set of HFR batched requests
4351 // or a single request from streaming or burst. In either case the first element
4352 // should contain the latest camera settings that we need to check for any session
4353 // parameter updates.
4354 if (updateSessionParameters(mNextRequests[0].captureRequest->mSettings)) {
4355 res = OK;
4356
4357 //Input stream buffers are already acquired at this point so an input stream
4358 //will not be able to move to idle state unless we force it.
4359 if (mNextRequests[0].captureRequest->mInputStream != nullptr) {
4360 res = mNextRequests[0].captureRequest->mInputStream->forceToIdle();
4361 if (res != OK) {
4362 ALOGE("%s: Failed to force idle input stream: %d", __FUNCTION__, res);
4363 cleanUpFailedRequests(/*sendRequestError*/ false);
4364 return false;
4365 }
4366 }
4367
4368 if (res == OK) {
4369 sp<StatusTracker> statusTracker = mStatusTracker.promote();
4370 if (statusTracker != 0) {
4371 statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);
4372
4373 sp<Camera3Device> parent = mParent.promote();
4374 if (parent != nullptr) {
4375 mReconfigured |= parent->reconfigureCamera(mLatestSessionParams);
4376 }
4377
4378 statusTracker->markComponentActive(mStatusId);
4379 setPaused(false);
4380 }
4381
4382 if (mNextRequests[0].captureRequest->mInputStream != nullptr) {
4383 mNextRequests[0].captureRequest->mInputStream->restoreConfiguredState();
4384 if (res != OK) {
4385 ALOGE("%s: Failed to restore configured input stream: %d", __FUNCTION__, res);
4386 cleanUpFailedRequests(/*sendRequestError*/ false);
4387 return false;
4388 }
4389 }
4390 }
4391 }
4392
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004393 // Prepare a batch of HAL requests and output buffers.
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004394 res = prepareHalRequests();
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004395 if (res == TIMED_OUT) {
4396 // Not a fatal error if getting output buffers time out.
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004397 cleanUpFailedRequests(/*sendRequestError*/ true);
Chien-Yu Chene8c535e2016-04-14 12:18:26 -07004398 // Check if any stream is abandoned.
4399 checkAndStopRepeatingRequest();
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004400 return true;
4401 } else if (res != OK) {
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004402 cleanUpFailedRequests(/*sendRequestError*/ false);
Eino-Ville Talvala42368d92013-04-09 14:13:50 -07004403 return false;
4404 }
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004405
Zhijun Hecc27e112013-10-03 16:12:43 -07004406 // Inform waitUntilRequestProcessed thread of a new request ID
4407 {
4408 Mutex::Autolock al(mLatestRequestMutex);
4409
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004410 mLatestRequestId = latestRequestId;
Zhijun Hecc27e112013-10-03 16:12:43 -07004411 mLatestRequestSignal.signal();
4412 }
4413
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004414 // Submit a batch of requests to HAL.
4415 // Use flush lock only when submitting multilple requests in a batch.
4416 // TODO: The problem with flush lock is flush() will be blocked by process_capture_request()
4417 // which may take a long time to finish so synchronizing flush() and
4418 // process_capture_request() defeats the purpose of cancelling requests ASAP with flush().
4419 // For now, only synchronize for high speed recording and we should figure something out for
4420 // removing the synchronization.
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004421 bool useFlushLock = mNextRequests.size() > 1;
Eino-Ville Talvala17a61ad2013-06-03 16:53:32 -07004422
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004423 if (useFlushLock) {
4424 mFlushLock.lock();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004425 }
4426
Zhijun Hef0645c12016-08-02 00:58:11 -07004427 ALOGVV("%s: %d: submitting %zu requests in a batch.", __FUNCTION__, __LINE__,
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004428 mNextRequests.size());
Igor Murashkin1e479c02013-09-06 16:55:14 -07004429
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004430 bool submitRequestSuccess = false;
Shuzhen Wang686f6442017-06-20 16:16:04 -07004431 nsecs_t tRequestStart = systemTime(SYSTEM_TIME_MONOTONIC);
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004432 if (mInterface->supportBatchRequest()) {
4433 submitRequestSuccess = sendRequestsBatch();
4434 } else {
4435 submitRequestSuccess = sendRequestsOneByOne();
Igor Murashkin1e479c02013-09-06 16:55:14 -07004436 }
Shuzhen Wang686f6442017-06-20 16:16:04 -07004437 nsecs_t tRequestEnd = systemTime(SYSTEM_TIME_MONOTONIC);
4438 mRequestLatency.add(tRequestStart, tRequestEnd);
Igor Murashkin1e479c02013-09-06 16:55:14 -07004439
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004440 if (useFlushLock) {
4441 mFlushLock.unlock();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004442 }
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004443
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004444 // Unset as current request
4445 {
4446 Mutex::Autolock l(mRequestLock);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004447 mNextRequests.clear();
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004448 }
4449
Yin-Chia Yeh94c68e02017-03-06 14:09:44 -08004450 return submitRequestSuccess;
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004451}
4452
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004453status_t Camera3Device::RequestThread::prepareHalRequests() {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004454 ATRACE_CALL();
4455
Shuzhen Wang4a472662017-02-26 23:29:04 -08004456 for (size_t i = 0; i < mNextRequests.size(); i++) {
4457 auto& nextRequest = mNextRequests.editItemAt(i);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004458 sp<CaptureRequest> captureRequest = nextRequest.captureRequest;
4459 camera3_capture_request_t* halRequest = &nextRequest.halRequest;
4460 Vector<camera3_stream_buffer_t>* outputBuffers = &nextRequest.outputBuffers;
4461
4462 // Prepare a request to HAL
4463 halRequest->frame_number = captureRequest->mResultExtras.frameNumber;
4464
4465 // Insert any queued triggers (before metadata is locked)
4466 status_t res = insertTriggers(captureRequest);
4467
4468 if (res < 0) {
4469 SET_ERR("RequestThread: Unable to insert triggers "
4470 "(capture request %d, HAL device: %s (%d)",
4471 halRequest->frame_number, strerror(-res), res);
4472 return INVALID_OPERATION;
4473 }
4474 int triggerCount = res;
4475 bool triggersMixedIn = (triggerCount > 0 || mPrevTriggers > 0);
4476 mPrevTriggers = triggerCount;
4477
4478 // If the request is the same as last, or we had triggers last time
4479 if (mPrevRequest != captureRequest || triggersMixedIn) {
4480 /**
4481 * HAL workaround:
4482 * Insert a dummy trigger ID if a trigger is set but no trigger ID is
4483 */
4484 res = addDummyTriggerIds(captureRequest);
4485 if (res != OK) {
4486 SET_ERR("RequestThread: Unable to insert dummy trigger IDs "
4487 "(capture request %d, HAL device: %s (%d)",
4488 halRequest->frame_number, strerror(-res), res);
4489 return INVALID_OPERATION;
4490 }
4491
4492 /**
4493 * The request should be presorted so accesses in HAL
4494 * are O(logn). Sidenote, sorting a sorted metadata is nop.
4495 */
4496 captureRequest->mSettings.sort();
4497 halRequest->settings = captureRequest->mSettings.getAndLock();
4498 mPrevRequest = captureRequest;
4499 ALOGVV("%s: Request settings are NEW", __FUNCTION__);
4500
4501 IF_ALOGV() {
4502 camera_metadata_ro_entry_t e = camera_metadata_ro_entry_t();
4503 find_camera_metadata_ro_entry(
4504 halRequest->settings,
4505 ANDROID_CONTROL_AF_TRIGGER,
4506 &e
4507 );
4508 if (e.count > 0) {
4509 ALOGV("%s: Request (frame num %d) had AF trigger 0x%x",
4510 __FUNCTION__,
4511 halRequest->frame_number,
4512 e.data.u8[0]);
4513 }
4514 }
4515 } else {
4516 // leave request.settings NULL to indicate 'reuse latest given'
4517 ALOGVV("%s: Request settings are REUSED",
4518 __FUNCTION__);
4519 }
4520
4521 uint32_t totalNumBuffers = 0;
4522
4523 // Fill in buffers
4524 if (captureRequest->mInputStream != NULL) {
4525 halRequest->input_buffer = &captureRequest->mInputBuffer;
4526 totalNumBuffers += 1;
4527 } else {
4528 halRequest->input_buffer = NULL;
4529 }
4530
4531 outputBuffers->insertAt(camera3_stream_buffer_t(), 0,
4532 captureRequest->mOutputStreams.size());
4533 halRequest->output_buffers = outputBuffers->array();
Shuzhen Wang4a472662017-02-26 23:29:04 -08004534 for (size_t j = 0; j < captureRequest->mOutputStreams.size(); j++) {
4535 sp<Camera3OutputStreamInterface> outputStream = captureRequest->mOutputStreams.editItemAt(j);
Chien-Yu Chenc66969b2016-05-19 16:37:51 -07004536
4537 // Prepare video buffers for high speed recording on the first video request.
4538 if (mPrepareVideoStream && outputStream->isVideoStream()) {
4539 // Only try to prepare video stream on the first video request.
4540 mPrepareVideoStream = false;
4541
4542 res = outputStream->startPrepare(Camera3StreamInterface::ALLOCATE_PIPELINE_MAX);
4543 while (res == NOT_ENOUGH_DATA) {
4544 res = outputStream->prepareNextBuffer();
4545 }
4546 if (res != OK) {
4547 ALOGW("%s: Preparing video buffers for high speed failed: %s (%d)",
4548 __FUNCTION__, strerror(-res), res);
4549 outputStream->cancelPrepare();
4550 }
4551 }
4552
Shuzhen Wang4a472662017-02-26 23:29:04 -08004553 res = outputStream->getBuffer(&outputBuffers->editItemAt(j),
4554 captureRequest->mOutputSurfaces[j]);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004555 if (res != OK) {
4556 // Can't get output buffer from gralloc queue - this could be due to
4557 // abandoned queue or other consumer misbehavior, so not a fatal
4558 // error
4559 ALOGE("RequestThread: Can't get output buffer, skipping request:"
4560 " %s (%d)", strerror(-res), res);
4561
4562 return TIMED_OUT;
4563 }
4564 halRequest->num_output_buffers++;
Shuzhen Wang0129d522016-10-30 22:43:41 -07004565
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004566 }
4567 totalNumBuffers += halRequest->num_output_buffers;
4568
4569 // Log request in the in-flight queue
4570 sp<Camera3Device> parent = mParent.promote();
4571 if (parent == NULL) {
4572 // Should not happen, and nowhere to send errors to, so just log it
4573 CLOGE("RequestThread: Parent is gone");
4574 return INVALID_OPERATION;
4575 }
Shuzhen Wang4a472662017-02-26 23:29:04 -08004576
4577 // If this request list is for constrained high speed recording (not
4578 // preview), and the current request is not the last one in the batch,
4579 // do not send callback to the app.
4580 bool hasCallback = true;
4581 if (mNextRequests[0].captureRequest->mBatchSize > 1 && i != mNextRequests.size()-1) {
4582 hasCallback = false;
4583 }
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004584 res = parent->registerInFlight(halRequest->frame_number,
4585 totalNumBuffers, captureRequest->mResultExtras,
4586 /*hasInput*/halRequest->input_buffer != NULL,
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07004587 hasCallback,
4588 calculateMaxExpectedDuration(halRequest->settings));
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004589 ALOGVV("%s: registered in flight requestId = %" PRId32 ", frameNumber = %" PRId64
4590 ", burstId = %" PRId32 ".",
4591 __FUNCTION__,
4592 captureRequest->mResultExtras.requestId, captureRequest->mResultExtras.frameNumber,
4593 captureRequest->mResultExtras.burstId);
4594 if (res != OK) {
4595 SET_ERR("RequestThread: Unable to register new in-flight request:"
4596 " %s (%d)", strerror(-res), res);
4597 return INVALID_OPERATION;
4598 }
4599 }
4600
4601 return OK;
4602}
4603
Igor Murashkin1e479c02013-09-06 16:55:14 -07004604CameraMetadata Camera3Device::RequestThread::getLatestRequest() const {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004605 ATRACE_CALL();
Igor Murashkin1e479c02013-09-06 16:55:14 -07004606 Mutex::Autolock al(mLatestRequestMutex);
4607
4608 ALOGV("RequestThread::%s", __FUNCTION__);
4609
4610 return mLatestRequest;
4611}
4612
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07004613bool Camera3Device::RequestThread::isStreamPending(
4614 sp<Camera3StreamInterface>& stream) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004615 ATRACE_CALL();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07004616 Mutex::Autolock l(mRequestLock);
4617
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004618 for (const auto& nextRequest : mNextRequests) {
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004619 if (!nextRequest.submitted) {
4620 for (const auto& s : nextRequest.captureRequest->mOutputStreams) {
4621 if (stream == s) return true;
4622 }
4623 if (stream == nextRequest.captureRequest->mInputStream) return true;
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004624 }
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004625 }
4626
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07004627 for (const auto& request : mRequestQueue) {
4628 for (const auto& s : request->mOutputStreams) {
4629 if (stream == s) return true;
4630 }
4631 if (stream == request->mInputStream) return true;
4632 }
4633
4634 for (const auto& request : mRepeatingRequests) {
4635 for (const auto& s : request->mOutputStreams) {
4636 if (stream == s) return true;
4637 }
4638 if (stream == request->mInputStream) return true;
4639 }
4640
4641 return false;
4642}
Jianing Weicb0652e2014-03-12 18:29:36 -07004643
Emilian Peev40ead602017-09-26 15:46:36 +01004644bool Camera3Device::RequestThread::isOutputSurfacePending(int streamId, size_t surfaceId) {
4645 ATRACE_CALL();
4646 Mutex::Autolock l(mRequestLock);
4647
4648 for (const auto& nextRequest : mNextRequests) {
4649 for (const auto& s : nextRequest.captureRequest->mOutputSurfaces) {
4650 if (s.first == streamId) {
4651 const auto &it = std::find(s.second.begin(), s.second.end(), surfaceId);
4652 if (it != s.second.end()) {
4653 return true;
4654 }
4655 }
4656 }
4657 }
4658
4659 for (const auto& request : mRequestQueue) {
4660 for (const auto& s : request->mOutputSurfaces) {
4661 if (s.first == streamId) {
4662 const auto &it = std::find(s.second.begin(), s.second.end(), surfaceId);
4663 if (it != s.second.end()) {
4664 return true;
4665 }
4666 }
4667 }
4668 }
4669
4670 for (const auto& request : mRepeatingRequests) {
4671 for (const auto& s : request->mOutputSurfaces) {
4672 if (s.first == streamId) {
4673 const auto &it = std::find(s.second.begin(), s.second.end(), surfaceId);
4674 if (it != s.second.end()) {
4675 return true;
4676 }
4677 }
4678 }
4679 }
4680
4681 return false;
4682}
4683
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07004684nsecs_t Camera3Device::getExpectedInFlightDuration() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004685 ATRACE_CALL();
Yin-Chia Yeh598fc602017-07-24 11:37:23 -07004686 Mutex::Autolock al(mInFlightLock);
Eino-Ville Talvala10bd57e2017-06-23 16:22:44 -07004687 return mExpectedInflightDuration > kMinInflightDuration ?
4688 mExpectedInflightDuration : kMinInflightDuration;
4689}
4690
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004691void Camera3Device::RequestThread::cleanUpFailedRequests(bool sendRequestError) {
4692 if (mNextRequests.empty()) {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004693 return;
4694 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004695
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004696 for (auto& nextRequest : mNextRequests) {
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004697 // Skip the ones that have been submitted successfully.
4698 if (nextRequest.submitted) {
4699 continue;
4700 }
4701
4702 sp<CaptureRequest> captureRequest = nextRequest.captureRequest;
4703 camera3_capture_request_t* halRequest = &nextRequest.halRequest;
4704 Vector<camera3_stream_buffer_t>* outputBuffers = &nextRequest.outputBuffers;
4705
4706 if (halRequest->settings != NULL) {
4707 captureRequest->mSettings.unlock(halRequest->settings);
4708 }
4709
4710 if (captureRequest->mInputStream != NULL) {
4711 captureRequest->mInputBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
4712 captureRequest->mInputStream->returnInputBuffer(captureRequest->mInputBuffer);
4713 }
4714
4715 for (size_t i = 0; i < halRequest->num_output_buffers; i++) {
Emilian Peevc58cf4c2017-05-11 17:23:41 +01004716 //Buffers that failed processing could still have
4717 //valid acquire fence.
4718 int acquireFence = (*outputBuffers)[i].acquire_fence;
4719 if (0 <= acquireFence) {
4720 close(acquireFence);
4721 outputBuffers->editItemAt(i).acquire_fence = -1;
4722 }
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004723 outputBuffers->editItemAt(i).status = CAMERA3_BUFFER_STATUS_ERROR;
4724 captureRequest->mOutputStreams.editItemAt(i)->returnBuffer((*outputBuffers)[i], 0);
4725 }
4726
4727 if (sendRequestError) {
4728 Mutex::Autolock l(mRequestLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07004729 sp<NotificationListener> listener = mListener.promote();
4730 if (listener != NULL) {
4731 listener->notifyError(
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08004732 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004733 captureRequest->mResultExtras);
4734 }
4735 }
Shuzhen Wangcadb3302016-11-04 14:17:56 -07004736
4737 // Remove yet-to-be submitted inflight request from inflightMap
4738 {
4739 sp<Camera3Device> parent = mParent.promote();
4740 if (parent != NULL) {
4741 Mutex::Autolock l(parent->mInFlightLock);
4742 ssize_t idx = parent->mInFlightMap.indexOfKey(captureRequest->mResultExtras.frameNumber);
4743 if (idx >= 0) {
4744 ALOGV("%s: Remove inflight request from queue: frameNumber %" PRId64,
4745 __FUNCTION__, captureRequest->mResultExtras.frameNumber);
4746 parent->removeInFlightMapEntryLocked(idx);
4747 }
4748 }
4749 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004750 }
Eino-Ville Talvalae74c2282015-05-27 14:46:23 -07004751
4752 Mutex::Autolock l(mRequestLock);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004753 mNextRequests.clear();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004754}
4755
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004756void Camera3Device::RequestThread::waitForNextRequestBatch() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004757 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004758 // Optimized a bit for the simple steady-state case (single repeating
4759 // request), to avoid putting that request in the queue temporarily.
4760 Mutex::Autolock l(mRequestLock);
4761
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004762 assert(mNextRequests.empty());
4763
4764 NextRequest nextRequest;
4765 nextRequest.captureRequest = waitForNextRequestLocked();
4766 if (nextRequest.captureRequest == nullptr) {
4767 return;
4768 }
4769
4770 nextRequest.halRequest = camera3_capture_request_t();
4771 nextRequest.submitted = false;
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004772 mNextRequests.add(nextRequest);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004773
4774 // Wait for additional requests
4775 const size_t batchSize = nextRequest.captureRequest->mBatchSize;
4776
4777 for (size_t i = 1; i < batchSize; i++) {
4778 NextRequest additionalRequest;
4779 additionalRequest.captureRequest = waitForNextRequestLocked();
4780 if (additionalRequest.captureRequest == nullptr) {
4781 break;
4782 }
4783
4784 additionalRequest.halRequest = camera3_capture_request_t();
4785 additionalRequest.submitted = false;
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004786 mNextRequests.add(additionalRequest);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004787 }
4788
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004789 if (mNextRequests.size() < batchSize) {
Eino-Ville Talvalad309fb92015-11-25 12:12:45 -08004790 ALOGE("RequestThread: only get %zu out of %zu requests. Skipping requests.",
Chien-Yu Chen57ea2922015-09-04 12:58:56 -07004791 mNextRequests.size(), batchSize);
4792 cleanUpFailedRequests(/*sendRequestError*/true);
Chien-Yu Chen85a64552015-08-28 15:46:12 -07004793 }
4794
4795 return;
4796}
4797
4798sp<Camera3Device::CaptureRequest>
4799 Camera3Device::RequestThread::waitForNextRequestLocked() {
4800 status_t res;
4801 sp<CaptureRequest> nextRequest;
4802
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004803 while (mRequestQueue.empty()) {
4804 if (!mRepeatingRequests.empty()) {
4805 // Always atomically enqueue all requests in a repeating request
4806 // list. Guarantees a complete in-sequence set of captures to
4807 // application.
4808 const RequestList &requests = mRepeatingRequests;
4809 RequestList::const_iterator firstRequest =
4810 requests.begin();
4811 nextRequest = *firstRequest;
4812 mRequestQueue.insert(mRequestQueue.end(),
4813 ++firstRequest,
4814 requests.end());
4815 // No need to wait any longer
Jianing Weicb0652e2014-03-12 18:29:36 -07004816
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07004817 mRepeatingLastFrameNumber = mFrameNumber + requests.size() - 1;
Jianing Weicb0652e2014-03-12 18:29:36 -07004818
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004819 break;
4820 }
4821
4822 res = mRequestSignal.waitRelative(mRequestLock, kRequestTimeout);
4823
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004824 if ((mRequestQueue.empty() && mRepeatingRequests.empty()) ||
4825 exitPending()) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004826 Mutex::Autolock pl(mPauseLock);
4827 if (mPaused == false) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004828 ALOGV("%s: RequestThread: Going idle", __FUNCTION__);
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004829 mPaused = true;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004830 // Let the tracker know
4831 sp<StatusTracker> statusTracker = mStatusTracker.promote();
4832 if (statusTracker != 0) {
4833 statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);
4834 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004835 }
4836 // Stop waiting for now and let thread management happen
4837 return NULL;
4838 }
4839 }
4840
4841 if (nextRequest == NULL) {
4842 // Don't have a repeating request already in hand, so queue
4843 // must have an entry now.
4844 RequestList::iterator firstRequest =
4845 mRequestQueue.begin();
4846 nextRequest = *firstRequest;
4847 mRequestQueue.erase(firstRequest);
Shuzhen Wang9d066012016-09-30 11:30:20 -07004848 if (mRequestQueue.empty() && !nextRequest->mRepeating) {
4849 sp<NotificationListener> listener = mListener.promote();
4850 if (listener != NULL) {
4851 listener->notifyRequestQueueEmpty();
4852 }
4853 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004854 }
4855
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07004856 // In case we've been unpaused by setPaused clearing mDoPause, need to
4857 // update internal pause state (capture/setRepeatingRequest unpause
4858 // directly).
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004859 Mutex::Autolock pl(mPauseLock);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004860 if (mPaused) {
4861 ALOGV("%s: RequestThread: Unpaused", __FUNCTION__);
4862 sp<StatusTracker> statusTracker = mStatusTracker.promote();
4863 if (statusTracker != 0) {
4864 statusTracker->markComponentActive(mStatusId);
4865 }
4866 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004867 mPaused = false;
4868
4869 // Check if we've reconfigured since last time, and reset the preview
4870 // request if so. Can't use 'NULL request == repeat' across configure calls.
4871 if (mReconfigured) {
4872 mPrevRequest.clear();
4873 mReconfigured = false;
4874 }
4875
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07004876 if (nextRequest != NULL) {
4877 nextRequest->mResultExtras.frameNumber = mFrameNumber++;
Yin-Chia Yehc00a25c2014-08-21 14:27:44 -07004878 nextRequest->mResultExtras.afTriggerId = mCurrentAfTriggerId;
4879 nextRequest->mResultExtras.precaptureTriggerId = mCurrentPreCaptureTriggerId;
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07004880
4881 // Since RequestThread::clear() removes buffers from the input stream,
4882 // get the right buffer here before unlocking mRequestLock
4883 if (nextRequest->mInputStream != NULL) {
4884 res = nextRequest->mInputStream->getInputBuffer(&nextRequest->mInputBuffer);
4885 if (res != OK) {
4886 // Can't get input buffer from gralloc queue - this could be due to
4887 // disconnected queue or other producer misbehavior, so not a fatal
4888 // error
4889 ALOGE("%s: Can't get input buffer, skipping request:"
4890 " %s (%d)", __FUNCTION__, strerror(-res), res);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07004891
4892 sp<NotificationListener> listener = mListener.promote();
4893 if (listener != NULL) {
4894 listener->notifyError(
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -08004895 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
Chien-Yu Chenc2adf482015-05-27 14:27:49 -07004896 nextRequest->mResultExtras);
4897 }
4898 return NULL;
4899 }
4900 }
Jianing Wei2d6bb3f2014-04-11 10:00:31 -07004901 }
Chien-Yu Chend196d612015-06-22 19:49:01 -07004902
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004903 return nextRequest;
4904}
4905
4906bool Camera3Device::RequestThread::waitIfPaused() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004907 ATRACE_CALL();
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004908 status_t res;
4909 Mutex::Autolock l(mPauseLock);
4910 while (mDoPause) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004911 if (mPaused == false) {
4912 mPaused = true;
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004913 ALOGV("%s: RequestThread: Paused", __FUNCTION__);
4914 // Let the tracker know
4915 sp<StatusTracker> statusTracker = mStatusTracker.promote();
4916 if (statusTracker != 0) {
4917 statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);
4918 }
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004919 }
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004920
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004921 res = mDoPauseSignal.waitRelative(mPauseLock, kRequestTimeout);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004922 if (res == TIMED_OUT || exitPending()) {
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08004923 return true;
4924 }
4925 }
4926 // We don't set mPaused to false here, because waitForNextRequest needs
4927 // to further manage the paused state in case of starvation.
4928 return false;
4929}
4930
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07004931void Camera3Device::RequestThread::unpauseForNewRequests() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004932 ATRACE_CALL();
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07004933 // With work to do, mark thread as unpaused.
4934 // If paused by request (setPaused), don't resume, to avoid
4935 // extra signaling/waiting overhead to waitUntilPaused
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004936 mRequestSignal.signal();
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07004937 Mutex::Autolock p(mPauseLock);
4938 if (!mDoPause) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -07004939 ALOGV("%s: RequestThread: Going active", __FUNCTION__);
4940 if (mPaused) {
4941 sp<StatusTracker> statusTracker = mStatusTracker.promote();
4942 if (statusTracker != 0) {
4943 statusTracker->markComponentActive(mStatusId);
4944 }
4945 }
Eino-Ville Talvala26fe6c72013-08-29 12:46:18 -07004946 mPaused = false;
4947 }
4948}
4949
Eino-Ville Talvalab2058d12013-04-09 13:49:56 -07004950void Camera3Device::RequestThread::setErrorState(const char *fmt, ...) {
4951 sp<Camera3Device> parent = mParent.promote();
4952 if (parent != NULL) {
4953 va_list args;
4954 va_start(args, fmt);
4955
4956 parent->setErrorStateV(fmt, args);
4957
4958 va_end(args);
4959 }
4960}
4961
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004962status_t Camera3Device::RequestThread::insertTriggers(
4963 const sp<CaptureRequest> &request) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07004964 ATRACE_CALL();
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004965 Mutex::Autolock al(mTriggerMutex);
4966
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07004967 sp<Camera3Device> parent = mParent.promote();
4968 if (parent == NULL) {
4969 CLOGE("RequestThread: Parent is gone");
4970 return DEAD_OBJECT;
4971 }
4972
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004973 CameraMetadata &metadata = request->mSettings;
4974 size_t count = mTriggerMap.size();
4975
4976 for (size_t i = 0; i < count; ++i) {
4977 RequestTrigger trigger = mTriggerMap.valueAt(i);
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004978 uint32_t tag = trigger.metadataTag;
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07004979
4980 if (tag == ANDROID_CONTROL_AF_TRIGGER_ID || tag == ANDROID_CONTROL_AE_PRECAPTURE_ID) {
4981 bool isAeTrigger = (trigger.metadataTag == ANDROID_CONTROL_AE_PRECAPTURE_ID);
4982 uint32_t triggerId = static_cast<uint32_t>(trigger.entryValue);
Yin-Chia Yehc00a25c2014-08-21 14:27:44 -07004983 if (isAeTrigger) {
4984 request->mResultExtras.precaptureTriggerId = triggerId;
4985 mCurrentPreCaptureTriggerId = triggerId;
4986 } else {
4987 request->mResultExtras.afTriggerId = triggerId;
4988 mCurrentAfTriggerId = triggerId;
4989 }
Emilian Peev7e25e5e2017-04-07 15:48:49 +01004990 continue;
Yin-Chia Yeh741ace82014-06-23 14:07:56 -07004991 }
4992
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07004993 camera_metadata_entry entry = metadata.find(tag);
4994
4995 if (entry.count > 0) {
4996 /**
4997 * Already has an entry for this trigger in the request.
4998 * Rewrite it with our requested trigger value.
4999 */
5000 RequestTrigger oldTrigger = trigger;
5001
5002 oldTrigger.entryValue = entry.data.u8[0];
5003
5004 mTriggerReplacedMap.add(tag, oldTrigger);
5005 } else {
5006 /**
5007 * More typical, no trigger entry, so we just add it
5008 */
5009 mTriggerRemovedMap.add(tag, trigger);
5010 }
5011
5012 status_t res;
5013
5014 switch (trigger.getTagType()) {
5015 case TYPE_BYTE: {
5016 uint8_t entryValue = static_cast<uint8_t>(trigger.entryValue);
5017 res = metadata.update(tag,
5018 &entryValue,
5019 /*count*/1);
5020 break;
5021 }
5022 case TYPE_INT32:
5023 res = metadata.update(tag,
5024 &trigger.entryValue,
5025 /*count*/1);
5026 break;
5027 default:
5028 ALOGE("%s: Type not supported: 0x%x",
5029 __FUNCTION__,
5030 trigger.getTagType());
5031 return INVALID_OPERATION;
5032 }
5033
5034 if (res != OK) {
5035 ALOGE("%s: Failed to update request metadata with trigger tag %s"
5036 ", value %d", __FUNCTION__, trigger.getTagName(),
5037 trigger.entryValue);
5038 return res;
5039 }
5040
5041 ALOGV("%s: Mixed in trigger %s, value %d", __FUNCTION__,
5042 trigger.getTagName(),
5043 trigger.entryValue);
5044 }
5045
5046 mTriggerMap.clear();
5047
5048 return count;
5049}
5050
5051status_t Camera3Device::RequestThread::removeTriggers(
5052 const sp<CaptureRequest> &request) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005053 ATRACE_CALL();
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005054 Mutex::Autolock al(mTriggerMutex);
5055
5056 CameraMetadata &metadata = request->mSettings;
5057
5058 /**
5059 * Replace all old entries with their old values.
5060 */
5061 for (size_t i = 0; i < mTriggerReplacedMap.size(); ++i) {
5062 RequestTrigger trigger = mTriggerReplacedMap.valueAt(i);
5063
5064 status_t res;
5065
5066 uint32_t tag = trigger.metadataTag;
5067 switch (trigger.getTagType()) {
5068 case TYPE_BYTE: {
5069 uint8_t entryValue = static_cast<uint8_t>(trigger.entryValue);
5070 res = metadata.update(tag,
5071 &entryValue,
5072 /*count*/1);
5073 break;
5074 }
5075 case TYPE_INT32:
5076 res = metadata.update(tag,
5077 &trigger.entryValue,
5078 /*count*/1);
5079 break;
5080 default:
5081 ALOGE("%s: Type not supported: 0x%x",
5082 __FUNCTION__,
5083 trigger.getTagType());
5084 return INVALID_OPERATION;
5085 }
5086
5087 if (res != OK) {
5088 ALOGE("%s: Failed to restore request metadata with trigger tag %s"
5089 ", trigger value %d", __FUNCTION__,
5090 trigger.getTagName(), trigger.entryValue);
5091 return res;
5092 }
5093 }
5094 mTriggerReplacedMap.clear();
5095
5096 /**
5097 * Remove all new entries.
5098 */
5099 for (size_t i = 0; i < mTriggerRemovedMap.size(); ++i) {
5100 RequestTrigger trigger = mTriggerRemovedMap.valueAt(i);
5101 status_t res = metadata.erase(trigger.metadataTag);
5102
5103 if (res != OK) {
5104 ALOGE("%s: Failed to erase metadata with trigger tag %s"
5105 ", trigger value %d", __FUNCTION__,
5106 trigger.getTagName(), trigger.entryValue);
5107 return res;
5108 }
5109 }
5110 mTriggerRemovedMap.clear();
5111
5112 return OK;
5113}
5114
Eino-Ville Talvala2f876f92013-09-13 11:39:24 -07005115status_t Camera3Device::RequestThread::addDummyTriggerIds(
5116 const sp<CaptureRequest> &request) {
Eino-Ville Talvalad309fb92015-11-25 12:12:45 -08005117 // Trigger ID 0 had special meaning in the HAL2 spec, so avoid it here
Eino-Ville Talvala2f876f92013-09-13 11:39:24 -07005118 static const int32_t dummyTriggerId = 1;
5119 status_t res;
5120
5121 CameraMetadata &metadata = request->mSettings;
5122
5123 // If AF trigger is active, insert a dummy AF trigger ID if none already
5124 // exists
5125 camera_metadata_entry afTrigger = metadata.find(ANDROID_CONTROL_AF_TRIGGER);
5126 camera_metadata_entry afId = metadata.find(ANDROID_CONTROL_AF_TRIGGER_ID);
5127 if (afTrigger.count > 0 &&
5128 afTrigger.data.u8[0] != ANDROID_CONTROL_AF_TRIGGER_IDLE &&
5129 afId.count == 0) {
5130 res = metadata.update(ANDROID_CONTROL_AF_TRIGGER_ID, &dummyTriggerId, 1);
5131 if (res != OK) return res;
5132 }
5133
5134 // If AE precapture trigger is active, insert a dummy precapture trigger ID
5135 // if none already exists
5136 camera_metadata_entry pcTrigger =
5137 metadata.find(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER);
5138 camera_metadata_entry pcId = metadata.find(ANDROID_CONTROL_AE_PRECAPTURE_ID);
5139 if (pcTrigger.count > 0 &&
5140 pcTrigger.data.u8[0] != ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE &&
5141 pcId.count == 0) {
5142 res = metadata.update(ANDROID_CONTROL_AE_PRECAPTURE_ID,
5143 &dummyTriggerId, 1);
5144 if (res != OK) return res;
5145 }
5146
5147 return OK;
5148}
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005149
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005150/**
5151 * PreparerThread inner class methods
5152 */
5153
5154Camera3Device::PreparerThread::PreparerThread() :
Eino-Ville Talvala77c1a352016-06-13 12:32:43 -07005155 Thread(/*canCallJava*/false), mListener(nullptr),
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005156 mActive(false), mCancelNow(false), mCurrentMaxCount(0), mCurrentPrepareComplete(false) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005157}
5158
5159Camera3Device::PreparerThread::~PreparerThread() {
5160 Thread::requestExitAndWait();
5161 if (mCurrentStream != nullptr) {
5162 mCurrentStream->cancelPrepare();
5163 ATRACE_ASYNC_END("stream prepare", mCurrentStream->getId());
5164 mCurrentStream.clear();
5165 }
5166 clear();
5167}
5168
Ruben Brunkc78ac262015-08-13 17:58:46 -07005169status_t Camera3Device::PreparerThread::prepare(int maxCount, sp<Camera3StreamInterface>& stream) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005170 ATRACE_CALL();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005171 status_t res;
5172
5173 Mutex::Autolock l(mLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005174 sp<NotificationListener> listener = mListener.promote();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005175
Ruben Brunkc78ac262015-08-13 17:58:46 -07005176 res = stream->startPrepare(maxCount);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005177 if (res == OK) {
5178 // No preparation needed, fire listener right off
5179 ALOGV("%s: Stream %d already prepared", __FUNCTION__, stream->getId());
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005180 if (listener != NULL) {
5181 listener->notifyPrepared(stream->getId());
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005182 }
5183 return OK;
5184 } else if (res != NOT_ENOUGH_DATA) {
5185 return res;
5186 }
5187
5188 // Need to prepare, start up thread if necessary
5189 if (!mActive) {
5190 // mRunning will change to false before the thread fully shuts down, so wait to be sure it
5191 // isn't running
5192 Thread::requestExitAndWait();
5193 res = Thread::run("C3PrepThread", PRIORITY_BACKGROUND);
5194 if (res != OK) {
5195 ALOGE("%s: Unable to start preparer stream: %d (%s)", __FUNCTION__, res, strerror(-res));
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005196 if (listener != NULL) {
5197 listener->notifyPrepared(stream->getId());
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005198 }
5199 return res;
5200 }
5201 mCancelNow = false;
5202 mActive = true;
5203 ALOGV("%s: Preparer stream started", __FUNCTION__);
5204 }
5205
5206 // queue up the work
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005207 mPendingStreams.emplace(maxCount, stream);
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005208 ALOGV("%s: Stream %d queued for preparing", __FUNCTION__, stream->getId());
5209
5210 return OK;
5211}
5212
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005213void Camera3Device::PreparerThread::pause() {
5214 ATRACE_CALL();
5215
5216 Mutex::Autolock l(mLock);
5217
5218 std::unordered_map<int, sp<camera3::Camera3StreamInterface> > pendingStreams;
5219 pendingStreams.insert(mPendingStreams.begin(), mPendingStreams.end());
5220 sp<camera3::Camera3StreamInterface> currentStream = mCurrentStream;
5221 int currentMaxCount = mCurrentMaxCount;
5222 mPendingStreams.clear();
5223 mCancelNow = true;
5224 while (mActive) {
5225 auto res = mThreadActiveSignal.waitRelative(mLock, kActiveTimeout);
5226 if (res == TIMED_OUT) {
5227 ALOGE("%s: Timed out waiting on prepare thread!", __FUNCTION__);
5228 return;
5229 } else if (res != OK) {
5230 ALOGE("%s: Encountered an error: %d waiting on prepare thread!", __FUNCTION__, res);
5231 return;
5232 }
5233 }
5234
5235 //Check whether the prepare thread was able to complete the current
5236 //stream. In case work is still pending emplace it along with the rest
5237 //of the streams in the pending list.
5238 if (currentStream != nullptr) {
5239 if (!mCurrentPrepareComplete) {
5240 pendingStreams.emplace(currentMaxCount, currentStream);
5241 }
5242 }
5243
5244 mPendingStreams.insert(pendingStreams.begin(), pendingStreams.end());
5245 for (const auto& it : mPendingStreams) {
5246 it.second->cancelPrepare();
5247 }
5248}
5249
5250status_t Camera3Device::PreparerThread::resume() {
5251 ATRACE_CALL();
5252 status_t res;
5253
5254 Mutex::Autolock l(mLock);
5255 sp<NotificationListener> listener = mListener.promote();
5256
5257 if (mActive) {
5258 ALOGE("%s: Trying to resume an already active prepare thread!", __FUNCTION__);
5259 return NO_INIT;
5260 }
5261
5262 auto it = mPendingStreams.begin();
5263 for (; it != mPendingStreams.end();) {
5264 res = it->second->startPrepare(it->first);
5265 if (res == OK) {
5266 if (listener != NULL) {
5267 listener->notifyPrepared(it->second->getId());
5268 }
5269 it = mPendingStreams.erase(it);
5270 } else if (res != NOT_ENOUGH_DATA) {
5271 ALOGE("%s: Unable to start preparer stream: %d (%s)", __FUNCTION__,
5272 res, strerror(-res));
5273 it = mPendingStreams.erase(it);
5274 } else {
5275 it++;
5276 }
5277 }
5278
5279 if (mPendingStreams.empty()) {
5280 return OK;
5281 }
5282
5283 res = Thread::run("C3PrepThread", PRIORITY_BACKGROUND);
5284 if (res != OK) {
5285 ALOGE("%s: Unable to start preparer stream: %d (%s)",
5286 __FUNCTION__, res, strerror(-res));
5287 return res;
5288 }
5289 mCancelNow = false;
5290 mActive = true;
5291 ALOGV("%s: Preparer stream started", __FUNCTION__);
5292
5293 return OK;
5294}
5295
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005296status_t Camera3Device::PreparerThread::clear() {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005297 ATRACE_CALL();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005298 Mutex::Autolock l(mLock);
5299
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005300 for (const auto& it : mPendingStreams) {
5301 it.second->cancelPrepare();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005302 }
5303 mPendingStreams.clear();
5304 mCancelNow = true;
5305
5306 return OK;
5307}
5308
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005309void Camera3Device::PreparerThread::setNotificationListener(wp<NotificationListener> listener) {
Eino-Ville Talvala6aeb8882017-08-07 17:40:49 -07005310 ATRACE_CALL();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005311 Mutex::Autolock l(mLock);
5312 mListener = listener;
5313}
5314
5315bool Camera3Device::PreparerThread::threadLoop() {
5316 status_t res;
5317 {
5318 Mutex::Autolock l(mLock);
5319 if (mCurrentStream == nullptr) {
5320 // End thread if done with work
5321 if (mPendingStreams.empty()) {
5322 ALOGV("%s: Preparer stream out of work", __FUNCTION__);
5323 // threadLoop _must not_ re-acquire mLock after it sets mActive to false; would
5324 // cause deadlock with prepare()'s requestExitAndWait triggered by !mActive.
5325 mActive = false;
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005326 mThreadActiveSignal.signal();
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005327 return false;
5328 }
5329
5330 // Get next stream to prepare
5331 auto it = mPendingStreams.begin();
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005332 mCurrentStream = it->second;
5333 mCurrentMaxCount = it->first;
5334 mCurrentPrepareComplete = false;
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005335 mPendingStreams.erase(it);
5336 ATRACE_ASYNC_BEGIN("stream prepare", mCurrentStream->getId());
5337 ALOGV("%s: Preparing stream %d", __FUNCTION__, mCurrentStream->getId());
5338 } else if (mCancelNow) {
5339 mCurrentStream->cancelPrepare();
5340 ATRACE_ASYNC_END("stream prepare", mCurrentStream->getId());
5341 ALOGV("%s: Cancelling stream %d prepare", __FUNCTION__, mCurrentStream->getId());
5342 mCurrentStream.clear();
5343 mCancelNow = false;
5344 return true;
5345 }
5346 }
5347
5348 res = mCurrentStream->prepareNextBuffer();
5349 if (res == NOT_ENOUGH_DATA) return true;
5350 if (res != OK) {
5351 // Something bad happened; try to recover by cancelling prepare and
5352 // signalling listener anyway
5353 ALOGE("%s: Stream %d returned error %d (%s) during prepare", __FUNCTION__,
5354 mCurrentStream->getId(), res, strerror(-res));
5355 mCurrentStream->cancelPrepare();
5356 }
5357
5358 // This stream has finished, notify listener
5359 Mutex::Autolock l(mLock);
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005360 sp<NotificationListener> listener = mListener.promote();
5361 if (listener != NULL) {
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005362 ALOGV("%s: Stream %d prepare done, signaling listener", __FUNCTION__,
5363 mCurrentStream->getId());
Yin-Chia Yehe1c80632016-08-08 14:48:05 -07005364 listener->notifyPrepared(mCurrentStream->getId());
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005365 }
5366
5367 ATRACE_ASYNC_END("stream prepare", mCurrentStream->getId());
5368 mCurrentStream.clear();
Emilian Peevac3ce6c2017-12-12 15:27:02 +00005369 mCurrentPrepareComplete = true;
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -07005370
5371 return true;
5372}
Igor Murashkin4d2f2e82013-04-01 17:29:07 -07005373
Eino-Ville Talvalaf76e0272013-02-27 18:02:26 -08005374/**
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08005375 * Static callback forwarding methods from HAL to instance
5376 */
5377
5378void Camera3Device::sProcessCaptureResult(const camera3_callback_ops *cb,
5379 const camera3_capture_result *result) {
5380 Camera3Device *d =
5381 const_cast<Camera3Device*>(static_cast<const Camera3Device*>(cb));
Chien-Yu Chend196d612015-06-22 19:49:01 -07005382
Eino-Ville Talvala7fa43f32013-02-06 17:20:07 -08005383 d->processCaptureResult(result);
5384}
5385
5386void Camera3Device::sNotify(const camera3_callback_ops *cb,
5387 const camera3_notify_msg *msg) {
5388 Camera3Device *d =
5389 const_cast<Camera3Device*>(static_cast<const Camera3Device*>(cb));
5390 d->notify(msg);
5391}
5392
5393}; // namespace android