blob: 4744a6deb789b8d1f884821aef16e396abf1d945 [file] [log] [blame]
Cliff Wuc2ad9c82021-04-21 00:58:58 +08001/*
2 * Copyright (C) 2021 The Android Open Source Project
3 *
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 "Camera3DeviceInjectionMethods"
18#define ATRACE_TAG ATRACE_TAG_CAMERA
19//#define LOG_NDEBUG 0
20
21#include <utils/Log.h>
22#include <utils/Trace.h>
23
24#include "common/CameraProviderManager.h"
25#include "device3/Camera3Device.h"
26
27namespace android {
28
29using hardware::camera::device::V3_2::ICameraDeviceSession;
30
31Camera3Device::Camera3DeviceInjectionMethods::Camera3DeviceInjectionMethods(
32 wp<Camera3Device> parent)
33 : mParent(parent) {
34 ALOGV("%s: Created injection camera methods", __FUNCTION__);
35}
36
37Camera3Device::Camera3DeviceInjectionMethods::~Camera3DeviceInjectionMethods() {
38 ALOGV("%s: Removed injection camera methods", __FUNCTION__);
39 injectionDisconnectImpl();
40}
41
42status_t Camera3Device::Camera3DeviceInjectionMethods::injectionInitialize(
43 const String8& injectedCamId, sp<CameraProviderManager> manager,
44 const sp<android::hardware::camera::device::V3_2::ICameraDeviceCallback>&
45 callback) {
46 ATRACE_CALL();
47 Mutex::Autolock lock(mInjectionLock);
48
49 if (manager == nullptr) {
50 ALOGE("%s: manager does not exist!", __FUNCTION__);
51 return INVALID_OPERATION;
52 }
53
54 sp<Camera3Device> parent = mParent.promote();
55 if (parent == nullptr) {
56 ALOGE("%s: parent does not exist!", __FUNCTION__);
57 return INVALID_OPERATION;
58 }
59
60 mInjectedCamId = injectedCamId;
61 sp<ICameraDeviceSession> session;
62 ATRACE_BEGIN("Injection CameraHal::openSession");
63 status_t res = manager->openSession(injectedCamId.string(), callback,
64 /*out*/ &session);
65 ATRACE_END();
66 if (res != OK) {
67 ALOGE("Injection camera could not open camera session: %s (%d)",
68 strerror(-res), res);
69 return res;
70 }
71
72 std::shared_ptr<RequestMetadataQueue> queue;
73 auto requestQueueRet =
74 session->getCaptureRequestMetadataQueue([&queue](const auto& descriptor) {
75 queue = std::make_shared<RequestMetadataQueue>(descriptor);
76 if (!queue->isValid() || queue->availableToWrite() <= 0) {
77 ALOGE("Injection camera HAL returns empty request metadata fmq, not "
78 "use it");
79 queue = nullptr;
80 // don't use the queue onwards.
81 }
82 });
83 if (!requestQueueRet.isOk()) {
84 ALOGE("Injection camera transaction error when getting request metadata fmq: "
85 "%s, not use it", requestQueueRet.description().c_str());
86 return DEAD_OBJECT;
87 }
88
Cliff Wu3b268182021-07-06 15:44:43 +080089 std::unique_ptr<ResultMetadataQueue>& resQueue = mInjectionResultMetadataQueue;
Cliff Wuc2ad9c82021-04-21 00:58:58 +080090 auto resultQueueRet = session->getCaptureResultMetadataQueue(
91 [&resQueue](const auto& descriptor) {
92 resQueue = std::make_unique<ResultMetadataQueue>(descriptor);
93 if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
94 ALOGE("Injection camera HAL returns empty result metadata fmq, not use "
95 "it");
96 resQueue = nullptr;
97 // Don't use the resQueue onwards.
98 }
99 });
100 if (!resultQueueRet.isOk()) {
101 ALOGE("Injection camera transaction error when getting result metadata queue "
102 "from camera session: %s", resultQueueRet.description().c_str());
103 return DEAD_OBJECT;
104 }
105 IF_ALOGV() {
106 session->interfaceChain(
107 [](::android::hardware::hidl_vec<::android::hardware::hidl_string>
108 interfaceChain) {
109 ALOGV("Injection camera session interface chain:");
110 for (const auto& iface : interfaceChain) {
111 ALOGV(" %s", iface.c_str());
112 }
113 });
114 }
115
116 ALOGV("%s: Injection camera interface = new HalInterface()", __FUNCTION__);
117 mInjectedCamHalInterface =
118 new HalInterface(session, queue, parent->mUseHalBufManager,
119 parent->mSupportOfflineProcessing);
120 if (mInjectedCamHalInterface == nullptr) {
121 ALOGE("%s: mInjectedCamHalInterface does not exist!", __FUNCTION__);
122 return DEAD_OBJECT;
123 }
124
125 return OK;
126}
127
128status_t Camera3Device::Camera3DeviceInjectionMethods::injectCamera(
129 camera3::camera_stream_configuration& injectionConfig,
Cliff Wu3b268182021-07-06 15:44:43 +0800130 const std::vector<uint32_t>& injectionBufferSizes) {
Cliff Wuc2ad9c82021-04-21 00:58:58 +0800131 status_t res = NO_ERROR;
Cliff Wuc2ad9c82021-04-21 00:58:58 +0800132
133 if (mInjectedCamHalInterface == nullptr) {
134 ALOGE("%s: mInjectedCamHalInterface does not exist!", __FUNCTION__);
135 return DEAD_OBJECT;
136 }
137
138 sp<Camera3Device> parent = mParent.promote();
139 if (parent == nullptr) {
140 ALOGE("%s: parent does not exist!", __FUNCTION__);
141 return INVALID_OPERATION;
142 }
143
144 nsecs_t maxExpectedDuration = parent->getExpectedInFlightDuration();
145 bool wasActive = false;
146 if (parent->mStatus == STATUS_ACTIVE) {
147 ALOGV("%s: Let the device be IDLE and the request thread is paused",
148 __FUNCTION__);
Cliff Wuc2ad9c82021-04-21 00:58:58 +0800149 res = parent->internalPauseAndWaitLocked(maxExpectedDuration);
150 if (res != OK) {
151 ALOGE("%s: Can't pause captures to inject camera!", __FUNCTION__);
152 return res;
153 }
154 wasActive = true;
155 }
156
157 ALOGV("%s: Injection camera: replaceHalInterface", __FUNCTION__);
158 res = replaceHalInterface(mInjectedCamHalInterface, true);
159 if (res != OK) {
160 ALOGE("%s: Failed to replace the new HalInterface!", __FUNCTION__);
161 injectionDisconnectImpl();
162 return res;
163 }
164
165 res = parent->mRequestThread->setHalInterface(mInjectedCamHalInterface);
166 if (res != OK) {
167 ALOGE("%s: Failed to set new HalInterface in RequestThread!", __FUNCTION__);
168 replaceHalInterface(mBackupHalInterface, false);
169 injectionDisconnectImpl();
170 return res;
171 }
172
173 parent->mNeedConfig = true;
174 res = injectionConfigureStreams(injectionConfig, injectionBufferSizes);
175 parent->mNeedConfig = false;
176 if (res != OK) {
177 ALOGE("Can't injectionConfigureStreams device for streams: %d: %s "
178 "(%d)", parent->mNextStreamId, strerror(-res), res);
179 replaceHalInterface(mBackupHalInterface, false);
180 injectionDisconnectImpl();
181 return res;
182 }
183
184 if (wasActive) {
185 ALOGV("%s: Restarting activity to inject camera", __FUNCTION__);
186 // Reuse current operating mode and session parameters for new stream
187 // config.
Cliff Wu3b268182021-07-06 15:44:43 +0800188 parent->internalResumeLocked();
Cliff Wuc2ad9c82021-04-21 00:58:58 +0800189 }
190
191 return OK;
192}
193
194status_t Camera3Device::Camera3DeviceInjectionMethods::stopInjection() {
195 status_t res = NO_ERROR;
196
197 sp<Camera3Device> parent = mParent.promote();
198 if (parent == nullptr) {
199 ALOGE("%s: parent does not exist!", __FUNCTION__);
200 return DEAD_OBJECT;
201 }
202
203 nsecs_t maxExpectedDuration = parent->getExpectedInFlightDuration();
204 bool wasActive = false;
205 if (parent->mStatus == STATUS_ACTIVE) {
206 ALOGV("%s: Let the device be IDLE and the request thread is paused",
207 __FUNCTION__);
Cliff Wuc2ad9c82021-04-21 00:58:58 +0800208 res = parent->internalPauseAndWaitLocked(maxExpectedDuration);
209 if (res != OK) {
210 ALOGE("%s: Can't pause captures to stop injection!", __FUNCTION__);
211 return res;
212 }
213 wasActive = true;
214 }
215
216 res = replaceHalInterface(mBackupHalInterface, false);
217 if (res != OK) {
218 ALOGE("%s: Failed to restore the backup HalInterface!", __FUNCTION__);
219 injectionDisconnectImpl();
220 return res;
221 }
222 injectionDisconnectImpl();
223
224 if (wasActive) {
225 ALOGV("%s: Restarting activity to stop injection", __FUNCTION__);
226 // Reuse current operating mode and session parameters for new stream
227 // config.
Cliff Wu3b268182021-07-06 15:44:43 +0800228 parent->internalResumeLocked();
Cliff Wuc2ad9c82021-04-21 00:58:58 +0800229 }
230
231 return OK;
232}
233
234bool Camera3Device::Camera3DeviceInjectionMethods::isInjecting() {
235 if (mInjectedCamHalInterface == nullptr) {
236 return false;
237 } else {
238 return true;
239 }
240}
241
Cliff Wu3b268182021-07-06 15:44:43 +0800242bool Camera3Device::Camera3DeviceInjectionMethods::isStreamConfigCompleteButNotInjected() {
243 return mIsStreamConfigCompleteButNotInjected;
244}
245
Cliff Wuc2ad9c82021-04-21 00:58:58 +0800246const String8& Camera3Device::Camera3DeviceInjectionMethods::getInjectedCamId()
247 const {
248 return mInjectedCamId;
249}
250
251void Camera3Device::Camera3DeviceInjectionMethods::getInjectionConfig(
252 /*out*/ camera3::camera_stream_configuration* injectionConfig,
253 /*out*/ std::vector<uint32_t>* injectionBufferSizes) {
254 if (injectionConfig == nullptr || injectionBufferSizes == nullptr) {
255 ALOGE("%s: Injection configuration arguments must not be null!", __FUNCTION__);
256 return;
257 }
258
259 *injectionConfig = mInjectionConfig;
260 *injectionBufferSizes = mInjectionBufferSizes;
261}
262
Cliff Wu3b268182021-07-06 15:44:43 +0800263void Camera3Device::Camera3DeviceInjectionMethods::storeInjectionConfig(
264 const camera3::camera_stream_configuration& injectionConfig,
265 const std::vector<uint32_t>& injectionBufferSizes) {
266 mIsStreamConfigCompleteButNotInjected = true;
Cliff Wu3b268182021-07-06 15:44:43 +0800267 mInjectionConfig = injectionConfig;
Cliff Wud0476312021-07-27 20:15:55 +0800268 mInjectionStreams.clear();
Cliff Wu3b268182021-07-06 15:44:43 +0800269 for (size_t i = 0; i < injectionConfig.num_streams; i++) {
Cliff Wud0476312021-07-27 20:15:55 +0800270 mInjectionStreams.push_back(injectionConfig.streams[i]);
Cliff Wu3b268182021-07-06 15:44:43 +0800271 }
Cliff Wud0476312021-07-27 20:15:55 +0800272 mInjectionConfig.streams = mInjectionStreams.editArray();
Cliff Wu3b268182021-07-06 15:44:43 +0800273 mInjectionBufferSizes = injectionBufferSizes;
274}
Cliff Wuc2ad9c82021-04-21 00:58:58 +0800275
276status_t Camera3Device::Camera3DeviceInjectionMethods::injectionConfigureStreams(
277 camera3::camera_stream_configuration& injectionConfig,
Cliff Wu3b268182021-07-06 15:44:43 +0800278 const std::vector<uint32_t>& injectionBufferSizes) {
Cliff Wuc2ad9c82021-04-21 00:58:58 +0800279 ATRACE_CALL();
280 status_t res = NO_ERROR;
281
282 sp<Camera3Device> parent = mParent.promote();
283 if (parent == nullptr) {
284 ALOGE("%s: parent does not exist!", __FUNCTION__);
285 return INVALID_OPERATION;
286 }
287
288 if (parent->mOperatingMode < 0) {
289 ALOGE("Invalid operating mode: %d", parent->mOperatingMode);
290 return BAD_VALUE;
291 }
292
293 // Start configuring the streams
294 ALOGV("%s: Injection camera %s: Starting stream configuration", __FUNCTION__,
295 mInjectedCamId.string());
296
297 parent->mPreparerThread->pause();
298
299 // Do the HAL configuration; will potentially touch stream
300 // max_buffers, usage, and priv fields, as well as data_space and format
301 // fields for IMPLEMENTATION_DEFINED formats.
302
303 const camera_metadata_t* sessionBuffer = parent->mSessionParams.getAndLock();
304 res = mInjectedCamHalInterface->configureInjectedStreams(
305 sessionBuffer, &injectionConfig, injectionBufferSizes,
306 parent->mDeviceInfo);
307 parent->mSessionParams.unlock(sessionBuffer);
308
309 if (res == BAD_VALUE) {
310 // HAL rejected this set of streams as unsupported, clean up config
311 // attempt and return to unconfigured state
312 ALOGE("Set of requested outputs not supported by HAL");
313 parent->cancelStreamsConfigurationLocked();
314 return BAD_VALUE;
315 } else if (res != OK) {
316 // Some other kind of error from configure_streams - this is not
317 // expected
318 ALOGE("Unable to configure streams with HAL: %s (%d)", strerror(-res),
319 res);
320 return res;
321 }
322
323 for (size_t i = 0; i < parent->mOutputStreams.size(); i++) {
324 sp<camera3::Camera3OutputStreamInterface> outputStream =
325 parent->mOutputStreams[i];
326 mInjectedCamHalInterface->onStreamReConfigured(outputStream->getId());
327 }
328
329 // Request thread needs to know to avoid using repeat-last-settings protocol
330 // across configure_streams() calls
331 parent->mRequestThread->configurationComplete(
332 parent->mIsConstrainedHighSpeedConfiguration, parent->mSessionParams,
333 parent->mGroupIdPhysicalCameraMap);
334
335 parent->internalUpdateStatusLocked(STATUS_CONFIGURED);
336
337 ALOGV("%s: Injection camera %s: Stream configuration complete", __FUNCTION__,
338 mInjectedCamId.string());
339
340 auto rc = parent->mPreparerThread->resume();
Cliff Wuc2ad9c82021-04-21 00:58:58 +0800341 if (rc != OK) {
342 ALOGE("%s: Injection camera %s: Preparer thread failed to resume!",
343 __FUNCTION__, mInjectedCamId.string());
344 return rc;
345 }
346
347 return OK;
348}
349
350void Camera3Device::Camera3DeviceInjectionMethods::injectionDisconnectImpl() {
351 ATRACE_CALL();
352 ALOGI("%s: Injection camera disconnect", __FUNCTION__);
Cliff Wud0476312021-07-27 20:15:55 +0800353 mIsStreamConfigCompleteButNotInjected = false;
354 mInjectionStreams.clear();
355 mInjectionConfig.streams = nullptr;
Cliff Wuc2ad9c82021-04-21 00:58:58 +0800356
357 mBackupHalInterface = nullptr;
358 HalInterface* interface = nullptr;
359 {
360 Mutex::Autolock lock(mInjectionLock);
361 if (mInjectedCamHalInterface != nullptr) {
362 interface = mInjectedCamHalInterface.get();
363 // Call close without internal mutex held, as the HAL close may need
364 // to wait on assorted callbacks,etc, to complete before it can
365 // return.
366 }
367 }
368
369 if (interface != nullptr) {
370 interface->close();
371 }
372
373 {
374 Mutex::Autolock lock(mInjectionLock);
375 if (mInjectedCamHalInterface != nullptr) {
376 mInjectedCamHalInterface->clear();
377 mInjectedCamHalInterface = nullptr;
378 }
379 }
380}
381
382status_t Camera3Device::Camera3DeviceInjectionMethods::replaceHalInterface(
383 sp<HalInterface> newHalInterface, bool keepBackup) {
384 Mutex::Autolock lock(mInjectionLock);
385 if (newHalInterface.get() == nullptr) {
386 ALOGE("%s: The newHalInterface does not exist, to stop replacing.",
387 __FUNCTION__);
388 return DEAD_OBJECT;
389 }
390
391 sp<Camera3Device> parent = mParent.promote();
392 if (parent == nullptr) {
393 ALOGE("%s: parent does not exist!", __FUNCTION__);
394 return INVALID_OPERATION;
395 }
396
Cliff Wu3b268182021-07-06 15:44:43 +0800397 if (keepBackup) {
398 if (mBackupHalInterface == nullptr) {
399 mBackupHalInterface = parent->mInterface;
400 }
401 if (mBackupResultMetadataQueue == nullptr) {
402 mBackupResultMetadataQueue = std::move(parent->mResultMetadataQueue);
403 parent->mResultMetadataQueue = std::move(mInjectionResultMetadataQueue);
404 }
405 } else {
Cliff Wuc2ad9c82021-04-21 00:58:58 +0800406 mBackupHalInterface = nullptr;
Cliff Wu3b268182021-07-06 15:44:43 +0800407 parent->mResultMetadataQueue = std::move(mBackupResultMetadataQueue);
408 mBackupResultMetadataQueue = nullptr;
Cliff Wuc2ad9c82021-04-21 00:58:58 +0800409 }
410 parent->mInterface = newHalInterface;
411
412 return OK;
413}
414
415}; // namespace android