1 /*
2  * Copyright (C) 2018 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 #include <android/hardware/camera/device/3.2/types.h>
18 #include <cutils/properties.h>
19 #include <gui/Surface.h>
20 #include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h>
21 
22 #include <hidl/AidlCameraDeviceCallbacks.h>
23 #include <hidl/Convert.h>
24 #include <hidl/HidlCameraDeviceUser.h>
25 #include <android/hardware/camera/device/3.2/types.h>
26 
27 namespace android {
28 namespace frameworks {
29 namespace cameraservice {
30 namespace device {
31 namespace V2_0 {
32 namespace implementation {
33 
34 using hardware::cameraservice::utils::conversion::convertToHidl;
35 using hardware::cameraservice::utils::conversion::convertFromHidl;
36 using hardware::cameraservice::utils::conversion::B2HStatus;
37 
38 using hardware::graphics::bufferqueue::V1_0::utils::H2BGraphicBufferProducer;
39 using hardware::hidl_vec;
40 using hardware::Return;
41 using hardware::Void;
42 using HSubmitInfo = device::V2_0::SubmitInfo;
43 using hardware::camera2::params::OutputConfiguration;
44 using hardware::camera2::params::SessionConfiguration;
45 
46 static constexpr int32_t CAMERA_REQUEST_METADATA_QUEUE_SIZE = 1 << 20 /* 1 MB */;
47 static constexpr int32_t CAMERA_RESULT_METADATA_QUEUE_SIZE = 1 << 20 /* 1 MB */;
48 
disconnect()49 Return<void> HidlCameraDeviceUser::disconnect() {
50     mDeviceRemote->disconnect();
51     return Void();
52 }
53 
HidlCameraDeviceUser(const sp<hardware::camera2::ICameraDeviceUser> & deviceRemote)54 HidlCameraDeviceUser::HidlCameraDeviceUser(
55     const sp<hardware::camera2::ICameraDeviceUser> &deviceRemote)
56   : mDeviceRemote(deviceRemote) {
57     mInitSuccess = initDevice();
58 }
59 
initDevice()60 bool HidlCameraDeviceUser::initDevice() {
61     // TODO: Get request and result metadata queue size from a system property.
62     int32_t reqFMQSize = CAMERA_REQUEST_METADATA_QUEUE_SIZE;
63 
64     mCaptureRequestMetadataQueue =
65         std::make_unique<CaptureRequestMetadataQueue>(static_cast<size_t>(reqFMQSize),
66                                                       false /* non blocking */);
67     if (!mCaptureRequestMetadataQueue->isValid()) {
68         ALOGE("%s: invalid request fmq", __FUNCTION__);
69         return false;
70     }
71 
72     int32_t resFMQSize = CAMERA_RESULT_METADATA_QUEUE_SIZE;
73     mCaptureResultMetadataQueue =
74         std::make_shared<CaptureResultMetadataQueue>(static_cast<size_t>(resFMQSize),
75                                                      false /* non blocking */);
76     if (!mCaptureResultMetadataQueue->isValid()) {
77         ALOGE("%s: invalid result fmq", __FUNCTION__);
78         return false;
79     }
80     return true;
81 }
82 
getCaptureRequestMetadataQueue(getCaptureRequestMetadataQueue_cb _hidl_cb)83 Return<void> HidlCameraDeviceUser::getCaptureRequestMetadataQueue(
84     getCaptureRequestMetadataQueue_cb _hidl_cb) {
85     if (mInitSuccess) {
86         _hidl_cb(*mCaptureRequestMetadataQueue->getDesc());
87     }
88     return Void();
89 }
90 
getCaptureResultMetadataQueue(getCaptureResultMetadataQueue_cb _hidl_cb)91 Return<void> HidlCameraDeviceUser::getCaptureResultMetadataQueue(
92     getCaptureResultMetadataQueue_cb _hidl_cb) {
93     if (mInitSuccess) {
94         _hidl_cb(*mCaptureResultMetadataQueue->getDesc());
95     }
96     return Void();
97 }
98 
99 /**
100  * To be used only by submitRequestList implementation, since it requires
101  * clients to call this method serially, incase fmq is used to send metadata.
102  */
copyPhysicalCameraSettings(const hidl_vec<HPhysicalCameraSettings> & hPhysicalCameraSettings,std::vector<CaptureRequest::PhysicalCameraSettings> * physicalCameraSettings)103 bool HidlCameraDeviceUser::copyPhysicalCameraSettings(
104     const hidl_vec<HPhysicalCameraSettings> &hPhysicalCameraSettings,
105     std::vector<CaptureRequest::PhysicalCameraSettings> *physicalCameraSettings) {
106     bool converted = false;
107     for (auto &e : hPhysicalCameraSettings) {
108         physicalCameraSettings->emplace_back();
109         CaptureRequest::PhysicalCameraSettings &physicalCameraSetting =
110             physicalCameraSettings->back();
111         physicalCameraSetting.id = e.id.c_str();
112 
113         // Read the settings either from the fmq or straightaway from the
114         // request. We don't need any synchronization, since submitRequestList
115         // is guaranteed to be called serially by the client if it decides to
116         // use fmq.
117         if (e.settings.getDiscriminator() ==
118             FmqSizeOrMetadata::hidl_discriminator::fmqMetadataSize) {
119             /**
120              * Get settings from the fmq.
121              */
122             HCameraMetadata settingsFmq;
123             settingsFmq.resize(e.settings.fmqMetadataSize());
124             bool read = mCaptureRequestMetadataQueue->read(settingsFmq.data(),
125                                                            e.settings.fmqMetadataSize());
126             if (!read) {
127                 ALOGE("%s capture request settings could't be read from fmq size",
128                       __FUNCTION__);
129                 converted = false;
130             } else {
131                 converted = convertFromHidl(settingsFmq, &physicalCameraSetting.settings);
132             }
133         } else {
134             /**
135              * The settings metadata is contained in request settings field.
136              */
137             converted =
138                 convertFromHidl(e.settings.metadata(),
139                                 &physicalCameraSetting.settings);
140         }
141         if (!converted) {
142           ALOGE("%s: Unable to convert physicalCameraSettings from HIDL to AIDL.", __FUNCTION__);
143           return false;
144         }
145     }
146     return true;
147 }
148 
convertRequestFromHidl(const HCaptureRequest & hRequest,CaptureRequest * request)149 bool HidlCameraDeviceUser::convertRequestFromHidl(const HCaptureRequest &hRequest,
150                                                   CaptureRequest *request) {
151     // No reprocessing support.
152     request->mIsReprocess = false;
153     for (const auto &streamAndWindowId : hRequest.streamAndWindowIds) {
154         request->mStreamIdxList.push_back(streamAndWindowId.streamId);
155         request->mSurfaceIdxList.push_back(streamAndWindowId.windowId);
156     }
157     return copyPhysicalCameraSettings(hRequest.physicalCameraSettings,
158                                       &(request->mPhysicalCameraSettings));
159 }
160 
submitRequestList(const hidl_vec<HCaptureRequest> & hRequestList,bool streaming,submitRequestList_cb _hidl_cb)161 Return<void> HidlCameraDeviceUser::submitRequestList(const hidl_vec<HCaptureRequest>& hRequestList,
162                                                      bool streaming,
163                                                      submitRequestList_cb _hidl_cb) {
164     hardware::camera2::utils::SubmitInfo submitInfo;
165     HSubmitInfo hSubmitInfo;
166     /**
167      * Create AIDL CaptureRequest from requestList and graphicBufferProducers.
168      */
169     std::vector<hardware::camera2::CaptureRequest> requests;
170     for (auto &hRequest : hRequestList) {
171         requests.emplace_back();
172         auto &request = requests.back();
173         if (!convertRequestFromHidl(hRequest, &request)) {
174             _hidl_cb(HStatus::ILLEGAL_ARGUMENT, hSubmitInfo);
175             return Void();
176         }
177     }
178     mDeviceRemote->submitRequestList(requests, streaming, &submitInfo);
179     mRequestId = submitInfo.mRequestId;
180     convertToHidl(submitInfo, &hSubmitInfo);
181     _hidl_cb(HStatus::NO_ERROR, hSubmitInfo);
182     return Void();
183 }
184 
cancelRepeatingRequest(cancelRepeatingRequest_cb _hidl_cb)185 Return<void> HidlCameraDeviceUser::cancelRepeatingRequest(cancelRepeatingRequest_cb _hidl_cb) {
186     int64_t lastFrameNumber = 0;
187     binder::Status ret = mDeviceRemote->cancelRequest(mRequestId, &lastFrameNumber);
188     _hidl_cb(B2HStatus(ret), lastFrameNumber);
189     return Void();
190 }
191 
beginConfigure()192 Return<HStatus> HidlCameraDeviceUser::beginConfigure() {
193     binder::Status ret = mDeviceRemote->beginConfigure();
194     return B2HStatus(ret);
195 }
196 
endConfigure(StreamConfigurationMode operatingMode,const hidl_vec<uint8_t> & sessionParams)197 Return<HStatus> HidlCameraDeviceUser::endConfigure(StreamConfigurationMode operatingMode,
198                                                    const hidl_vec<uint8_t>& sessionParams) {
199     android::CameraMetadata cameraMetadata;
200     if (!convertFromHidl(sessionParams, &cameraMetadata)) {
201         return HStatus::ILLEGAL_ARGUMENT;
202     }
203 
204     binder::Status ret = mDeviceRemote->endConfigure(convertFromHidl(operatingMode),
205                                                      cameraMetadata);
206     return B2HStatus(ret);
207 }
208 
deleteStream(int32_t streamId)209 Return<HStatus> HidlCameraDeviceUser::deleteStream(int32_t streamId) {
210     binder::Status ret = mDeviceRemote->deleteStream(streamId);
211     return B2HStatus(ret);
212 }
213 
createStream(const HOutputConfiguration & hOutputConfiguration,createStream_cb hidl_cb_)214 Return<void> HidlCameraDeviceUser::createStream(const HOutputConfiguration& hOutputConfiguration,
215                                                 createStream_cb hidl_cb_) {
216     OutputConfiguration outputConfiguration =
217         convertFromHidl(hOutputConfiguration);
218     int32_t newStreamId = 0;
219     binder::Status ret = mDeviceRemote->createStream(outputConfiguration, &newStreamId);
220     HStatus status = B2HStatus(ret);
221     hidl_cb_(status, newStreamId);
222     return Void();
223 }
224 
createDefaultRequest(TemplateId templateId,createDefaultRequest_cb _hidl_cb)225 Return<void> HidlCameraDeviceUser::createDefaultRequest(TemplateId templateId,
226                                                         createDefaultRequest_cb _hidl_cb) {
227     android::CameraMetadata cameraMetadata;
228     binder::Status ret = mDeviceRemote->createDefaultRequest(convertFromHidl(templateId),
229                                                              &cameraMetadata);
230     HStatus hStatus = B2HStatus(ret);
231     HCameraMetadata hidlMetadata;
232     const camera_metadata_t *rawMetadata = cameraMetadata.getAndLock();
233     convertToHidl(rawMetadata, &hidlMetadata);
234     _hidl_cb(hStatus, hidlMetadata);
235     cameraMetadata.unlock(rawMetadata);
236     return Void();
237 }
238 
waitUntilIdle()239 Return<HStatus> HidlCameraDeviceUser::waitUntilIdle() {
240     binder::Status ret = mDeviceRemote->waitUntilIdle();
241     return B2HStatus(ret);
242 }
243 
flush(flush_cb _hidl_cb)244 Return<void> HidlCameraDeviceUser::flush(flush_cb _hidl_cb) {
245     int64_t lastFrameNumber = 0;
246     binder::Status ret = mDeviceRemote->flush(&lastFrameNumber);
247     _hidl_cb(B2HStatus(ret),lastFrameNumber);
248     return Void();
249 }
250 
updateOutputConfiguration(int32_t streamId,const HOutputConfiguration & hOutputConfiguration)251 Return<HStatus> HidlCameraDeviceUser::updateOutputConfiguration(
252     int32_t streamId,
253     const HOutputConfiguration& hOutputConfiguration) {
254     OutputConfiguration outputConfiguration = convertFromHidl(hOutputConfiguration);
255     binder::Status ret = mDeviceRemote->updateOutputConfiguration(streamId, outputConfiguration);
256     return B2HStatus(ret);
257 }
258 
isSessionConfigurationSupported(const HSessionConfiguration & hSessionConfiguration,isSessionConfigurationSupported_cb _hidl_cb)259 Return<void> HidlCameraDeviceUser::isSessionConfigurationSupported(
260     const HSessionConfiguration& hSessionConfiguration,
261     isSessionConfigurationSupported_cb _hidl_cb) {
262     bool supported = false;
263     SessionConfiguration sessionConfiguration = convertFromHidl(hSessionConfiguration);
264     binder::Status ret = mDeviceRemote->isSessionConfigurationSupported(
265             sessionConfiguration, &supported);
266     HStatus status = B2HStatus(ret);
267     _hidl_cb(status, supported);
268     return Void();
269 }
270 
271 } // implementation
272 } // V2_0
273 } // device
274 } // cameraservice
275 } // frameworks
276 } // android
277