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 return {};
136 }
137
getExtendedInfo(uint32_t opaqueIdentifier)138 Return<int32_t> HidlCamera::getExtendedInfo(uint32_t opaqueIdentifier) {
139 if (!mAidlCamera) {
140 LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
141 return 0;
142 }
143
144 std::vector<uint8_t> value;
145 if (!mAidlCamera->getExtendedInfo(static_cast<int32_t>(opaqueIdentifier), &value).isOk() ||
146 value.size() < sizeof(int32_t)) {
147 return 0;
148 }
149
150 return *reinterpret_cast<int32_t*>(value.data());
151 }
152
setExtendedInfo(uint32_t opaqueIdentifier,int32_t opaqueValue)153 Return<hidlevs::V1_0::EvsResult> HidlCamera::setExtendedInfo(uint32_t opaqueIdentifier,
154 int32_t opaqueValue) {
155 if (!mAidlCamera) {
156 LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
157 return hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR;
158 }
159
160 std::vector<uint8_t> value(sizeof(int32_t));
161 *reinterpret_cast<int32_t*>(value.data()) = opaqueValue;
162 auto status = mAidlCamera->setExtendedInfo(static_cast<int32_t>(opaqueIdentifier), value);
163 if (!status.isOk()) {
164 return Utils::makeToHidl(static_cast<EvsResult>(status.getServiceSpecificError()));
165 }
166 return hidlevs::V1_0::EvsResult::OK;
167 }
168
169 // Methods from ::android::hardware::automotive::evs::V1_1::IEvsCamera follow.
getCameraInfo_1_1(getCameraInfo_1_1_cb _hidl_cb)170 Return<void> HidlCamera::getCameraInfo_1_1(getCameraInfo_1_1_cb _hidl_cb) {
171 if (!mAidlCamera) {
172 LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
173 _hidl_cb({});
174 return {};
175 }
176
177 CameraDesc aidlDesc;
178 if (auto status = mAidlCamera->getCameraInfo(&aidlDesc); !status.isOk()) {
179 LOG(ERROR) << "Failed to get a camera information, status = "
180 << toString(static_cast<EvsResult>(status.getServiceSpecificError()));
181 _hidl_cb({});
182 return {};
183 }
184
185 _hidl_cb(std::move(Utils::makeToHidlV1_1(aidlDesc)));
186 return {};
187 }
188
getPhysicalCameraInfo(const hidl_string & deviceId,getPhysicalCameraInfo_cb _hidl_cb)189 Return<void> HidlCamera::getPhysicalCameraInfo(const hidl_string& deviceId,
190 getPhysicalCameraInfo_cb _hidl_cb) {
191 if (!mAidlCamera) {
192 LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
193 _hidl_cb({});
194 return {};
195 }
196
197 CameraDesc aidlDesc;
198 if (auto status = mAidlCamera->getPhysicalCameraInfo(deviceId, &aidlDesc); !status.isOk()) {
199 LOG(ERROR) << "Failed to read information of a camera " << deviceId << ", status = "
200 << toString(static_cast<EvsResult>(status.getServiceSpecificError()));
201 _hidl_cb({});
202 return {};
203 }
204
205 _hidl_cb(Utils::makeToHidlV1_1(aidlDesc));
206 return {};
207 }
208
doneWithFrame_1_1(const hidl_vec<hidlevs::V1_1::BufferDesc> & buffers)209 Return<hidlevs::V1_0::EvsResult> HidlCamera::doneWithFrame_1_1(
210 const hidl_vec<hidlevs::V1_1::BufferDesc>& buffers) {
211 if (!mAidlStream) {
212 LOG(WARNING) << "A reference to AIDL IEvsCameraStream object is invalid.";
213 return hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR;
214 }
215
216 std::vector<BufferDesc> buffersToReturn(buffers.size());
217 for (auto i = 0; i < buffers.size(); ++i) {
218 BufferDesc aidlBuffer;
219 if (!mAidlStream->getBuffer(buffers[i].bufferId, &aidlBuffer)) {
220 LOG(WARNING) << "Ignores an unknown buffer " << buffers[i].bufferId;
221 continue;
222 }
223
224 buffersToReturn[i] = std::move(aidlBuffer);
225 }
226
227 if (auto status = mAidlCamera->doneWithFrame(std::move(buffersToReturn)); !status.isOk()) {
228 LOG(ERROR) << "Failed to return buffers, status = " << status.getServiceSpecificError();
229 return Utils::makeToHidl(static_cast<EvsResult>(status.getServiceSpecificError()));
230 }
231
232 return hidlevs::V1_0::EvsResult::OK;
233 }
234
setMaster()235 Return<hidlevs::V1_0::EvsResult> HidlCamera::setMaster() {
236 if (!mAidlCamera) {
237 LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
238 return hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR;
239 }
240
241 if (auto status = mAidlCamera->setPrimaryClient(); !status.isOk()) {
242 EvsResult err = static_cast<EvsResult>(status.getServiceSpecificError());
243 if (err == EvsResult::PERMISSION_DENIED) {
244 // HIDL EvsManager implementations return EvsResult::OWNERSHIP_LOST
245 // if the primary client exists already.
246 err = EvsResult::OWNERSHIP_LOST;
247 }
248 return Utils::makeToHidl(err);
249 }
250
251 return hidlevs::V1_0::EvsResult::OK;
252 }
253
forceMaster(const::android::sp<hidlevs::V1_0::IEvsDisplay> & display)254 Return<hidlevs::V1_0::EvsResult> HidlCamera::forceMaster(
255 const ::android::sp<hidlevs::V1_0::IEvsDisplay>& display) {
256 if (!mAidlCamera) {
257 LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
258 return hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR;
259 }
260
261 auto status = mAidlCamera->forcePrimaryClient(::ndk::SharedRefBase::make<AidlDisplay>(display));
262 if (!status.isOk()) {
263 return Utils::makeToHidl(static_cast<EvsResult>(status.getServiceSpecificError()));
264 }
265
266 return hidlevs::V1_0::EvsResult::OK;
267 }
268
unsetMaster()269 Return<hidlevs::V1_0::EvsResult> HidlCamera::unsetMaster() {
270 if (!mAidlCamera) {
271 LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
272 return hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR;
273 }
274
275 if (auto status = mAidlCamera->unsetPrimaryClient(); !status.isOk()) {
276 return Utils::makeToHidl(static_cast<EvsResult>(status.getServiceSpecificError()));
277 }
278
279 return hidlevs::V1_0::EvsResult::OK;
280 }
281
getParameterList(getParameterList_cb _hidl_cb)282 Return<void> HidlCamera::getParameterList(getParameterList_cb _hidl_cb) {
283 if (!mAidlCamera) {
284 LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
285 _hidl_cb({});
286 return {};
287 }
288
289 std::vector<CameraParam> aidlList;
290 if (auto status = mAidlCamera->getParameterList(&aidlList); !status.isOk()) {
291 LOG(ERROR) << "Failed to get a parameter list, status = "
292 << toString(static_cast<EvsResult>(status.getServiceSpecificError()));
293 _hidl_cb({});
294 return {};
295 }
296
297 hidl_vec<hidlevs::V1_1::CameraParam> hidlList;
298 hidlList.resize(aidlList.size());
299 for (auto i = 0; i < aidlList.size(); ++i) {
300 hidlList[i] = Utils::makeToHidl(aidlList[i]);
301 }
302 _hidl_cb(hidlList);
303 return {};
304 }
305
getIntParameterRange(hidlevs::V1_1::CameraParam id,getIntParameterRange_cb _hidl_cb)306 Return<void> HidlCamera::getIntParameterRange(hidlevs::V1_1::CameraParam id,
307 getIntParameterRange_cb _hidl_cb) {
308 if (!mAidlCamera) {
309 LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
310 _hidl_cb(0, 0, 0);
311 return {};
312 }
313
314 ParameterRange aidlRange;
315 if (auto status = mAidlCamera->getIntParameterRange(Utils::makeFromHidl(id), &aidlRange);
316 !status.isOk()) {
317 LOG(ERROR) << "Failed to get a parameter range, status = "
318 << toString(static_cast<EvsResult>(status.getServiceSpecificError()));
319 _hidl_cb(0, 0, 0);
320 return {};
321 }
322
323 _hidl_cb(aidlRange.min, aidlRange.max, aidlRange.step);
324 return {};
325 }
326
setIntParameter(hidlevs::V1_1::CameraParam id,int32_t value,setIntParameter_cb _hidl_cb)327 Return<void> HidlCamera::setIntParameter(hidlevs::V1_1::CameraParam id, int32_t value,
328 setIntParameter_cb _hidl_cb) {
329 if (!mAidlCamera) {
330 LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
331 _hidl_cb(hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR, {});
332 return {};
333 }
334
335 std::vector<int32_t> aidlValues;
336 auto status = mAidlCamera->setIntParameter(Utils::makeFromHidl(id), value, &aidlValues);
337 if (!status.isOk()) {
338 EvsResult err = static_cast<EvsResult>(status.getServiceSpecificError());
339 if (err == EvsResult::PERMISSION_DENIED) {
340 // HIDL EvsManager implementations return EvsResult::INVALID_ARG if
341 // the client is not permitted to change parameters.
342 err = EvsResult::INVALID_ARG;
343 }
344 _hidl_cb(Utils::makeToHidl(err), {value});
345 return {};
346 }
347
348 _hidl_cb(hidlevs::V1_0::EvsResult::OK, aidlValues);
349 return {};
350 }
351
getIntParameter(hidlevs::V1_1::CameraParam id,getIntParameter_cb _hidl_cb)352 Return<void> HidlCamera::getIntParameter(hidlevs::V1_1::CameraParam id,
353 getIntParameter_cb _hidl_cb) {
354 if (!mAidlCamera) {
355 LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
356 _hidl_cb(hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR, {});
357 return {};
358 }
359
360 std::vector<int32_t> aidlValues;
361 auto status = mAidlCamera->getIntParameter(Utils::makeFromHidl(id), &aidlValues);
362 if (!status.isOk()) {
363 _hidl_cb(Utils::makeToHidl(static_cast<EvsResult>(status.getServiceSpecificError())), {});
364 return {};
365 }
366
367 _hidl_cb(hidlevs::V1_0::EvsResult::OK, aidlValues);
368 return {};
369 }
370
setExtendedInfo_1_1(uint32_t opaqueIdentifier,const hidl_vec<uint8_t> & opaqueValue)371 Return<hidlevs::V1_0::EvsResult> HidlCamera::setExtendedInfo_1_1(
372 uint32_t opaqueIdentifier, const hidl_vec<uint8_t>& opaqueValue) {
373 if (!mAidlCamera) {
374 LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
375 return hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR;
376 }
377
378 std::vector<uint8_t> value(opaqueValue);
379 auto status = mAidlCamera->setExtendedInfo(static_cast<int32_t>(opaqueIdentifier), value);
380 if (!status.isOk()) {
381 return Utils::makeToHidl(static_cast<EvsResult>(status.getServiceSpecificError()));
382 }
383
384 return hidlevs::V1_0::EvsResult::OK;
385 }
386
getExtendedInfo_1_1(uint32_t opaqueIdentifier,getExtendedInfo_1_1_cb _hidl_cb)387 Return<void> HidlCamera::getExtendedInfo_1_1(uint32_t opaqueIdentifier,
388 getExtendedInfo_1_1_cb _hidl_cb) {
389 if (!mAidlCamera) {
390 LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
391 _hidl_cb(hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR, {});
392 return {};
393 }
394
395 std::vector<uint8_t> value;
396 auto status = mAidlCamera->getExtendedInfo(static_cast<int32_t>(opaqueIdentifier), &value);
397 if (!status.isOk()) {
398 _hidl_cb(Utils::makeToHidl(static_cast<EvsResult>(status.getServiceSpecificError())), {});
399 return {};
400 }
401
402 _hidl_cb(hidlevs::V1_0::EvsResult::OK, value);
403 return {};
404 }
405
importExternalBuffers(const hidl_vec<hidlevs::V1_1::BufferDesc> & buffers,importExternalBuffers_cb _hidl_cb)406 Return<void> HidlCamera::importExternalBuffers(const hidl_vec<hidlevs::V1_1::BufferDesc>& buffers,
407 importExternalBuffers_cb _hidl_cb) {
408 if (!mAidlCamera) {
409 LOG(ERROR) << "A reference to AIDL IEvsCamera object is invalid.";
410 _hidl_cb(hidlevs::V1_0::EvsResult::UNDERLYING_SERVICE_ERROR, 0);
411 return {};
412 }
413
414 std::vector<BufferDesc> aidlBuffers(buffers.size());
415 for (auto i = 0; i < buffers.size(); ++i) {
416 aidlBuffers[i] = std::move(Utils::makeFromHidl(buffers[i]));
417 }
418
419 int32_t delta = 0;
420 if (auto status = mAidlCamera->importExternalBuffers(aidlBuffers, &delta); !status.isOk()) {
421 _hidl_cb(Utils::makeToHidl(static_cast<EvsResult>(status.getServiceSpecificError())),
422 delta);
423 return {};
424 }
425
426 _hidl_cb(hidlevs::V1_0::EvsResult::OK, delta);
427 return {};
428 }
429
430 } // namespace aidl::android::automotive::evs::implementation
431