1 /*
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
27 namespace android {
28
29 using hardware::camera::device::V3_2::ICameraDeviceSession;
30
Camera3DeviceInjectionMethods(wp<Camera3Device> parent)31 Camera3Device::Camera3DeviceInjectionMethods::Camera3DeviceInjectionMethods(
32 wp<Camera3Device> parent)
33 : mParent(parent) {
34 ALOGV("%s: Created injection camera methods", __FUNCTION__);
35 }
36
~Camera3DeviceInjectionMethods()37 Camera3Device::Camera3DeviceInjectionMethods::~Camera3DeviceInjectionMethods() {
38 ALOGV("%s: Removed injection camera methods", __FUNCTION__);
39 injectionDisconnectImpl();
40 }
41
injectionInitialize(const String8 & injectedCamId,sp<CameraProviderManager> manager,const sp<android::hardware::camera::device::V3_2::ICameraDeviceCallback> & callback)42 status_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
89 std::unique_ptr<ResultMetadataQueue>& resQueue = parent->mResultMetadataQueue;
90 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
injectCamera(camera3::camera_stream_configuration & injectionConfig,std::vector<uint32_t> & injectionBufferSizes)128 status_t Camera3Device::Camera3DeviceInjectionMethods::injectCamera(
129 camera3::camera_stream_configuration& injectionConfig,
130 std::vector<uint32_t>& injectionBufferSizes) {
131 status_t res = NO_ERROR;
132 mInjectionConfig = injectionConfig;
133 mInjectionBufferSizes = injectionBufferSizes;
134
135 if (mInjectedCamHalInterface == nullptr) {
136 ALOGE("%s: mInjectedCamHalInterface does not exist!", __FUNCTION__);
137 return DEAD_OBJECT;
138 }
139
140 sp<Camera3Device> parent = mParent.promote();
141 if (parent == nullptr) {
142 ALOGE("%s: parent does not exist!", __FUNCTION__);
143 return INVALID_OPERATION;
144 }
145
146 nsecs_t maxExpectedDuration = parent->getExpectedInFlightDuration();
147 bool wasActive = false;
148 if (parent->mStatus == STATUS_ACTIVE) {
149 ALOGV("%s: Let the device be IDLE and the request thread is paused",
150 __FUNCTION__);
151 parent->mPauseStateNotify = true;
152 res = parent->internalPauseAndWaitLocked(maxExpectedDuration);
153 if (res != OK) {
154 ALOGE("%s: Can't pause captures to inject camera!", __FUNCTION__);
155 return res;
156 }
157 wasActive = true;
158 }
159
160 ALOGV("%s: Injection camera: replaceHalInterface", __FUNCTION__);
161 res = replaceHalInterface(mInjectedCamHalInterface, true);
162 if (res != OK) {
163 ALOGE("%s: Failed to replace the new HalInterface!", __FUNCTION__);
164 injectionDisconnectImpl();
165 return res;
166 }
167
168 res = parent->mRequestThread->setHalInterface(mInjectedCamHalInterface);
169 if (res != OK) {
170 ALOGE("%s: Failed to set new HalInterface in RequestThread!", __FUNCTION__);
171 replaceHalInterface(mBackupHalInterface, false);
172 injectionDisconnectImpl();
173 return res;
174 }
175
176 parent->mNeedConfig = true;
177 res = injectionConfigureStreams(injectionConfig, injectionBufferSizes);
178 parent->mNeedConfig = false;
179 if (res != OK) {
180 ALOGE("Can't injectionConfigureStreams device for streams: %d: %s "
181 "(%d)", parent->mNextStreamId, strerror(-res), res);
182 replaceHalInterface(mBackupHalInterface, false);
183 injectionDisconnectImpl();
184 return res;
185 }
186
187 if (wasActive) {
188 ALOGV("%s: Restarting activity to inject camera", __FUNCTION__);
189 // Reuse current operating mode and session parameters for new stream
190 // config.
191 parent->internalUpdateStatusLocked(STATUS_ACTIVE);
192 }
193
194 return OK;
195 }
196
stopInjection()197 status_t Camera3Device::Camera3DeviceInjectionMethods::stopInjection() {
198 status_t res = NO_ERROR;
199
200 sp<Camera3Device> parent = mParent.promote();
201 if (parent == nullptr) {
202 ALOGE("%s: parent does not exist!", __FUNCTION__);
203 return DEAD_OBJECT;
204 }
205
206 nsecs_t maxExpectedDuration = parent->getExpectedInFlightDuration();
207 bool wasActive = false;
208 if (parent->mStatus == STATUS_ACTIVE) {
209 ALOGV("%s: Let the device be IDLE and the request thread is paused",
210 __FUNCTION__);
211 parent->mPauseStateNotify = true;
212 res = parent->internalPauseAndWaitLocked(maxExpectedDuration);
213 if (res != OK) {
214 ALOGE("%s: Can't pause captures to stop injection!", __FUNCTION__);
215 return res;
216 }
217 wasActive = true;
218 }
219
220 res = replaceHalInterface(mBackupHalInterface, false);
221 if (res != OK) {
222 ALOGE("%s: Failed to restore the backup HalInterface!", __FUNCTION__);
223 injectionDisconnectImpl();
224 return res;
225 }
226 injectionDisconnectImpl();
227
228 if (wasActive) {
229 ALOGV("%s: Restarting activity to stop injection", __FUNCTION__);
230 // Reuse current operating mode and session parameters for new stream
231 // config.
232 parent->internalUpdateStatusLocked(STATUS_ACTIVE);
233 }
234
235 return OK;
236 }
237
isInjecting()238 bool Camera3Device::Camera3DeviceInjectionMethods::isInjecting() {
239 if (mInjectedCamHalInterface == nullptr) {
240 return false;
241 } else {
242 return true;
243 }
244 }
245
getInjectedCamId() const246 const String8& Camera3Device::Camera3DeviceInjectionMethods::getInjectedCamId()
247 const {
248 return mInjectedCamId;
249 }
250
getInjectionConfig(camera3::camera_stream_configuration * injectionConfig,std::vector<uint32_t> * injectionBufferSizes)251 void 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
263
injectionConfigureStreams(camera3::camera_stream_configuration & injectionConfig,std::vector<uint32_t> & injectionBufferSizes)264 status_t Camera3Device::Camera3DeviceInjectionMethods::injectionConfigureStreams(
265 camera3::camera_stream_configuration& injectionConfig,
266 std::vector<uint32_t>& injectionBufferSizes) {
267 ATRACE_CALL();
268 status_t res = NO_ERROR;
269
270 sp<Camera3Device> parent = mParent.promote();
271 if (parent == nullptr) {
272 ALOGE("%s: parent does not exist!", __FUNCTION__);
273 return INVALID_OPERATION;
274 }
275
276 if (parent->mOperatingMode < 0) {
277 ALOGE("Invalid operating mode: %d", parent->mOperatingMode);
278 return BAD_VALUE;
279 }
280
281 // Start configuring the streams
282 ALOGV("%s: Injection camera %s: Starting stream configuration", __FUNCTION__,
283 mInjectedCamId.string());
284
285 parent->mPreparerThread->pause();
286
287 // Do the HAL configuration; will potentially touch stream
288 // max_buffers, usage, and priv fields, as well as data_space and format
289 // fields for IMPLEMENTATION_DEFINED formats.
290
291 const camera_metadata_t* sessionBuffer = parent->mSessionParams.getAndLock();
292 res = mInjectedCamHalInterface->configureInjectedStreams(
293 sessionBuffer, &injectionConfig, injectionBufferSizes,
294 parent->mDeviceInfo);
295 parent->mSessionParams.unlock(sessionBuffer);
296
297 if (res == BAD_VALUE) {
298 // HAL rejected this set of streams as unsupported, clean up config
299 // attempt and return to unconfigured state
300 ALOGE("Set of requested outputs not supported by HAL");
301 parent->cancelStreamsConfigurationLocked();
302 return BAD_VALUE;
303 } else if (res != OK) {
304 // Some other kind of error from configure_streams - this is not
305 // expected
306 ALOGE("Unable to configure streams with HAL: %s (%d)", strerror(-res),
307 res);
308 return res;
309 }
310
311 for (size_t i = 0; i < parent->mOutputStreams.size(); i++) {
312 sp<camera3::Camera3OutputStreamInterface> outputStream =
313 parent->mOutputStreams[i];
314 mInjectedCamHalInterface->onStreamReConfigured(outputStream->getId());
315 }
316
317 // Request thread needs to know to avoid using repeat-last-settings protocol
318 // across configure_streams() calls
319 parent->mRequestThread->configurationComplete(
320 parent->mIsConstrainedHighSpeedConfiguration, parent->mSessionParams,
321 parent->mGroupIdPhysicalCameraMap);
322
323 parent->internalUpdateStatusLocked(STATUS_CONFIGURED);
324
325 ALOGV("%s: Injection camera %s: Stream configuration complete", __FUNCTION__,
326 mInjectedCamId.string());
327
328 auto rc = parent->mPreparerThread->resume();
329
330 if (rc != OK) {
331 ALOGE("%s: Injection camera %s: Preparer thread failed to resume!",
332 __FUNCTION__, mInjectedCamId.string());
333 return rc;
334 }
335
336 return OK;
337 }
338
injectionDisconnectImpl()339 void Camera3Device::Camera3DeviceInjectionMethods::injectionDisconnectImpl() {
340 ATRACE_CALL();
341 ALOGI("%s: Injection camera disconnect", __FUNCTION__);
342
343 mBackupHalInterface = nullptr;
344 HalInterface* interface = nullptr;
345 {
346 Mutex::Autolock lock(mInjectionLock);
347 if (mInjectedCamHalInterface != nullptr) {
348 interface = mInjectedCamHalInterface.get();
349 // Call close without internal mutex held, as the HAL close may need
350 // to wait on assorted callbacks,etc, to complete before it can
351 // return.
352 }
353 }
354
355 if (interface != nullptr) {
356 interface->close();
357 }
358
359 {
360 Mutex::Autolock lock(mInjectionLock);
361 if (mInjectedCamHalInterface != nullptr) {
362 mInjectedCamHalInterface->clear();
363 mInjectedCamHalInterface = nullptr;
364 }
365 }
366 }
367
replaceHalInterface(sp<HalInterface> newHalInterface,bool keepBackup)368 status_t Camera3Device::Camera3DeviceInjectionMethods::replaceHalInterface(
369 sp<HalInterface> newHalInterface, bool keepBackup) {
370 Mutex::Autolock lock(mInjectionLock);
371 if (newHalInterface.get() == nullptr) {
372 ALOGE("%s: The newHalInterface does not exist, to stop replacing.",
373 __FUNCTION__);
374 return DEAD_OBJECT;
375 }
376
377 sp<Camera3Device> parent = mParent.promote();
378 if (parent == nullptr) {
379 ALOGE("%s: parent does not exist!", __FUNCTION__);
380 return INVALID_OPERATION;
381 }
382
383 if (keepBackup && mBackupHalInterface == nullptr) {
384 mBackupHalInterface = parent->mInterface;
385 } else if (!keepBackup) {
386 mBackupHalInterface = nullptr;
387 }
388 parent->mInterface = newHalInterface;
389
390 return OK;
391 }
392
393 }; // namespace android
394