1 /*
2  * Copyright (C) 2019 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 #define LOG_TAG "android.hardware.automotive.evs@1.1-service"
18 
19 #include "EvsEnumerator.h"
20 #include "EvsCamera.h"
21 #include "EvsDisplay.h"
22 #include "EvsUltrasonicsArray.h"
23 
24 namespace android {
25 namespace hardware {
26 namespace automotive {
27 namespace evs {
28 namespace V1_1 {
29 namespace implementation {
30 
31 
32 // NOTE:  All members values are static so that all clients operate on the same state
33 //        That is to say, this is effectively a singleton despite the fact that HIDL
34 //        constructs a new instance for each client.
35 std::list<EvsEnumerator::CameraRecord>              EvsEnumerator::sCameraList;
36 wp<EvsDisplay>                                      EvsEnumerator::sActiveDisplay;
37 unique_ptr<ConfigManager>                           EvsEnumerator::sConfigManager;
38 sp<IAutomotiveDisplayProxyService>                  EvsEnumerator::sDisplayProxyService;
39 std::unordered_map<uint8_t, uint64_t>               EvsEnumerator::sDisplayPortList;
40 std::list<EvsEnumerator::UltrasonicsArrayRecord>    EvsEnumerator::sUltrasonicsArrayRecordList;
41 
EvsEnumerator(sp<IAutomotiveDisplayProxyService> windowService)42 EvsEnumerator::EvsEnumerator(sp<IAutomotiveDisplayProxyService> windowService) {
43     ALOGD("EvsEnumerator created");
44 
45     // Add sample camera data to our list of cameras
46     // In a real driver, this would be expected to can the available hardware
47     sConfigManager =
48         ConfigManager::Create("/vendor/etc/automotive/evs/evs_default_configuration.xml");
49 
50     // Add available cameras
51     for (auto v : sConfigManager->getCameraList()) {
52         sCameraList.emplace_back(v.c_str());
53     }
54 
55     if (sDisplayProxyService == nullptr) {
56         /* sets a car-window service handle */
57         sDisplayProxyService = windowService;
58     }
59 
60     // Add available displays
61     if (sDisplayProxyService != nullptr) {
62         // Get a display ID list.
63         sDisplayProxyService->getDisplayIdList([](const auto& displayIds) {
64             for (const auto& id : displayIds) {
65                 const auto port = id & 0xF;
66                 sDisplayPortList.insert_or_assign(port, id);
67             }
68         });
69     }
70 
71     // Add ultrasonics array desc.
72     sUltrasonicsArrayRecordList.emplace_back(
73             EvsUltrasonicsArray::GetMockArrayDesc("front_array"));
74 }
75 
76 
77 // Methods from ::android::hardware::automotive::evs::V1_0::IEvsEnumerator follow.
getCameraList(getCameraList_cb _hidl_cb)78 Return<void> EvsEnumerator::getCameraList(getCameraList_cb _hidl_cb)  {
79     ALOGD("getCameraList");
80 
81     const unsigned numCameras = sCameraList.size();
82 
83     // Build up a packed array of CameraDesc for return
84     // NOTE:  Only has to live until the callback returns
85     std::vector<CameraDesc_1_0> descriptions;
86     descriptions.reserve(numCameras);
87     for (const auto& cam : sCameraList) {
88         descriptions.push_back( cam.desc.v1 );
89     }
90 
91     // Encapsulate our camera descriptions in the HIDL vec type
92     hidl_vec<CameraDesc_1_0> hidlCameras(descriptions);
93 
94     // Send back the results
95     ALOGD("reporting %zu cameras available", hidlCameras.size());
96     _hidl_cb(hidlCameras);
97 
98     // HIDL convention says we return Void if we sent our result back via callback
99     return Void();
100 }
101 
102 
openCamera(const hidl_string & cameraId)103 Return<sp<IEvsCamera_1_0>> EvsEnumerator::openCamera(const hidl_string& cameraId) {
104     ALOGD("openCamera");
105 
106     // Find the named camera
107     CameraRecord *pRecord = nullptr;
108     for (auto &&cam : sCameraList) {
109         if (cam.desc.v1.cameraId == cameraId) {
110             // Found a match!
111             pRecord = &cam;
112             break;
113         }
114     }
115 
116     // Is this a recognized camera id?
117     if (!pRecord) {
118         ALOGE("Requested camera %s not found", cameraId.c_str());
119         return nullptr;
120     }
121 
122     // Has this camera already been instantiated by another caller?
123     sp<EvsCamera> pActiveCamera = pRecord->activeInstance.promote();
124     if (pActiveCamera != nullptr) {
125         ALOGW("Killing previous camera because of new caller");
126         closeCamera(pActiveCamera);
127     }
128 
129     // Construct a camera instance for the caller
130     if (sConfigManager == nullptr) {
131         pActiveCamera = EvsCamera::Create(cameraId.c_str());
132     } else {
133         pActiveCamera = EvsCamera::Create(cameraId.c_str(),
134                                           sConfigManager->getCameraInfo(cameraId));
135     }
136     pRecord->activeInstance = pActiveCamera;
137     if (pActiveCamera == nullptr) {
138         ALOGE("Failed to allocate new EvsCamera object for %s\n", cameraId.c_str());
139     }
140 
141     return pActiveCamera;
142 }
143 
144 
closeCamera(const::android::sp<IEvsCamera_1_0> & pCamera)145 Return<void> EvsEnumerator::closeCamera(const ::android::sp<IEvsCamera_1_0>& pCamera) {
146     ALOGD("closeCamera");
147 
148     auto pCamera_1_1 = IEvsCamera_1_1::castFrom(pCamera).withDefault(nullptr);
149     if (pCamera_1_1 == nullptr) {
150         ALOGE("Ignoring call to closeCamera with null camera ptr");
151         return Void();
152     }
153 
154     // Get the camera id so we can find it in our list
155     std::string cameraId;
156     pCamera_1_1->getCameraInfo_1_1([&cameraId](CameraDesc desc) {
157                                cameraId = desc.v1.cameraId;
158                            }
159     );
160 
161     // Find the named camera
162     CameraRecord *pRecord = nullptr;
163     for (auto &&cam : sCameraList) {
164         if (cam.desc.v1.cameraId == cameraId) {
165             // Found a match!
166             pRecord = &cam;
167             break;
168         }
169     }
170 
171     // Is the display being destroyed actually the one we think is active?
172     if (!pRecord) {
173         ALOGE("Asked to close a camera who's name isn't recognized");
174     } else {
175         sp<EvsCamera> pActiveCamera = pRecord->activeInstance.promote();
176 
177         if (pActiveCamera == nullptr) {
178             ALOGE("Somehow a camera is being destroyed when the enumerator didn't know one existed");
179         } else if (pActiveCamera != pCamera_1_1) {
180             // This can happen if the camera was aggressively reopened, orphaning this previous instance
181             ALOGW("Ignoring close of previously orphaned camera - why did a client steal?");
182         } else {
183             // Drop the active camera
184             pActiveCamera->forceShutdown();
185             pRecord->activeInstance = nullptr;
186         }
187     }
188 
189     return Void();
190 }
191 
192 
openDisplay()193 Return<sp<IEvsDisplay_1_0>> EvsEnumerator::openDisplay() {
194     ALOGD("openDisplay");
195 
196     // If we already have a display active, then we need to shut it down so we can
197     // give exclusive access to the new caller.
198     sp<EvsDisplay> pActiveDisplay = sActiveDisplay.promote();
199     if (pActiveDisplay != nullptr) {
200         ALOGW("Killing previous display because of new caller");
201         closeDisplay(pActiveDisplay);
202     }
203 
204     // Create a new display interface and return it
205     pActiveDisplay = new EvsDisplay();
206     sActiveDisplay = pActiveDisplay;
207 
208     ALOGD("Returning new EvsDisplay object %p", pActiveDisplay.get());
209     return pActiveDisplay;
210 }
211 
212 
getDisplayIdList(getDisplayIdList_cb _list_cb)213 Return<void> EvsEnumerator::getDisplayIdList(getDisplayIdList_cb _list_cb) {
214     hidl_vec<uint8_t> ids;
215 
216     ids.resize(sDisplayPortList.size());
217     unsigned i = 0;
218     for (const auto& [port, id] : sDisplayPortList) {
219         ids[i++] = port;
220     }
221 
222     _list_cb(ids);
223     return Void();
224 }
225 
226 
openDisplay_1_1(uint8_t port)227 Return<sp<IEvsDisplay>> EvsEnumerator::openDisplay_1_1(uint8_t port) {
228     ALOGD("%s", __FUNCTION__);
229 
230     // If we already have a display active, then we need to shut it down so we can
231     // give exclusive access to the new caller.
232     sp<EvsDisplay> pActiveDisplay = sActiveDisplay.promote();
233     if (pActiveDisplay != nullptr) {
234         ALOGW("Killing previous display because of new caller");
235         closeDisplay(pActiveDisplay);
236     }
237 
238     // Create a new display interface and return it
239     pActiveDisplay = new EvsDisplay(sDisplayProxyService, sDisplayPortList[port]);
240     sActiveDisplay = pActiveDisplay;
241 
242     ALOGD("Returning new EvsDisplay object %p", pActiveDisplay.get());
243     return pActiveDisplay;
244 }
245 
246 
247 
closeDisplay(const::android::sp<IEvsDisplay_1_0> & pDisplay)248 Return<void> EvsEnumerator::closeDisplay(const ::android::sp<IEvsDisplay_1_0>& pDisplay) {
249     ALOGD("closeDisplay");
250 
251     // Do we still have a display object we think should be active?
252     sp<EvsDisplay> pActiveDisplay = sActiveDisplay.promote();
253     if (pActiveDisplay == nullptr) {
254         ALOGE("Somehow a display is being destroyed when the enumerator didn't know one existed");
255     } else if (sActiveDisplay != pDisplay) {
256         ALOGW("Ignoring close of previously orphaned display - why did a client steal?");
257     } else {
258         // Drop the active display
259         pActiveDisplay->forceShutdown();
260         sActiveDisplay = nullptr;
261     }
262 
263     return Void();
264 }
265 
266 
getDisplayState()267 Return<DisplayState> EvsEnumerator::getDisplayState()  {
268     ALOGD("getDisplayState");
269 
270     // Do we still have a display object we think should be active?
271     sp<IEvsDisplay> pActiveDisplay = sActiveDisplay.promote();
272     if (pActiveDisplay != nullptr) {
273         return pActiveDisplay->getDisplayState();
274     } else {
275         return DisplayState::NOT_OPEN;
276     }
277 }
278 
279 
280 // Methods from ::android::hardware::automotive::evs::V1_1::IEvsEnumerator follow.
getCameraList_1_1(getCameraList_1_1_cb _hidl_cb)281 Return<void> EvsEnumerator::getCameraList_1_1(getCameraList_1_1_cb _hidl_cb)  {
282     ALOGD("getCameraList");
283 
284     const unsigned numCameras = sCameraList.size();
285 
286     // Build up a packed array of CameraDesc for return
287     // NOTE:  Only has to live until the callback returns
288     std::vector<CameraDesc_1_1> descriptions;
289     descriptions.reserve(numCameras);
290     for (const auto& cam : sCameraList) {
291         descriptions.push_back( cam.desc );
292     }
293 
294     // Encapsulate our camera descriptions in the HIDL vec type
295     hidl_vec<CameraDesc_1_1> hidlCameras(descriptions);
296 
297     // Send back the results
298     ALOGD("reporting %zu cameras available", hidlCameras.size());
299     _hidl_cb(hidlCameras);
300 
301     // HIDL convention says we return Void if we sent our result back via callback
302     return Void();
303 }
304 
305 Return<sp<IEvsCamera_1_1>>
openCamera_1_1(const hidl_string & cameraId,const Stream & streamCfg)306 EvsEnumerator::openCamera_1_1(const hidl_string& cameraId,
307                               const Stream& streamCfg) {
308     // Find the named camera
309     CameraRecord *pRecord = nullptr;
310     for (auto &&cam : sCameraList) {
311         if (cam.desc.v1.cameraId == cameraId) {
312             // Found a match!
313             pRecord = &cam;
314             break;
315         }
316     }
317 
318     // Is this a recognized camera id?
319     if (!pRecord) {
320         ALOGE("Requested camera %s not found", cameraId.c_str());
321         return nullptr;
322     }
323 
324     // Has this camera already been instantiated by another caller?
325     sp<EvsCamera> pActiveCamera = pRecord->activeInstance.promote();
326     if (pActiveCamera != nullptr) {
327         ALOGW("Killing previous camera because of new caller");
328         closeCamera(pActiveCamera);
329     }
330 
331     // Construct a camera instance for the caller
332     if (sConfigManager == nullptr) {
333         pActiveCamera = EvsCamera::Create(cameraId.c_str());
334     } else {
335         pActiveCamera = EvsCamera::Create(cameraId.c_str(),
336                                           sConfigManager->getCameraInfo(cameraId),
337                                           &streamCfg);
338     }
339 
340     pRecord->activeInstance = pActiveCamera;
341     if (pActiveCamera == nullptr) {
342         ALOGE("Failed to allocate new EvsCamera object for %s\n", cameraId.c_str());
343     }
344 
345     return pActiveCamera;
346 }
347 
348 
findCameraById(const std::string & cameraId)349 EvsEnumerator::CameraRecord* EvsEnumerator::findCameraById(const std::string& cameraId) {
350     // Find the named camera
351     CameraRecord *pRecord = nullptr;
352     for (auto &&cam : sCameraList) {
353         if (cam.desc.v1.cameraId == cameraId) {
354             // Found a match!
355             pRecord = &cam;
356             break;
357         }
358     }
359 
360     return pRecord;
361 }
362 
findUltrasonicsArrayById(const std::string & ultrasonicsArrayId)363 EvsEnumerator::UltrasonicsArrayRecord* EvsEnumerator::findUltrasonicsArrayById(
364         const std::string& ultrasonicsArrayId) {
365     auto recordIt = std::find_if(
366             sUltrasonicsArrayRecordList.begin(), sUltrasonicsArrayRecordList.end(),
367                     [&ultrasonicsArrayId](const UltrasonicsArrayRecord& record) {
368                             return ultrasonicsArrayId == record.desc.ultrasonicsArrayId;});
369 
370     return (recordIt != sUltrasonicsArrayRecordList.end()) ? &*recordIt : nullptr;
371 }
372 
getUltrasonicsArrayList(getUltrasonicsArrayList_cb _hidl_cb)373 Return<void> EvsEnumerator::getUltrasonicsArrayList(getUltrasonicsArrayList_cb _hidl_cb) {
374     hidl_vec<UltrasonicsArrayDesc> desc;
375     desc.resize(sUltrasonicsArrayRecordList.size());
376 
377     // Copy over desc from sUltrasonicsArrayRecordList.
378     for (auto p = std::make_pair(sUltrasonicsArrayRecordList.begin(), desc.begin());
379             p.first != sUltrasonicsArrayRecordList.end(); p.first++, p.second++) {
380         *p.second = p.first->desc;
381     }
382 
383     // Send back the results
384     ALOGD("reporting %zu ultrasonics arrays available", desc.size());
385     _hidl_cb(desc);
386 
387     // HIDL convention says we return Void if we sent our result back via callback
388     return Void();
389 }
390 
openUltrasonicsArray(const hidl_string & ultrasonicsArrayId)391 Return<sp<IEvsUltrasonicsArray>> EvsEnumerator::openUltrasonicsArray(
392         const hidl_string& ultrasonicsArrayId) {
393     // Find the named ultrasonic array.
394     UltrasonicsArrayRecord* pRecord = findUltrasonicsArrayById(ultrasonicsArrayId);
395 
396     // Is this a recognized ultrasonic array id?
397     if (!pRecord) {
398         ALOGE("Requested ultrasonics array %s not found", ultrasonicsArrayId.c_str());
399         return nullptr;
400     }
401 
402     // Has this ultrasonic array already been instantiated by another caller?
403     sp<EvsUltrasonicsArray> pActiveUltrasonicsArray = pRecord->activeInstance.promote();
404     if (pActiveUltrasonicsArray != nullptr) {
405         ALOGW("Killing previous ultrasonics array because of new caller");
406         closeUltrasonicsArray(pActiveUltrasonicsArray);
407     }
408 
409     // Construct a ultrasonic array instance for the caller
410     pActiveUltrasonicsArray = EvsUltrasonicsArray::Create(ultrasonicsArrayId.c_str());
411     pRecord->activeInstance = pActiveUltrasonicsArray;
412     if (pActiveUltrasonicsArray == nullptr) {
413         ALOGE("Failed to allocate new EvsUltrasonicsArray object for %s\n",
414               ultrasonicsArrayId.c_str());
415     }
416 
417     return pActiveUltrasonicsArray;
418 }
419 
closeUltrasonicsArray(const sp<IEvsUltrasonicsArray> & pEvsUltrasonicsArray)420 Return<void> EvsEnumerator::closeUltrasonicsArray(
421         const sp<IEvsUltrasonicsArray>& pEvsUltrasonicsArray) {
422 
423     if (pEvsUltrasonicsArray.get() == nullptr) {
424         ALOGE("Ignoring call to closeUltrasonicsArray with null ultrasonics array");
425         return Void();
426     }
427 
428     // Get the ultrasonics array id so we can find it in our list.
429     std::string ultrasonicsArrayId;
430     pEvsUltrasonicsArray->getUltrasonicArrayInfo([&ultrasonicsArrayId](UltrasonicsArrayDesc desc) {
431         ultrasonicsArrayId.assign(desc.ultrasonicsArrayId);
432     });
433 
434     // Find the named ultrasonics array
435     UltrasonicsArrayRecord* pRecord = findUltrasonicsArrayById(ultrasonicsArrayId);
436     if (!pRecord) {
437         ALOGE("Asked to close a ultrasonics array whose name isnt not found");
438         return Void();
439     }
440 
441     sp<EvsUltrasonicsArray> pActiveUltrasonicsArray = pRecord->activeInstance.promote();
442 
443     if (pActiveUltrasonicsArray.get() == nullptr) {
444         ALOGE("Somehow a ultrasonics array is being destroyed when the enumerator didn't know "
445               "one existed");
446     } else if (pActiveUltrasonicsArray != pEvsUltrasonicsArray) {
447         // This can happen if the ultrasonics array was aggressively reopened,
448         // orphaning this previous instance
449         ALOGW("Ignoring close of previously orphaned ultrasonics array - why did a client steal?");
450     } else {
451         // Drop the active ultrasonics array
452         pActiveUltrasonicsArray->forceShutdown();
453         pRecord->activeInstance = nullptr;
454     }
455 
456     return Void();
457 }
458 
459 } // namespace implementation
460 } // namespace V1_1
461 } // namespace evs
462 } // namespace automotive
463 } // namespace hardware
464 } // namespace android
465