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