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 =
286 std::move(::ndk::SharedRefBase::make<AidlCamera>(hidlCamera, /* forceV1_0= */ true));
287
288 return ScopedAStatus::ok();
289 }
290
openDisplay(int32_t id)291 ::android::sp<hidlevs::V1_0::IEvsDisplay> AidlEnumerator::ImplV0::openDisplay(int32_t id) {
292 if (!mHidlEnumerator) {
293 LOG(ERROR) << "AidlEnumerator is not initialized yet.";
294 return nullptr;
295 }
296
297 if (id != kDisplayIdUnavailable &&
298 (id < std::numeric_limits<uint8_t>::min() || id > std::numeric_limits<uint8_t>::max())) {
299 LOG(ERROR) << "A given display ID, " << id << ", is invalid.";
300 return nullptr;
301 }
302
303 LOG(DEBUG) << "A given display ID is ignored because HIDL IEvsEnumerator::openDisplay() opens "
304 "the default display always.";
305 ::android::sp<hidlevs::V1_0::IEvsDisplay> hidlDisplay = mHidlEnumerator->openDisplay();
306 mActiveHidlDisplay = hidlDisplay;
307 return hidlDisplay;
308 }
309
closeDisplay(const::android::sp<hidlevs::V1_0::IEvsDisplay> & display)310 ScopedAStatus AidlEnumerator::ImplV0::closeDisplay(
311 const ::android::sp<hidlevs::V1_0::IEvsDisplay>& display) {
312 if (!mHidlEnumerator) {
313 return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
314 }
315
316 if (display != mActiveHidlDisplay.promote()) {
317 LOG(WARNING) << "Ignore a request to close a display with an incorrect display handle.";
318 return ScopedAStatus::ok();
319 }
320
321 mHidlEnumerator->closeDisplay(display);
322 return ScopedAStatus::ok();
323 }
324
getDisplayIdList(std::vector<uint8_t> * _aidl_return)325 ScopedAStatus AidlEnumerator::ImplV0::getDisplayIdList(
326 [[maybe_unused]] std::vector<uint8_t>* _aidl_return) {
327 if (!mHidlEnumerator) {
328 return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
329 }
330
331 // android::hardware::automotive::evs::V1_0::IEvsEnumerator does not declare
332 // a method that returns any display ID because
333 // android::hardware::automotive::evs::V1_0::IEvsDisplay always uses the
334 // default (internal) display; hence, we return a NOT_SUPPORTED.
335 return Utils::buildScopedAStatusFromEvsResult(EvsResult::NOT_SUPPORTED);
336 }
337
closeCamera(const::android::sp<hidlevs::V1_0::IEvsCamera> & cameraObj)338 ScopedAStatus AidlEnumerator::ImplV1::closeCamera(
339 const ::android::sp<hidlevs::V1_0::IEvsCamera>& cameraObj) {
340 if (!mHidlEnumerator) {
341 return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
342 }
343
344 mHidlEnumerator->closeCamera(cameraObj);
345 return ScopedAStatus::ok();
346 }
347
getCameraList(std::vector<CameraDesc> * _aidl_return)348 ScopedAStatus AidlEnumerator::ImplV1::getCameraList(std::vector<CameraDesc>* _aidl_return) {
349 if (!mHidlEnumerator) {
350 return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
351 }
352
353 mHidlEnumerator->getCameraList_1_1([_aidl_return](auto hidl_cameras) {
354 _aidl_return->resize(hidl_cameras.size());
355 auto it = _aidl_return->begin();
356 for (const auto& camera : hidl_cameras) {
357 *it++ = std::move(Utils::makeFromHidl(camera));
358 }
359 });
360
361 return ScopedAStatus::ok();
362 }
363
openCamera(const std::string & id,const Stream & cfg,std::shared_ptr<IEvsCamera> * _aidl_return)364 ScopedAStatus AidlEnumerator::ImplV1::openCamera(const std::string& id, const Stream& cfg,
365 std::shared_ptr<IEvsCamera>* _aidl_return) {
366 if (!mHidlEnumerator) {
367 return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
368 }
369
370 auto hidlStreamConfig = std::move(Utils::makeToHidl(cfg));
371 ::android::sp<hidlevs::V1_1::IEvsCamera> hidlCamera =
372 mHidlEnumerator->openCamera_1_1(id, hidlStreamConfig);
373 if (!hidlCamera) {
374 LOG(ERROR) << "Failed to open a camera " << id;
375 return Utils::buildScopedAStatusFromEvsResult(EvsResult::INVALID_ARG);
376 }
377
378 *_aidl_return = std::move(::ndk::SharedRefBase::make<AidlCamera>(hidlCamera));
379
380 return ScopedAStatus::ok();
381 }
382
openDisplay(int32_t id)383 ::android::sp<hidlevs::V1_0::IEvsDisplay> AidlEnumerator::ImplV1::openDisplay(int32_t id) {
384 if (!mHidlEnumerator) {
385 LOG(ERROR) << "AidlEnumerator is not initialized yet.";
386 return nullptr;
387 }
388
389 if (id < std::numeric_limits<uint8_t>::min() || id > std::numeric_limits<uint8_t>::max()) {
390 LOG(ERROR) << "A given display ID, " << id << ", is invalid.";
391 return nullptr;
392 }
393
394 ::android::sp<hidlevs::V1_1::IEvsDisplay> hidlDisplay = mHidlEnumerator->openDisplay_1_1(id);
395 return hidlDisplay;
396 }
397
closeDisplay(const::android::sp<hidlevs::V1_0::IEvsDisplay> & display)398 ScopedAStatus AidlEnumerator::ImplV1::closeDisplay(
399 const ::android::sp<hidlevs::V1_0::IEvsDisplay>& display) {
400 if (!mHidlEnumerator) {
401 return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
402 }
403
404 mHidlEnumerator->closeDisplay(display);
405 return ScopedAStatus::ok();
406 }
407
getDisplayIdList(std::vector<uint8_t> * _aidl_return)408 ScopedAStatus AidlEnumerator::ImplV1::getDisplayIdList(std::vector<uint8_t>* _aidl_return) {
409 if (!mHidlEnumerator) {
410 return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
411 }
412
413 mHidlEnumerator->getDisplayIdList(
414 [_aidl_return](auto& list) { *_aidl_return = std::move(list); });
415 return ScopedAStatus::ok();
416 }
417
418 } // namespace aidl::android::automotive::evs::implementation
419