blob: 117ee7aec40afc8bf1596143bc7a8d95d13fcad0 [file] [log] [blame]
Changyeon Jo2400b692019-07-18 21:32:48 -07001/*
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"
Tanmay Patilb97cceb2020-02-07 16:48:39 -080022#include "EvsUltrasonicsArray.h"
Changyeon Jo2400b692019-07-18 21:32:48 -070023
24namespace android {
25namespace hardware {
26namespace automotive {
27namespace evs {
28namespace V1_1 {
29namespace 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.
Tanmay Patilb97cceb2020-02-07 16:48:39 -080035std::list<EvsEnumerator::CameraRecord> EvsEnumerator::sCameraList;
36wp<EvsDisplay> EvsEnumerator::sActiveDisplay;
37unique_ptr<ConfigManager> EvsEnumerator::sConfigManager;
38sp<IAutomotiveDisplayProxyService> EvsEnumerator::sDisplayProxyService;
39std::unordered_map<uint8_t, uint64_t> EvsEnumerator::sDisplayPortList;
40std::list<EvsEnumerator::UltrasonicsArrayRecord> EvsEnumerator::sUltrasonicsArrayRecordList;
Changyeon Jo2400b692019-07-18 21:32:48 -070041
Changyeon Jo043a7a02020-01-02 17:55:55 -080042EvsEnumerator::EvsEnumerator(sp<IAutomotiveDisplayProxyService> windowService) {
Changyeon Jo2400b692019-07-18 21:32:48 -070043 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
Changyeon Joc6fa0ab2019-10-12 05:25:44 -070047 sConfigManager =
Changyeon Job0e72922020-01-30 09:00:35 -080048 ConfigManager::Create("/vendor/etc/automotive/evs/evs_default_configuration.xml");
Changyeon Jo043a7a02020-01-02 17:55:55 -080049
50 // Add available cameras
Changyeon Joc6fa0ab2019-10-12 05:25:44 -070051 for (auto v : sConfigManager->getCameraList()) {
52 sCameraList.emplace_back(v.c_str());
53 }
Changyeon Jo043a7a02020-01-02 17:55:55 -080054
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 }
Tanmay Patilb97cceb2020-02-07 16:48:39 -080070
71 // Add ultrasonics array desc.
72 sUltrasonicsArrayRecordList.emplace_back(
73 EvsUltrasonicsArray::GetDummyArrayDesc("front_array"));
Changyeon Jo2400b692019-07-18 21:32:48 -070074}
75
76
77// Methods from ::android::hardware::automotive::evs::V1_0::IEvsEnumerator follow.
78Return<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) {
Changyeon Joc6fa0ab2019-10-12 05:25:44 -070088 descriptions.push_back( cam.desc.v1 );
Changyeon Jo2400b692019-07-18 21:32:48 -070089 }
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
103Return<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) {
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700109 if (cam.desc.v1.cameraId == cameraId) {
Changyeon Jo2400b692019-07-18 21:32:48 -0700110 // 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
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700130 if (sConfigManager == nullptr) {
131 pActiveCamera = EvsCamera::Create(cameraId.c_str());
132 } else {
133 pActiveCamera = EvsCamera::Create(cameraId.c_str(),
134 sConfigManager->getCameraInfo(cameraId));
135 }
Changyeon Jo2400b692019-07-18 21:32:48 -0700136 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
145Return<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;
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700156 pCamera_1_1->getCameraInfo_1_1([&cameraId](CameraDesc desc) {
157 cameraId = desc.v1.cameraId;
Changyeon Jo2400b692019-07-18 21:32:48 -0700158 }
159 );
160
161 // Find the named camera
162 CameraRecord *pRecord = nullptr;
163 for (auto &&cam : sCameraList) {
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700164 if (cam.desc.v1.cameraId == cameraId) {
Changyeon Jo2400b692019-07-18 21:32:48 -0700165 // 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
Changyeon Jo043a7a02020-01-02 17:55:55 -0800193Return<sp<IEvsDisplay_1_0>> EvsEnumerator::openDisplay() {
Changyeon Jo2400b692019-07-18 21:32:48 -0700194 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
Changyeon Jo043a7a02020-01-02 17:55:55 -0800213Return<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
227Return<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
248Return<void> EvsEnumerator::closeDisplay(const ::android::sp<IEvsDisplay_1_0>& pDisplay) {
Changyeon Jo2400b692019-07-18 21:32:48 -0700249 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
267Return<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
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700280// Methods from ::android::hardware::automotive::evs::V1_1::IEvsEnumerator follow.
281Return<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
305Return<sp<IEvsCamera_1_1>>
306EvsEnumerator::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
349EvsEnumerator::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
Tanmay Patilb97cceb2020-02-07 16:48:39 -0800363EvsEnumerator::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
Tanmay Patil496b86c2020-01-07 17:50:23 -0800373Return<void> EvsEnumerator::getUltrasonicsArrayList(getUltrasonicsArrayList_cb _hidl_cb) {
Tanmay Patilb97cceb2020-02-07 16:48:39 -0800374 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
Tanmay Patil496b86c2020-01-07 17:50:23 -0800388 return Void();
389}
390
Tanmay Patil496b86c2020-01-07 17:50:23 -0800391Return<sp<IEvsUltrasonicsArray>> EvsEnumerator::openUltrasonicsArray(
392 const hidl_string& ultrasonicsArrayId) {
Tanmay Patilb97cceb2020-02-07 16:48:39 -0800393 // 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;
Tanmay Patil496b86c2020-01-07 17:50:23 -0800418}
419
Tanmay Patil496b86c2020-01-07 17:50:23 -0800420Return<void> EvsEnumerator::closeUltrasonicsArray(
Tanmay Patilb97cceb2020-02-07 16:48:39 -0800421 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
Tanmay Patil496b86c2020-01-07 17:50:23 -0800456 return Void();
457}
458
Changyeon Jo2400b692019-07-18 21:32:48 -0700459} // namespace implementation
460} // namespace V1_1
461} // namespace evs
462} // namespace automotive
463} // namespace hardware
464} // namespace android