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 
Camera3DeviceInjectionMethods(wp<Camera3Device> parent)29 Camera3Device::Camera3DeviceInjectionMethods::Camera3DeviceInjectionMethods(
30         wp<Camera3Device> parent)
31         : mParent(parent) {
32     ALOGV("%s: Created injection camera methods", __FUNCTION__);
33 }
34 
~Camera3DeviceInjectionMethods()35 Camera3Device::Camera3DeviceInjectionMethods::~Camera3DeviceInjectionMethods() {
36     ALOGV("%s: Removed injection camera methods", __FUNCTION__);
37     injectionDisconnectImpl();
38 }
39 
injectCamera(camera3::camera_stream_configuration & injectionConfig,const std::vector<uint32_t> & injectionBufferSizes)40 status_t Camera3Device::Camera3DeviceInjectionMethods::injectCamera(
41         camera3::camera_stream_configuration& injectionConfig,
42         const std::vector<uint32_t>& injectionBufferSizes) {
43     status_t res = NO_ERROR;
44 
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__);
61         res = parent->internalPauseAndWaitLocked(maxExpectedDuration,
62                                                  /*requestThreadInvocation*/false);
63         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.
101         parent->internalResumeLocked();
102     }
103 
104     return OK;
105 }
106 
stopInjection()107 status_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__);
121         res = parent->internalPauseAndWaitLocked(maxExpectedDuration,
122                                                  /*requestThreadInvocation*/false);
123         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.
142         parent->internalResumeLocked();
143     }
144 
145     return OK;
146 }
147 
isInjecting()148 bool Camera3Device::Camera3DeviceInjectionMethods::isInjecting() {
149     if (mInjectedCamHalInterface == nullptr) {
150         return false;
151     } else {
152         return true;
153     }
154 }
155 
isStreamConfigCompleteButNotInjected()156 bool Camera3Device::Camera3DeviceInjectionMethods::isStreamConfigCompleteButNotInjected() {
157     return mIsStreamConfigCompleteButNotInjected;
158 }
159 
getInjectedCamId() const160 const std::string& Camera3Device::Camera3DeviceInjectionMethods::getInjectedCamId()
161         const {
162     return mInjectedCamId;
163 }
164 
getInjectionConfig(camera3::camera_stream_configuration * injectionConfig,std::vector<uint32_t> * injectionBufferSizes)165 void 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 
storeInjectionConfig(const camera3::camera_stream_configuration & injectionConfig,const std::vector<uint32_t> & injectionBufferSizes)177 void Camera3Device::Camera3DeviceInjectionMethods::storeInjectionConfig(
178         const camera3::camera_stream_configuration& injectionConfig,
179         const std::vector<uint32_t>& injectionBufferSizes) {
180     mIsStreamConfigCompleteButNotInjected = true;
181     mInjectionConfig = injectionConfig;
182     mInjectionStreams.clear();
183     for (size_t i = 0; i < injectionConfig.num_streams; i++) {
184         mInjectionStreams.push_back(injectionConfig.streams[i]);
185     }
186     mInjectionConfig.streams = mInjectionStreams.editArray();
187     mInjectionBufferSizes = injectionBufferSizes;
188 }
189 
injectionConfigureStreams(camera3::camera_stream_configuration & injectionConfig,const std::vector<uint32_t> & injectionBufferSizes)190 status_t Camera3Device::Camera3DeviceInjectionMethods::injectionConfigureStreams(
191         camera3::camera_stream_configuration& injectionConfig,
192         const std::vector<uint32_t>& injectionBufferSizes) {
193     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.c_str());
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.c_str());
253 
254     auto rc = parent->mPreparerThread->resume();
255     if (rc != OK) {
256         ALOGE("%s: Injection camera %s: Preparer thread failed to resume!",
257                  __FUNCTION__, mInjectedCamId.c_str());
258         return rc;
259     }
260 
261     return OK;
262 }
263 
injectionDisconnectImpl()264 void Camera3Device::Camera3DeviceInjectionMethods::injectionDisconnectImpl() {
265     ATRACE_CALL();
266     ALOGI("%s: Injection camera disconnect", __FUNCTION__);
267     mIsStreamConfigCompleteButNotInjected = false;
268     mInjectionStreams.clear();
269     mInjectionConfig.streams = nullptr;
270 
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 
296 };  // namespace android
297