1 /*
2 * Copyright (C) 2022 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 "HidlCamera.h"
18
19 #include "AidlCameraStream.h"
20 #include "AidlDisplay.h"
21 #include "utils/include/Utils.h"
22
23 #include <android-base/logging.h>
24
25 namespace aidl::android::automotive::evs::implementation {
26
27 namespace hidlevs = ::android::hardware::automotive::evs;
28
29 using ::aidl::android::hardware::automotive::evs::BufferDesc;
30 using ::aidl::android::hardware::automotive::evs::CameraDesc;
31 using ::aidl::android::hardware::automotive::evs::CameraParam;
32 using ::aidl::android::hardware::automotive::evs::DisplayState;
33 using ::aidl::android::hardware::automotive::evs::EvsEventDesc;
34 using ::aidl::android::hardware::automotive::evs::EvsEventType;
35 using ::aidl::android::hardware::automotive::evs::EvsResult;
36 using ::aidl::android::hardware::automotive::evs::IEvsCameraStream;
37 using ::aidl::android::hardware::automotive::evs::IEvsDisplay;
38 using ::aidl::android::hardware::automotive::evs::ParameterRange;
39 using ::android::hardware::hidl_string;
40 using ::android::hardware::hidl_vec;
41 using ::android::hardware::Return;
42 using ::ndk::ScopedAStatus;
43
~HidlCamera()44 HidlCamera::~HidlCamera() {
45 mAidlCamera = nullptr;
46 mAidlStream = nullptr;
47 }
48
getCameraInfo(getCameraInfo_cb _hidl_cb)49 Return<void> HidlCamera::getCameraInfo(getCameraInfo_cb _hidl_cb) {
50 if (!mAidlCamera) {
51 LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
52 _hidl_cb({});
53 return {};
54 }
55
56 CameraDesc aidlDesc;
57 if (auto status = mAidlCamera->getCameraInfo(&aidlDesc); !status.isOk()) {
58 LOG(ERROR) << "Failed to get a camera information, status = "
59 << toString(static_cast<EvsResult>(status.getServiceSpecificError()));
60 _hidl_cb({});
61 return {};
62 }
63
64 _hidl_cb(std::move(Utils::makeToHidlV1_0(aidlDesc)));
65 return {};
66 }
67
setMaxFramesInFlight(uint32_t bufferCount)68 Return<hidlevs::V1_0::EvsResult> HidlCamera::setMaxFramesInFlight(uint32_t bufferCount) {
69 if (!mAidlCamera) {
70 LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
71 return hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR;
72 }
73
74 auto status = mAidlCamera->setMaxFramesInFlight(static_cast<int32_t>(bufferCount));
75 if (!status.isOk()) {
76 return hidlevs::V1_0::EvsResult::BUFFER_NOT_AVAILABLE;
77 }
78
79 return hidlevs::V1_0::EvsResult::OK;
80 }
81
startVideoStream(const::android::sp<hidlevs::V1_0::IEvsCameraStream> & stream)82 Return<hidlevs::V1_0::EvsResult> HidlCamera::startVideoStream(
83 const ::android::sp<hidlevs::V1_0::IEvsCameraStream>& stream) {
84 if (!mAidlCamera) {
85 LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
86 return hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR;
87 } else if (!stream) {
88 LOG(ERROR) << "A given HIDL IEvsCameraStream object is invalid.";
89 return hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR;
90 } else if (mAidlStream) {
91 LOG(WARNING) << "A video stream is already running.";
92 return hidlevs::V1_0::EvsResult::STREAM_ALREADY_RUNNING;
93 }
94
95 // Creates a wrapper object and requests a video stream
96 mAidlStream = ::ndk::SharedRefBase::make<AidlCameraStream>(stream);
97 if (auto status = mAidlCamera->startVideoStream(mAidlStream); !status.isOk()) {
98 return Utils::makeToHidl(static_cast<EvsResult>(status.getServiceSpecificError()));
99 }
100
101 return hidlevs::V1_0::EvsResult::OK;
102 }
103
doneWithFrame(const hidlevs::V1_0::BufferDesc & buffer)104 Return<void> HidlCamera::doneWithFrame(const hidlevs::V1_0::BufferDesc& buffer) {
105 if (!mAidlStream) {
106 LOG(ERROR) << "A reference to AIDL IEvsCameraStream object is invalid.";
107 return {};
108 }
109
110 BufferDesc aidlBuffer;
111 if (!mAidlStream->getBuffer(buffer.bufferId, &aidlBuffer)) {
112 LOG(ERROR) << "Ignores an unknown buffer " << buffer.bufferId;
113 return {};
114 }
115
116 std::vector<BufferDesc> buffersToReturn(1);
117 int bufferId = aidlBuffer.bufferId; // save pre move() for log message.
118 buffersToReturn[0] = std::move(aidlBuffer);
119 if (auto status = mAidlCamera->doneWithFrame(std::move(buffersToReturn)); !status.isOk()) {
120 LOG(WARNING) << "Failed to return a buffer " << bufferId << ", status = "
121 << toString(static_cast<EvsResult>(status.getServiceSpecificError()));
122 return {};
123 }
124
125 return {};
126 }
127
stopVideoStream()128 Return<void> HidlCamera::stopVideoStream() {
129 if (!mAidlCamera) {
130 LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
131 return {};
132 }
133
134 mAidlCamera->stopVideoStream();
135 mAidlStream = nullptr;
136 return {};
137 }
138
getExtendedInfo(uint32_t opaqueIdentifier)139 Return<int32_t> HidlCamera::getExtendedInfo(uint32_t opaqueIdentifier) {
140 if (!mAidlCamera) {
141 LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
142 return 0;
143 }
144
145 std::vector<uint8_t> value;
146 if (!mAidlCamera->getExtendedInfo(static_cast<int32_t>(opaqueIdentifier), &value).isOk() ||
147 value.size() < sizeof(int32_t)) {
148 return 0;
149 }
150
151 return *reinterpret_cast<int32_t*>(value.data());
152 }
153
setExtendedInfo(uint32_t opaqueIdentifier,int32_t opaqueValue)154 Return<hidlevs::V1_0::EvsResult> HidlCamera::setExtendedInfo(uint32_t opaqueIdentifier,
155 int32_t opaqueValue) {
156 if (!mAidlCamera) {
157 LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
158 return hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR;
159 }
160
161 std::vector<uint8_t> value(sizeof(int32_t));
162 *reinterpret_cast<int32_t*>(value.data()) = opaqueValue;
163 auto status = mAidlCamera->setExtendedInfo(static_cast<int32_t>(opaqueIdentifier), value);
164 if (!status.isOk()) {
165 return Utils::makeToHidl(static_cast<EvsResult>(status.getServiceSpecificError()));
166 }
167 return hidlevs::V1_0::EvsResult::OK;
168 }
169
170 // Methods from ::android::hardware::automotive::evs::V1_1::IEvsCamera follow.
getCameraInfo_1_1(getCameraInfo_1_1_cb _hidl_cb)171 Return<void> HidlCamera::getCameraInfo_1_1(getCameraInfo_1_1_cb _hidl_cb) {
172 if (!mAidlCamera) {
173 LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
174 _hidl_cb({});
175 return {};
176 }
177
178 CameraDesc aidlDesc;
179 if (auto status = mAidlCamera->getCameraInfo(&aidlDesc); !status.isOk()) {
180 LOG(ERROR) << "Failed to get a camera information, status = "
181 << toString(static_cast<EvsResult>(status.getServiceSpecificError()));
182 _hidl_cb({});
183 return {};
184 }
185
186 _hidl_cb(std::move(Utils::makeToHidlV1_1(aidlDesc)));
187 return {};
188 }
189
getPhysicalCameraInfo(const hidl_string & deviceId,getPhysicalCameraInfo_cb _hidl_cb)190 Return<void> HidlCamera::getPhysicalCameraInfo(const hidl_string& deviceId,
191 getPhysicalCameraInfo_cb _hidl_cb) {
192 if (!mAidlCamera) {
193 LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
194 _hidl_cb({});
195 return {};
196 }
197
198 CameraDesc aidlDesc;
199 if (auto status = mAidlCamera->getPhysicalCameraInfo(deviceId, &aidlDesc); !status.isOk()) {
200 LOG(ERROR) << "Failed to read information of a camera " << deviceId << ", status = "
201 << toString(static_cast<EvsResult>(status.getServiceSpecificError()));
202 _hidl_cb({});
203 return {};
204 }
205
206 _hidl_cb(Utils::makeToHidlV1_1(aidlDesc));
207 return {};
208 }
209
doneWithFrame_1_1(const hidl_vec<hidlevs::V1_1::BufferDesc> & buffers)210 Return<hidlevs::V1_0::EvsResult> HidlCamera::doneWithFrame_1_1(
211 const hidl_vec<hidlevs::V1_1::BufferDesc>& buffers) {
212 if (!mAidlStream) {
213 LOG(WARNING) << "A reference to AIDL IEvsCameraStream object is invalid.";
214 return hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR;
215 }
216
217 std::vector<BufferDesc> buffersToReturn(buffers.size());
218 for (auto i = 0; i < buffers.size(); ++i) {
219 BufferDesc aidlBuffer;
220 if (!mAidlStream->getBuffer(buffers[i].bufferId, &aidlBuffer)) {
221 LOG(WARNING) << "Ignores an unknown buffer " << buffers[i].bufferId;
222 continue;
223 }
224
225 buffersToReturn[i] = std::move(aidlBuffer);
226 }
227
228 if (auto status = mAidlCamera->doneWithFrame(std::move(buffersToReturn)); !status.isOk()) {
229 LOG(ERROR) << "Failed to return buffers, status = " << status.getServiceSpecificError();
230 return Utils::makeToHidl(static_cast<EvsResult>(status.getServiceSpecificError()));
231 }
232
233 return hidlevs::V1_0::EvsResult::OK;
234 }
235
setMaster()236 Return<hidlevs::V1_0::EvsResult> HidlCamera::setMaster() {
237 if (!mAidlCamera) {
238 LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
239 return hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR;
240 }
241
242 if (auto status = mAidlCamera->setPrimaryClient(); !status.isOk()) {
243 EvsResult err = static_cast<EvsResult>(status.getServiceSpecificError());
244 if (err == EvsResult::PERMISSION_DENIED) {
245 // HIDL EvsManager implementations return EvsResult::OWNERSHIP_LOST
246 // if the primary client exists already.
247 err = EvsResult::OWNERSHIP_LOST;
248 }
249 return Utils::makeToHidl(err);
250 }
251
252 return hidlevs::V1_0::EvsResult::OK;
253 }
254
forceMaster(const::android::sp<hidlevs::V1_0::IEvsDisplay> & display)255 Return<hidlevs::V1_0::EvsResult> HidlCamera::forceMaster(
256 const ::android::sp<hidlevs::V1_0::IEvsDisplay>& display) {
257 if (!mAidlCamera) {
258 LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
259 return hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR;
260 }
261
262 auto status = mAidlCamera->forcePrimaryClient(::ndk::SharedRefBase::make<AidlDisplay>(display));
263 if (!status.isOk()) {
264 return Utils::makeToHidl(static_cast<EvsResult>(status.getServiceSpecificError()));
265 }
266
267 return hidlevs::V1_0::EvsResult::OK;
268 }
269
unsetMaster()270 Return<hidlevs::V1_0::EvsResult> HidlCamera::unsetMaster() {
271 if (!mAidlCamera) {
272 LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
273 return hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR;
274 }
275
276 if (auto status = mAidlCamera->unsetPrimaryClient(); !status.isOk()) {
277 return Utils::makeToHidl(static_cast<EvsResult>(status.getServiceSpecificError()));
278 }
279
280 return hidlevs::V1_0::EvsResult::OK;
281 }
282
getParameterList(getParameterList_cb _hidl_cb)283 Return<void> HidlCamera::getParameterList(getParameterList_cb _hidl_cb) {
284 if (!mAidlCamera) {
285 LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
286 _hidl_cb({});
287 return {};
288 }
289
290 std::vector<CameraParam> aidlList;
291 if (auto status = mAidlCamera->getParameterList(&aidlList); !status.isOk()) {
292 LOG(ERROR) << "Failed to get a parameter list, status = "
293 << toString(static_cast<EvsResult>(status.getServiceSpecificError()));
294 _hidl_cb({});
295 return {};
296 }
297
298 hidl_vec<hidlevs::V1_1::CameraParam> hidlList;
299 hidlList.resize(aidlList.size());
300 for (auto i = 0; i < aidlList.size(); ++i) {
301 hidlList[i] = Utils::makeToHidl(aidlList[i]);
302 }
303 _hidl_cb(hidlList);
304 return {};
305 }
306
getIntParameterRange(hidlevs::V1_1::CameraParam id,getIntParameterRange_cb _hidl_cb)307 Return<void> HidlCamera::getIntParameterRange(hidlevs::V1_1::CameraParam id,
308 getIntParameterRange_cb _hidl_cb) {
309 if (!mAidlCamera) {
310 LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
311 _hidl_cb(0, 0, 0);
312 return {};
313 }
314
315 ParameterRange aidlRange;
316 if (auto status = mAidlCamera->getIntParameterRange(Utils::makeFromHidl(id), &aidlRange);
317 !status.isOk()) {
318 LOG(ERROR) << "Failed to get a parameter range, status = "
319 << toString(static_cast<EvsResult>(status.getServiceSpecificError()));
320 _hidl_cb(0, 0, 0);
321 return {};
322 }
323
324 _hidl_cb(aidlRange.min, aidlRange.max, aidlRange.step);
325 return {};
326 }
327
setIntParameter(hidlevs::V1_1::CameraParam id,int32_t value,setIntParameter_cb _hidl_cb)328 Return<void> HidlCamera::setIntParameter(hidlevs::V1_1::CameraParam id, int32_t value,
329 setIntParameter_cb _hidl_cb) {
330 if (!mAidlCamera) {
331 LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
332 _hidl_cb(hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR, {});
333 return {};
334 }
335
336 std::vector<int32_t> aidlValues;
337 auto status = mAidlCamera->setIntParameter(Utils::makeFromHidl(id), value, &aidlValues);
338 if (!status.isOk()) {
339 EvsResult err = static_cast<EvsResult>(status.getServiceSpecificError());
340 if (err == EvsResult::PERMISSION_DENIED) {
341 // HIDL EvsManager implementations return EvsResult::INVALID_ARG if
342 // the client is not permitted to change parameters.
343 err = EvsResult::INVALID_ARG;
344 }
345 _hidl_cb(Utils::makeToHidl(err), {value});
346 return {};
347 }
348
349 _hidl_cb(hidlevs::V1_0::EvsResult::OK, aidlValues);
350 return {};
351 }
352
getIntParameter(hidlevs::V1_1::CameraParam id,getIntParameter_cb _hidl_cb)353 Return<void> HidlCamera::getIntParameter(hidlevs::V1_1::CameraParam id,
354 getIntParameter_cb _hidl_cb) {
355 if (!mAidlCamera) {
356 LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
357 _hidl_cb(hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR, {});
358 return {};
359 }
360
361 std::vector<int32_t> aidlValues;
362 auto status = mAidlCamera->getIntParameter(Utils::makeFromHidl(id), &aidlValues);
363 if (!status.isOk()) {
364 _hidl_cb(Utils::makeToHidl(static_cast<EvsResult>(status.getServiceSpecificError())), {});
365 return {};
366 }
367
368 _hidl_cb(hidlevs::V1_0::EvsResult::OK, aidlValues);
369 return {};
370 }
371
setExtendedInfo_1_1(uint32_t opaqueIdentifier,const hidl_vec<uint8_t> & opaqueValue)372 Return<hidlevs::V1_0::EvsResult> HidlCamera::setExtendedInfo_1_1(
373 uint32_t opaqueIdentifier, const hidl_vec<uint8_t>& opaqueValue) {
374 if (!mAidlCamera) {
375 LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
376 return hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR;
377 }
378
379 std::vector<uint8_t> value(opaqueValue);
380 auto status = mAidlCamera->setExtendedInfo(static_cast<int32_t>(opaqueIdentifier), value);
381 if (!status.isOk()) {
382 return Utils::makeToHidl(static_cast<EvsResult>(status.getServiceSpecificError()));
383 }
384
385 return hidlevs::V1_0::EvsResult::OK;
386 }
387
getExtendedInfo_1_1(uint32_t opaqueIdentifier,getExtendedInfo_1_1_cb _hidl_cb)388 Return<void> HidlCamera::getExtendedInfo_1_1(uint32_t opaqueIdentifier,
389 getExtendedInfo_1_1_cb _hidl_cb) {
390 if (!mAidlCamera) {
391 LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
392 _hidl_cb(hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR, {});
393 return {};
394 }
395
396 std::vector<uint8_t> value;
397 auto status = mAidlCamera->getExtendedInfo(static_cast<int32_t>(opaqueIdentifier), &value);
398 if (!status.isOk()) {
399 _hidl_cb(Utils::makeToHidl(static_cast<EvsResult>(status.getServiceSpecificError())), {});
400 return {};
401 }
402
403 _hidl_cb(hidlevs::V1_0::EvsResult::OK, value);
404 return {};
405 }
406
importExternalBuffers(const hidl_vec<hidlevs::V1_1::BufferDesc> & buffers,importExternalBuffers_cb _hidl_cb)407 Return<void> HidlCamera::importExternalBuffers(const hidl_vec<hidlevs::V1_1::BufferDesc>& buffers,
408 importExternalBuffers_cb _hidl_cb) {
409 if (!mAidlCamera) {
410 LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
411 _hidl_cb(hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR, 0);
412 return {};
413 }
414
415 std::vector<BufferDesc> aidlBuffers(buffers.size());
416 for (auto i = 0; i < buffers.size(); ++i) {
417 aidlBuffers[i] = std::move(Utils::makeFromHidl(buffers[i]));
418 }
419
420 int32_t delta = 0;
421 if (auto status = mAidlCamera->importExternalBuffers(aidlBuffers, &delta); !status.isOk()) {
422 _hidl_cb(Utils::makeToHidl(static_cast<EvsResult>(status.getServiceSpecificError())),
423 delta);
424 return {};
425 }
426
427 _hidl_cb(hidlevs::V1_0::EvsResult::OK, delta);
428 return {};
429 }
430
431 } // namespace aidl::android::automotive::evs::implementation
432