blob: ab772d4f8f87bbba432d2851b91436d47d844a14 [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
Cliff Wuc2ad9c82021-04-21 00:58:58 +080029Camera3Device::Camera3DeviceInjectionMethods::Camera3DeviceInjectionMethods(
30 wp<Camera3Device> parent)
31 : mParent(parent) {
32 ALOGV("%s: Created injection camera methods", __FUNCTION__);
33}
34
35Camera3Device::Camera3DeviceInjectionMethods::~Camera3DeviceInjectionMethods() {
36 ALOGV("%s: Removed injection camera methods", __FUNCTION__);
37 injectionDisconnectImpl();
38}
39
Cliff Wuc2ad9c82021-04-21 00:58:58 +080040status_t Camera3Device::Camera3DeviceInjectionMethods::injectCamera(
41 camera3::camera_stream_configuration& injectionConfig,
Cliff Wu3b268182021-07-06 15:44:43 +080042 const std::vector<uint32_t>& injectionBufferSizes) {
Cliff Wuc2ad9c82021-04-21 00:58:58 +080043 status_t res = NO_ERROR;
Cliff Wuc2ad9c82021-04-21 00:58:58 +080044
45 if (mInjectedCamHalInterface == nullptr) {
46 ALOGE("%s: mInjectedCamHalInterface does not exist!", __FUNCTION__);
47 return DEAD_OBJECT;
48 }
49
50 sp<Camera3Device> parent = mParent.promote();
51 if (parent == nullptr) {
52 ALOGE("%s: parent does not exist!", __FUNCTION__);
53 return INVALID_OPERATION;
54 }
55
56 nsecs_t maxExpectedDuration = parent->getExpectedInFlightDuration();
57 bool wasActive = false;
58 if (parent->mStatus == STATUS_ACTIVE) {
59 ALOGV("%s: Let the device be IDLE and the request thread is paused",
60 __FUNCTION__);
Bharatt Kukrejaf6f0ca12023-01-26 19:56:30 +000061 res = parent->internalPauseAndWaitLocked(maxExpectedDuration,
62 /*requestThreadInvocation*/false);
Cliff Wuc2ad9c82021-04-21 00:58:58 +080063 if (res != OK) {
64 ALOGE("%s: Can't pause captures to inject camera!", __FUNCTION__);
65 return res;
66 }
67 wasActive = true;
68 }
69
70 ALOGV("%s: Injection camera: replaceHalInterface", __FUNCTION__);
71 res = replaceHalInterface(mInjectedCamHalInterface, true);
72 if (res != OK) {
73 ALOGE("%s: Failed to replace the new HalInterface!", __FUNCTION__);
74 injectionDisconnectImpl();
75 return res;
76 }
77
78 res = parent->mRequestThread->setHalInterface(mInjectedCamHalInterface);
79 if (res != OK) {
80 ALOGE("%s: Failed to set new HalInterface in RequestThread!", __FUNCTION__);
81 replaceHalInterface(mBackupHalInterface, false);
82 injectionDisconnectImpl();
83 return res;
84 }
85
86 parent->mNeedConfig = true;
87 res = injectionConfigureStreams(injectionConfig, injectionBufferSizes);
88 parent->mNeedConfig = false;
89 if (res != OK) {
90 ALOGE("Can't injectionConfigureStreams device for streams: %d: %s "
91 "(%d)", parent->mNextStreamId, strerror(-res), res);
92 replaceHalInterface(mBackupHalInterface, false);
93 injectionDisconnectImpl();
94 return res;
95 }
96
97 if (wasActive) {
98 ALOGV("%s: Restarting activity to inject camera", __FUNCTION__);
99 // Reuse current operating mode and session parameters for new stream
100 // config.
Cliff Wu3b268182021-07-06 15:44:43 +0800101 parent->internalResumeLocked();
Cliff Wuc2ad9c82021-04-21 00:58:58 +0800102 }
103
104 return OK;
105}
106
107status_t Camera3Device::Camera3DeviceInjectionMethods::stopInjection() {
108 status_t res = NO_ERROR;
109
110 sp<Camera3Device> parent = mParent.promote();
111 if (parent == nullptr) {
112 ALOGE("%s: parent does not exist!", __FUNCTION__);
113 return DEAD_OBJECT;
114 }
115
116 nsecs_t maxExpectedDuration = parent->getExpectedInFlightDuration();
117 bool wasActive = false;
118 if (parent->mStatus == STATUS_ACTIVE) {
119 ALOGV("%s: Let the device be IDLE and the request thread is paused",
120 __FUNCTION__);
Bharatt Kukrejaf6f0ca12023-01-26 19:56:30 +0000121 res = parent->internalPauseAndWaitLocked(maxExpectedDuration,
122 /*requestThreadInvocation*/false);
Cliff Wuc2ad9c82021-04-21 00:58:58 +0800123 if (res != OK) {
124 ALOGE("%s: Can't pause captures to stop injection!", __FUNCTION__);
125 return res;
126 }
127 wasActive = true;
128 }
129
130 res = replaceHalInterface(mBackupHalInterface, false);
131 if (res != OK) {
132 ALOGE("%s: Failed to restore the backup HalInterface!", __FUNCTION__);
133 injectionDisconnectImpl();
134 return res;
135 }
136 injectionDisconnectImpl();
137
138 if (wasActive) {
139 ALOGV("%s: Restarting activity to stop injection", __FUNCTION__);
140 // Reuse current operating mode and session parameters for new stream
141 // config.
Cliff Wu3b268182021-07-06 15:44:43 +0800142 parent->internalResumeLocked();
Cliff Wuc2ad9c82021-04-21 00:58:58 +0800143 }
144
145 return OK;
146}
147
148bool Camera3Device::Camera3DeviceInjectionMethods::isInjecting() {
149 if (mInjectedCamHalInterface == nullptr) {
150 return false;
151 } else {
152 return true;
153 }
154}
155
Cliff Wu3b268182021-07-06 15:44:43 +0800156bool Camera3Device::Camera3DeviceInjectionMethods::isStreamConfigCompleteButNotInjected() {
157 return mIsStreamConfigCompleteButNotInjected;
158}
159
Cliff Wuc2ad9c82021-04-21 00:58:58 +0800160const String8& Camera3Device::Camera3DeviceInjectionMethods::getInjectedCamId()
161 const {
162 return mInjectedCamId;
163}
164
165void Camera3Device::Camera3DeviceInjectionMethods::getInjectionConfig(
166 /*out*/ camera3::camera_stream_configuration* injectionConfig,
167 /*out*/ std::vector<uint32_t>* injectionBufferSizes) {
168 if (injectionConfig == nullptr || injectionBufferSizes == nullptr) {
169 ALOGE("%s: Injection configuration arguments must not be null!", __FUNCTION__);
170 return;
171 }
172
173 *injectionConfig = mInjectionConfig;
174 *injectionBufferSizes = mInjectionBufferSizes;
175}
176
Cliff Wu3b268182021-07-06 15:44:43 +0800177void Camera3Device::Camera3DeviceInjectionMethods::storeInjectionConfig(
178 const camera3::camera_stream_configuration& injectionConfig,
179 const std::vector<uint32_t>& injectionBufferSizes) {
180 mIsStreamConfigCompleteButNotInjected = true;
Cliff Wu3b268182021-07-06 15:44:43 +0800181 mInjectionConfig = injectionConfig;
Cliff Wud0476312021-07-27 20:15:55 +0800182 mInjectionStreams.clear();
Cliff Wu3b268182021-07-06 15:44:43 +0800183 for (size_t i = 0; i < injectionConfig.num_streams; i++) {
Cliff Wud0476312021-07-27 20:15:55 +0800184 mInjectionStreams.push_back(injectionConfig.streams[i]);
Cliff Wu3b268182021-07-06 15:44:43 +0800185 }
Cliff Wud0476312021-07-27 20:15:55 +0800186 mInjectionConfig.streams = mInjectionStreams.editArray();
Cliff Wu3b268182021-07-06 15:44:43 +0800187 mInjectionBufferSizes = injectionBufferSizes;
188}
Cliff Wuc2ad9c82021-04-21 00:58:58 +0800189
190status_t Camera3Device::Camera3DeviceInjectionMethods::injectionConfigureStreams(
191 camera3::camera_stream_configuration& injectionConfig,
Cliff Wu3b268182021-07-06 15:44:43 +0800192 const std::vector<uint32_t>& injectionBufferSizes) {
Cliff Wuc2ad9c82021-04-21 00:58:58 +0800193 ATRACE_CALL();
194 status_t res = NO_ERROR;
195
196 sp<Camera3Device> parent = mParent.promote();
197 if (parent == nullptr) {
198 ALOGE("%s: parent does not exist!", __FUNCTION__);
199 return INVALID_OPERATION;
200 }
201
202 if (parent->mOperatingMode < 0) {
203 ALOGE("Invalid operating mode: %d", parent->mOperatingMode);
204 return BAD_VALUE;
205 }
206
207 // Start configuring the streams
208 ALOGV("%s: Injection camera %s: Starting stream configuration", __FUNCTION__,
209 mInjectedCamId.string());
210
211 parent->mPreparerThread->pause();
212
213 // Do the HAL configuration; will potentially touch stream
214 // max_buffers, usage, and priv fields, as well as data_space and format
215 // fields for IMPLEMENTATION_DEFINED formats.
216
217 const camera_metadata_t* sessionBuffer = parent->mSessionParams.getAndLock();
218 res = mInjectedCamHalInterface->configureInjectedStreams(
219 sessionBuffer, &injectionConfig, injectionBufferSizes,
220 parent->mDeviceInfo);
221 parent->mSessionParams.unlock(sessionBuffer);
222
223 if (res == BAD_VALUE) {
224 // HAL rejected this set of streams as unsupported, clean up config
225 // attempt and return to unconfigured state
226 ALOGE("Set of requested outputs not supported by HAL");
227 parent->cancelStreamsConfigurationLocked();
228 return BAD_VALUE;
229 } else if (res != OK) {
230 // Some other kind of error from configure_streams - this is not
231 // expected
232 ALOGE("Unable to configure streams with HAL: %s (%d)", strerror(-res),
233 res);
234 return res;
235 }
236
237 for (size_t i = 0; i < parent->mOutputStreams.size(); i++) {
238 sp<camera3::Camera3OutputStreamInterface> outputStream =
239 parent->mOutputStreams[i];
240 mInjectedCamHalInterface->onStreamReConfigured(outputStream->getId());
241 }
242
243 // Request thread needs to know to avoid using repeat-last-settings protocol
244 // across configure_streams() calls
245 parent->mRequestThread->configurationComplete(
246 parent->mIsConstrainedHighSpeedConfiguration, parent->mSessionParams,
247 parent->mGroupIdPhysicalCameraMap);
248
249 parent->internalUpdateStatusLocked(STATUS_CONFIGURED);
250
251 ALOGV("%s: Injection camera %s: Stream configuration complete", __FUNCTION__,
252 mInjectedCamId.string());
253
254 auto rc = parent->mPreparerThread->resume();
Cliff Wuc2ad9c82021-04-21 00:58:58 +0800255 if (rc != OK) {
256 ALOGE("%s: Injection camera %s: Preparer thread failed to resume!",
257 __FUNCTION__, mInjectedCamId.string());
258 return rc;
259 }
260
261 return OK;
262}
263
264void Camera3Device::Camera3DeviceInjectionMethods::injectionDisconnectImpl() {
265 ATRACE_CALL();
266 ALOGI("%s: Injection camera disconnect", __FUNCTION__);
Cliff Wud0476312021-07-27 20:15:55 +0800267 mIsStreamConfigCompleteButNotInjected = false;
268 mInjectionStreams.clear();
269 mInjectionConfig.streams = nullptr;
Cliff Wuc2ad9c82021-04-21 00:58:58 +0800270
271 mBackupHalInterface = nullptr;
272 HalInterface* interface = nullptr;
273 {
274 Mutex::Autolock lock(mInjectionLock);
275 if (mInjectedCamHalInterface != nullptr) {
276 interface = mInjectedCamHalInterface.get();
277 // Call close without internal mutex held, as the HAL close may need
278 // to wait on assorted callbacks,etc, to complete before it can
279 // return.
280 }
281 }
282
283 if (interface != nullptr) {
284 interface->close();
285 }
286
287 {
288 Mutex::Autolock lock(mInjectionLock);
289 if (mInjectedCamHalInterface != nullptr) {
290 mInjectedCamHalInterface->clear();
291 mInjectedCamHalInterface = nullptr;
292 }
293 }
294}
295
Cliff Wuc2ad9c82021-04-21 00:58:58 +0800296}; // namespace android