• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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