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 "AidlEnumerator.h"
18
19 #include "AidlCamera.h"
20 #include "AidlDisplay.h"
21 #include "Constants.h"
22 #include "utils/include/Utils.h"
23
24 #include <aidl/android/hardware/automotive/evs/Rotation.h>
25 #include <aidl/android/hardware/automotive/evs/StreamType.h>
26 #include <android-base/logging.h>
27 #include <android/binder_manager.h>
28
29 #include <limits>
30
31 namespace {
32
33 using ::aidl::android::hardware::automotive::evs::CameraDesc;
34 using ::aidl::android::hardware::automotive::evs::DisplayState;
35 using ::aidl::android::hardware::automotive::evs::EvsResult;
36 using ::aidl::android::hardware::automotive::evs::IEvsCamera;
37 using ::aidl::android::hardware::automotive::evs::IEvsDisplay;
38 using ::aidl::android::hardware::automotive::evs::IEvsEnumeratorStatusCallback;
39 using ::aidl::android::hardware::automotive::evs::IEvsUltrasonicsArray;
40 using ::aidl::android::hardware::automotive::evs::Rotation;
41 using ::aidl::android::hardware::automotive::evs::Stream;
42 using ::aidl::android::hardware::automotive::evs::StreamType;
43 using ::aidl::android::hardware::automotive::evs::UltrasonicsArrayDesc;
44 using ::aidl::android::hardware::graphics::common::BufferUsage;
45 using ::aidl::android::hardware::graphics::common::PixelFormat;
46 using ::ndk::ScopedAStatus;
47
48 struct StreamConfiguration {
49 int id;
50 int width;
51 int height;
52 PixelFormat format;
53 int type;
54 int framerate;
55 };
56
57 } // namespace
58
59 namespace aidl::android::automotive::evs::implementation {
60
61 namespace hidlevs = ::android::hardware::automotive::evs;
62
AidlEnumerator(const::android::sp<hidlevs::V1_0::IEvsEnumerator> & service,bool forceV1_0)63 AidlEnumerator::AidlEnumerator(const ::android::sp<hidlevs::V1_0::IEvsEnumerator>& service,
64 bool forceV1_0) {
65 auto serviceV1 = hidlevs::V1_1::IEvsEnumerator::castFrom(service).withDefault(nullptr);
66 if (forceV1_0 || !serviceV1) {
67 // AidlEnumerator is initialized in V1_0::IEvsEnumerator support mode in
68 // below conditions:
69 // 1. A given camera object is an implementation of V1_0::IEvsEnumerator
70 // (fails to upcast as V1_1::IEvsEnumertor).
71 // 2. A caller explicitly creates AidlEnumerator object in
72 // V1_0::IEvsEnumerator mode by setting forceV1_0 as true.
73 // 3. Or, A given camera object is invalid (nullptr).
74 mImpl = std::make_shared<ImplV0>(service);
75 LOG(DEBUG) << "Initialized in HIDL V1.0 support mode.";
76 } else {
77 mImpl = std::make_shared<ImplV1>(serviceV1);
78 LOG(DEBUG) << "Initialized in HIDL V1.1 support mode.";
79 }
80 }
81
82 // Methods from ::aidl::android::hardware::automotive::evs::IEvsEnumerator
isHardware(bool * flag)83 ScopedAStatus AidlEnumerator::isHardware(bool* flag) {
84 LOG(DEBUG) << __FUNCTION__;
85
86 // Always returns true because this class represents a HIDL EVS HAL
87 // implementation
88 *flag = true;
89 return ScopedAStatus::ok();
90 }
91
getCameraList(std::vector<CameraDesc> * _aidl_return)92 ScopedAStatus AidlEnumerator::getCameraList(std::vector<CameraDesc>* _aidl_return) {
93 LOG(DEBUG) << __FUNCTION__;
94 return mImpl->getCameraList(_aidl_return);
95 }
96
getStreamList(const CameraDesc & desc,std::vector<Stream> * _aidl_return)97 ScopedAStatus AidlEnumerator::getStreamList(const CameraDesc& desc,
98 std::vector<Stream>* _aidl_return) {
99 LOG(DEBUG) << __FUNCTION__;
100
101 if (desc.metadata.empty()) {
102 LOG(DEBUG) << "Camera metadata is empty.";
103 return ScopedAStatus::ok();
104 }
105
106 camera_metadata_t* pMetadata = const_cast<camera_metadata_t*>(
107 reinterpret_cast<const camera_metadata_t*>(desc.metadata.data()));
108 const size_t expectedSize = desc.metadata.size();
109 if (validate_camera_metadata_structure(pMetadata, &expectedSize) != ::android::OK) {
110 LOG(WARNING) << "Camera metadata is invalid.";
111 return ScopedAStatus::fromServiceSpecificError(static_cast<int>(EvsResult::INVALID_ARG));
112 }
113
114 camera_metadata_entry_t streamConfig;
115 if (find_camera_metadata_entry(pMetadata, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
116 &streamConfig) != ::android::OK) {
117 LOG(DEBUG) << "ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS does not exist in the camera "
118 "metadata.";
119 return ScopedAStatus::ok();
120 }
121
122 _aidl_return->resize(streamConfig.count);
123 const StreamConfiguration* pCurrentConfig =
124 reinterpret_cast<StreamConfiguration*>(streamConfig.data.i32);
125 for (unsigned i = 0; i < streamConfig.count; ++i, ++pCurrentConfig) {
126 Stream current = {
127 .id = pCurrentConfig->id,
128 .streamType =
129 pCurrentConfig->type == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT
130 ? StreamType::INPUT
131 : StreamType::OUTPUT,
132 .width = pCurrentConfig->width,
133 .height = pCurrentConfig->height,
134 .format = static_cast<PixelFormat>(pCurrentConfig->format),
135 .usage = BufferUsage::CAMERA_INPUT,
136 .rotation = Rotation::ROTATION_0,
137 };
138
139 (*_aidl_return)[i] = std::move(current);
140 }
141
142 return ScopedAStatus::ok();
143 }
144
closeCamera(const std::shared_ptr<IEvsCamera> & cameraObj)145 ScopedAStatus AidlEnumerator::closeCamera(const std::shared_ptr<IEvsCamera>& cameraObj) {
146 LOG(DEBUG) << __FUNCTION__;
147
148 if (!cameraObj) {
149 LOG(WARNING) << "Ignoring a call with an invalid camera object";
150 return ScopedAStatus::ok();
151 }
152
153 AidlCamera* aidlCamera = reinterpret_cast<AidlCamera*>(cameraObj.get());
154 return mImpl->closeCamera(aidlCamera->getHidlCamera());
155 }
156
openCamera(const std::string & id,const Stream & cfg,std::shared_ptr<IEvsCamera> * _aidl_return)157 ScopedAStatus AidlEnumerator::openCamera(const std::string& id, const Stream& cfg,
158 std::shared_ptr<IEvsCamera>* _aidl_return) {
159 LOG(DEBUG) << __FUNCTION__;
160 return mImpl->openCamera(id, cfg, _aidl_return);
161 }
162
openDisplay(int32_t id,std::shared_ptr<IEvsDisplay> * _aidl_return)163 ScopedAStatus AidlEnumerator::openDisplay(int32_t id, std::shared_ptr<IEvsDisplay>* _aidl_return) {
164 LOG(DEBUG) << __FUNCTION__;
165 auto hidlDisplay = mImpl->openDisplay(id);
166 if (!hidlDisplay) {
167 return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
168 }
169
170 mHidlDisplay = hidlDisplay;
171 auto aidlDisplay = ::ndk::SharedRefBase::make<AidlDisplay>(hidlDisplay);
172 mAidlDisplay = aidlDisplay;
173 *_aidl_return = std::move(aidlDisplay);
174
175 return ScopedAStatus::ok();
176 }
177
closeDisplay(const std::shared_ptr<IEvsDisplay> & displayToClose)178 ScopedAStatus AidlEnumerator::closeDisplay(const std::shared_ptr<IEvsDisplay>& displayToClose) {
179 LOG(DEBUG) << __FUNCTION__;
180
181 if (displayToClose != mAidlDisplay.lock()) {
182 return ScopedAStatus::ok();
183 }
184
185 auto pActiveDisplay = mHidlDisplay.promote();
186 if (pActiveDisplay) {
187 mImpl->closeDisplay(pActiveDisplay);
188 }
189
190 return ScopedAStatus::ok();
191 }
192
getDisplayState(DisplayState * _aidl_return)193 ScopedAStatus AidlEnumerator::getDisplayState(DisplayState* _aidl_return) {
194 LOG(DEBUG) << __FUNCTION__;
195
196 auto pActiveDisplay = mHidlDisplay.promote();
197 if (!pActiveDisplay) {
198 // We don't have a live display right now
199 mHidlDisplay = nullptr;
200 *_aidl_return = DisplayState::NOT_OPEN;
201 } else {
202 *_aidl_return =
203 std::move(Utils::makeFromHidl(std::move(pActiveDisplay->getDisplayState())));
204 }
205
206 return ScopedAStatus::ok();
207 }
208
getDisplayStateById(int32_t,DisplayState *)209 ScopedAStatus AidlEnumerator::getDisplayStateById(int32_t /* displayId */,
210 DisplayState* /* _aidl_return */) {
211 // No counterpart in the HIDL interfaces.
212 return Utils::buildScopedAStatusFromEvsResult(EvsResult::NOT_SUPPORTED);
213 }
214
getDisplayIdList(std::vector<uint8_t> * _aidl_return)215 ScopedAStatus AidlEnumerator::getDisplayIdList(std::vector<uint8_t>* _aidl_return) {
216 LOG(DEBUG) << __FUNCTION__;
217 return mImpl->getDisplayIdList(_aidl_return);
218 }
219
registerStatusCallback(const std::shared_ptr<IEvsEnumeratorStatusCallback> & callback)220 ScopedAStatus AidlEnumerator::registerStatusCallback(
221 [[maybe_unused]] const std::shared_ptr<IEvsEnumeratorStatusCallback>& callback) {
222 // This method always returns NOT_SUPPORTED because this class wraps around
223 // HIDL EVS HAL implementations, which do not support this callback
224 // interface.
225 return Utils::buildScopedAStatusFromEvsResult(EvsResult::NOT_SUPPORTED);
226 }
227
getUltrasonicsArrayList(std::vector<UltrasonicsArrayDesc> * list)228 ScopedAStatus AidlEnumerator::getUltrasonicsArrayList(
229 [[maybe_unused]] std::vector<UltrasonicsArrayDesc>* list) {
230 // TODO(b/149874793): Add implementation for EVS Manager and Sample driver
231 return Utils::buildScopedAStatusFromEvsResult(EvsResult::NOT_IMPLEMENTED);
232 }
233
openUltrasonicsArray(const std::string & id,std::shared_ptr<IEvsUltrasonicsArray> * obj)234 ScopedAStatus AidlEnumerator::openUltrasonicsArray(
235 [[maybe_unused]] const std::string& id,
236 [[maybe_unused]] std::shared_ptr<IEvsUltrasonicsArray>* obj) {
237 // TODO(b/149874793): Add implementation for EVS Manager and Sample driver
238 return Utils::buildScopedAStatusFromEvsResult(EvsResult::NOT_IMPLEMENTED);
239 }
240
closeUltrasonicsArray(const std::shared_ptr<IEvsUltrasonicsArray> & obj)241 ScopedAStatus AidlEnumerator::closeUltrasonicsArray(
242 [[maybe_unused]] const std::shared_ptr<IEvsUltrasonicsArray>& obj) {
243 // TODO(b/149874793): Add implementation for EVS Manager and Sample driver
244 return Utils::buildScopedAStatusFromEvsResult(EvsResult::NOT_IMPLEMENTED);
245 }
246
getCameraList(std::vector<CameraDesc> * _aidl_return)247 ScopedAStatus AidlEnumerator::ImplV0::getCameraList(std::vector<CameraDesc>* _aidl_return) {
248 if (!mHidlEnumerator) {
249 return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
250 }
251
252 mHidlEnumerator->getCameraList([_aidl_return](auto hidl_cameras) {
253 _aidl_return->resize(hidl_cameras.size());
254 auto it = _aidl_return->begin();
255 for (const auto& camera : hidl_cameras) {
256 *it++ = std::move(Utils::makeFromHidl(camera));
257 }
258 });
259
260 return ScopedAStatus::ok();
261 }
262
closeCamera(const::android::sp<hidlevs::V1_0::IEvsCamera> & cameraObj)263 ScopedAStatus AidlEnumerator::ImplV0::closeCamera(
264 const ::android::sp<hidlevs::V1_0::IEvsCamera>& cameraObj) {
265 if (!mHidlEnumerator) {
266 return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
267 }
268
269 mHidlEnumerator->closeCamera(cameraObj);
270 return ScopedAStatus::ok();
271 }
272
openCamera(const std::string & id,const Stream &,std::shared_ptr<IEvsCamera> * _aidl_return)273 ScopedAStatus AidlEnumerator::ImplV0::openCamera(const std::string& id, const Stream& /*cfg*/,
274 std::shared_ptr<IEvsCamera>* _aidl_return) {
275 if (!mHidlEnumerator) {
276 return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
277 }
278
279 ::android::sp<hidlevs::V1_0::IEvsCamera> hidlCamera = mHidlEnumerator->openCamera(id);
280 if (!hidlCamera) {
281 LOG(ERROR) << "Failed to open a camera " << id;
282 return Utils::buildScopedAStatusFromEvsResult(EvsResult::INVALID_ARG);
283 }
284
285 *_aidl_return = ::ndk::SharedRefBase::make<AidlCamera>(hidlCamera, /* forceV1_0= */ true);
286
287 return ScopedAStatus::ok();
288 }
289
openDisplay(int32_t id)290 ::android::sp<hidlevs::V1_0::IEvsDisplay> AidlEnumerator::ImplV0::openDisplay(int32_t id) {
291 if (!mHidlEnumerator) {
292 LOG(ERROR) << "AidlEnumerator is not initialized yet.";
293 return nullptr;
294 }
295
296 if (id != kDisplayIdUnavailable &&
297 (id < std::numeric_limits<uint8_t>::min() || id > std::numeric_limits<uint8_t>::max())) {
298 LOG(ERROR) << "A given display ID, " << id << ", is invalid.";
299 return nullptr;
300 }
301
302 LOG(DEBUG) << "A given display ID is ignored because HIDL IEvsEnumerator::openDisplay() opens "
303 "the default display always.";
304 ::android::sp<hidlevs::V1_0::IEvsDisplay> hidlDisplay = mHidlEnumerator->openDisplay();
305 mActiveHidlDisplay = hidlDisplay;
306 return hidlDisplay;
307 }
308
closeDisplay(const::android::sp<hidlevs::V1_0::IEvsDisplay> & display)309 ScopedAStatus AidlEnumerator::ImplV0::closeDisplay(
310 const ::android::sp<hidlevs::V1_0::IEvsDisplay>& display) {
311 if (!mHidlEnumerator) {
312 return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
313 }
314
315 if (display != mActiveHidlDisplay.promote()) {
316 LOG(WARNING) << "Ignore a request to close a display with an incorrect display handle.";
317 return ScopedAStatus::ok();
318 }
319
320 mHidlEnumerator->closeDisplay(display);
321 return ScopedAStatus::ok();
322 }
323
getDisplayIdList(std::vector<uint8_t> * _aidl_return)324 ScopedAStatus AidlEnumerator::ImplV0::getDisplayIdList(
325 [[maybe_unused]] std::vector<uint8_t>* _aidl_return) {
326 if (!mHidlEnumerator) {
327 return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
328 }
329
330 // android::hardware::automotive::evs::V1_0::IEvsEnumerator does not declare
331 // a method that returns any display ID because
332 // android::hardware::automotive::evs::V1_0::IEvsDisplay always uses the
333 // default (internal) display; hence, we return a NOT_SUPPORTED.
334 return Utils::buildScopedAStatusFromEvsResult(EvsResult::NOT_SUPPORTED);
335 }
336
closeCamera(const::android::sp<hidlevs::V1_0::IEvsCamera> & cameraObj)337 ScopedAStatus AidlEnumerator::ImplV1::closeCamera(
338 const ::android::sp<hidlevs::V1_0::IEvsCamera>& cameraObj) {
339 if (!mHidlEnumerator) {
340 return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
341 }
342
343 mHidlEnumerator->closeCamera(cameraObj);
344 return ScopedAStatus::ok();
345 }
346
getCameraList(std::vector<CameraDesc> * _aidl_return)347 ScopedAStatus AidlEnumerator::ImplV1::getCameraList(std::vector<CameraDesc>* _aidl_return) {
348 if (!mHidlEnumerator) {
349 return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
350 }
351
352 mHidlEnumerator->getCameraList_1_1([_aidl_return](auto hidl_cameras) {
353 _aidl_return->resize(hidl_cameras.size());
354 auto it = _aidl_return->begin();
355 for (const auto& camera : hidl_cameras) {
356 *it++ = std::move(Utils::makeFromHidl(camera));
357 }
358 });
359
360 return ScopedAStatus::ok();
361 }
362
openCamera(const std::string & id,const Stream & cfg,std::shared_ptr<IEvsCamera> * _aidl_return)363 ScopedAStatus AidlEnumerator::ImplV1::openCamera(const std::string& id, const Stream& cfg,
364 std::shared_ptr<IEvsCamera>* _aidl_return) {
365 if (!mHidlEnumerator) {
366 return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
367 }
368
369 auto hidlStreamConfig = Utils::makeToHidl(cfg);
370 ::android::sp<hidlevs::V1_1::IEvsCamera> hidlCamera =
371 mHidlEnumerator->openCamera_1_1(id, hidlStreamConfig);
372 if (!hidlCamera) {
373 LOG(ERROR) << "Failed to open a camera " << id;
374 return Utils::buildScopedAStatusFromEvsResult(EvsResult::INVALID_ARG);
375 }
376
377 *_aidl_return = ::ndk::SharedRefBase::make<AidlCamera>(hidlCamera);
378
379 return ScopedAStatus::ok();
380 }
381
openDisplay(int32_t id)382 ::android::sp<hidlevs::V1_0::IEvsDisplay> AidlEnumerator::ImplV1::openDisplay(int32_t id) {
383 if (!mHidlEnumerator) {
384 LOG(ERROR) << "AidlEnumerator is not initialized yet.";
385 return nullptr;
386 }
387
388 if (id < std::numeric_limits<uint8_t>::min() || id > std::numeric_limits<uint8_t>::max()) {
389 LOG(ERROR) << "A given display ID, " << id << ", is invalid.";
390 return nullptr;
391 }
392
393 ::android::sp<hidlevs::V1_1::IEvsDisplay> hidlDisplay = mHidlEnumerator->openDisplay_1_1(id);
394 return hidlDisplay;
395 }
396
closeDisplay(const::android::sp<hidlevs::V1_0::IEvsDisplay> & display)397 ScopedAStatus AidlEnumerator::ImplV1::closeDisplay(
398 const ::android::sp<hidlevs::V1_0::IEvsDisplay>& display) {
399 if (!mHidlEnumerator) {
400 return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
401 }
402
403 mHidlEnumerator->closeDisplay(display);
404 return ScopedAStatus::ok();
405 }
406
getDisplayIdList(std::vector<uint8_t> * _aidl_return)407 ScopedAStatus AidlEnumerator::ImplV1::getDisplayIdList(std::vector<uint8_t>* _aidl_return) {
408 if (!mHidlEnumerator) {
409 return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
410 }
411
412 mHidlEnumerator->getDisplayIdList(
413 [_aidl_return](auto& list) { *_aidl_return = std::move(list); });
414 return ScopedAStatus::ok();
415 }
416
417 } // namespace aidl::android::automotive::evs::implementation
418