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