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