• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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