blob: 0319560ee644de9f4af1a903dd52e063e8401df7 [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"
22
23namespace android {
24namespace hardware {
25namespace automotive {
26namespace evs {
27namespace V1_1 {
28namespace implementation {
29
30
31// NOTE: All members values are static so that all clients operate on the same state
32// That is to say, this is effectively a singleton despite the fact that HIDL
33// constructs a new instance for each client.
34std::list<EvsEnumerator::CameraRecord> EvsEnumerator::sCameraList;
35wp<EvsDisplay> EvsEnumerator::sActiveDisplay;
Changyeon Joc6fa0ab2019-10-12 05:25:44 -070036unique_ptr<ConfigManager> EvsEnumerator::sConfigManager;
Changyeon Jo043a7a02020-01-02 17:55:55 -080037sp<IAutomotiveDisplayProxyService> EvsEnumerator::sDisplayProxyService;
38std::unordered_map<uint8_t, uint64_t> EvsEnumerator::sDisplayPortList;
Changyeon Jo2400b692019-07-18 21:32:48 -070039
40
Changyeon Jo043a7a02020-01-02 17:55:55 -080041EvsEnumerator::EvsEnumerator(sp<IAutomotiveDisplayProxyService> windowService) {
Changyeon Jo2400b692019-07-18 21:32:48 -070042 ALOGD("EvsEnumerator created");
43
44 // Add sample camera data to our list of cameras
45 // In a real driver, this would be expected to can the available hardware
Changyeon Joc6fa0ab2019-10-12 05:25:44 -070046 sConfigManager =
Changyeon Job0e72922020-01-30 09:00:35 -080047 ConfigManager::Create("/vendor/etc/automotive/evs/evs_default_configuration.xml");
Changyeon Jo043a7a02020-01-02 17:55:55 -080048
49 // Add available cameras
Changyeon Joc6fa0ab2019-10-12 05:25:44 -070050 for (auto v : sConfigManager->getCameraList()) {
51 sCameraList.emplace_back(v.c_str());
52 }
Changyeon Jo043a7a02020-01-02 17:55:55 -080053
54 if (sDisplayProxyService == nullptr) {
55 /* sets a car-window service handle */
56 sDisplayProxyService = windowService;
57 }
58
59 // Add available displays
60 if (sDisplayProxyService != nullptr) {
61 // Get a display ID list.
62 sDisplayProxyService->getDisplayIdList([](const auto& displayIds) {
63 for (const auto& id : displayIds) {
64 const auto port = id & 0xF;
65 sDisplayPortList.insert_or_assign(port, id);
66 }
67 });
68 }
Changyeon Jo2400b692019-07-18 21:32:48 -070069}
70
71
72// Methods from ::android::hardware::automotive::evs::V1_0::IEvsEnumerator follow.
73Return<void> EvsEnumerator::getCameraList(getCameraList_cb _hidl_cb) {
74 ALOGD("getCameraList");
75
76 const unsigned numCameras = sCameraList.size();
77
78 // Build up a packed array of CameraDesc for return
79 // NOTE: Only has to live until the callback returns
80 std::vector<CameraDesc_1_0> descriptions;
81 descriptions.reserve(numCameras);
82 for (const auto& cam : sCameraList) {
Changyeon Joc6fa0ab2019-10-12 05:25:44 -070083 descriptions.push_back( cam.desc.v1 );
Changyeon Jo2400b692019-07-18 21:32:48 -070084 }
85
86 // Encapsulate our camera descriptions in the HIDL vec type
87 hidl_vec<CameraDesc_1_0> hidlCameras(descriptions);
88
89 // Send back the results
90 ALOGD("reporting %zu cameras available", hidlCameras.size());
91 _hidl_cb(hidlCameras);
92
93 // HIDL convention says we return Void if we sent our result back via callback
94 return Void();
95}
96
97
98Return<sp<IEvsCamera_1_0>> EvsEnumerator::openCamera(const hidl_string& cameraId) {
99 ALOGD("openCamera");
100
101 // Find the named camera
102 CameraRecord *pRecord = nullptr;
103 for (auto &&cam : sCameraList) {
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700104 if (cam.desc.v1.cameraId == cameraId) {
Changyeon Jo2400b692019-07-18 21:32:48 -0700105 // Found a match!
106 pRecord = &cam;
107 break;
108 }
109 }
110
111 // Is this a recognized camera id?
112 if (!pRecord) {
113 ALOGE("Requested camera %s not found", cameraId.c_str());
114 return nullptr;
115 }
116
117 // Has this camera already been instantiated by another caller?
118 sp<EvsCamera> pActiveCamera = pRecord->activeInstance.promote();
119 if (pActiveCamera != nullptr) {
120 ALOGW("Killing previous camera because of new caller");
121 closeCamera(pActiveCamera);
122 }
123
124 // Construct a camera instance for the caller
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700125 if (sConfigManager == nullptr) {
126 pActiveCamera = EvsCamera::Create(cameraId.c_str());
127 } else {
128 pActiveCamera = EvsCamera::Create(cameraId.c_str(),
129 sConfigManager->getCameraInfo(cameraId));
130 }
Changyeon Jo2400b692019-07-18 21:32:48 -0700131 pRecord->activeInstance = pActiveCamera;
132 if (pActiveCamera == nullptr) {
133 ALOGE("Failed to allocate new EvsCamera object for %s\n", cameraId.c_str());
134 }
135
136 return pActiveCamera;
137}
138
139
140Return<void> EvsEnumerator::closeCamera(const ::android::sp<IEvsCamera_1_0>& pCamera) {
141 ALOGD("closeCamera");
142
143 auto pCamera_1_1 = IEvsCamera_1_1::castFrom(pCamera).withDefault(nullptr);
144 if (pCamera_1_1 == nullptr) {
145 ALOGE("Ignoring call to closeCamera with null camera ptr");
146 return Void();
147 }
148
149 // Get the camera id so we can find it in our list
150 std::string cameraId;
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700151 pCamera_1_1->getCameraInfo_1_1([&cameraId](CameraDesc desc) {
152 cameraId = desc.v1.cameraId;
Changyeon Jo2400b692019-07-18 21:32:48 -0700153 }
154 );
155
156 // Find the named camera
157 CameraRecord *pRecord = nullptr;
158 for (auto &&cam : sCameraList) {
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700159 if (cam.desc.v1.cameraId == cameraId) {
Changyeon Jo2400b692019-07-18 21:32:48 -0700160 // Found a match!
161 pRecord = &cam;
162 break;
163 }
164 }
165
166 // Is the display being destroyed actually the one we think is active?
167 if (!pRecord) {
168 ALOGE("Asked to close a camera who's name isn't recognized");
169 } else {
170 sp<EvsCamera> pActiveCamera = pRecord->activeInstance.promote();
171
172 if (pActiveCamera == nullptr) {
173 ALOGE("Somehow a camera is being destroyed when the enumerator didn't know one existed");
174 } else if (pActiveCamera != pCamera_1_1) {
175 // This can happen if the camera was aggressively reopened, orphaning this previous instance
176 ALOGW("Ignoring close of previously orphaned camera - why did a client steal?");
177 } else {
178 // Drop the active camera
179 pActiveCamera->forceShutdown();
180 pRecord->activeInstance = nullptr;
181 }
182 }
183
184 return Void();
185}
186
187
Changyeon Jo043a7a02020-01-02 17:55:55 -0800188Return<sp<IEvsDisplay_1_0>> EvsEnumerator::openDisplay() {
Changyeon Jo2400b692019-07-18 21:32:48 -0700189 ALOGD("openDisplay");
190
191 // If we already have a display active, then we need to shut it down so we can
192 // give exclusive access to the new caller.
193 sp<EvsDisplay> pActiveDisplay = sActiveDisplay.promote();
194 if (pActiveDisplay != nullptr) {
195 ALOGW("Killing previous display because of new caller");
196 closeDisplay(pActiveDisplay);
197 }
198
199 // Create a new display interface and return it
200 pActiveDisplay = new EvsDisplay();
201 sActiveDisplay = pActiveDisplay;
202
203 ALOGD("Returning new EvsDisplay object %p", pActiveDisplay.get());
204 return pActiveDisplay;
205}
206
207
Changyeon Jo043a7a02020-01-02 17:55:55 -0800208Return<void> EvsEnumerator::getDisplayIdList(getDisplayIdList_cb _list_cb) {
209 hidl_vec<uint8_t> ids;
210
211 ids.resize(sDisplayPortList.size());
212 unsigned i = 0;
213 for (const auto& [port, id] : sDisplayPortList) {
214 ids[i++] = port;
215 }
216
217 _list_cb(ids);
218 return Void();
219}
220
221
222Return<sp<IEvsDisplay>> EvsEnumerator::openDisplay_1_1(uint8_t port) {
223 ALOGD("%s", __FUNCTION__);
224
225 // If we already have a display active, then we need to shut it down so we can
226 // give exclusive access to the new caller.
227 sp<EvsDisplay> pActiveDisplay = sActiveDisplay.promote();
228 if (pActiveDisplay != nullptr) {
229 ALOGW("Killing previous display because of new caller");
230 closeDisplay(pActiveDisplay);
231 }
232
233 // Create a new display interface and return it
234 pActiveDisplay = new EvsDisplay(sDisplayProxyService, sDisplayPortList[port]);
235 sActiveDisplay = pActiveDisplay;
236
237 ALOGD("Returning new EvsDisplay object %p", pActiveDisplay.get());
238 return pActiveDisplay;
239}
240
241
242
243Return<void> EvsEnumerator::closeDisplay(const ::android::sp<IEvsDisplay_1_0>& pDisplay) {
Changyeon Jo2400b692019-07-18 21:32:48 -0700244 ALOGD("closeDisplay");
245
246 // Do we still have a display object we think should be active?
247 sp<EvsDisplay> pActiveDisplay = sActiveDisplay.promote();
248 if (pActiveDisplay == nullptr) {
249 ALOGE("Somehow a display is being destroyed when the enumerator didn't know one existed");
250 } else if (sActiveDisplay != pDisplay) {
251 ALOGW("Ignoring close of previously orphaned display - why did a client steal?");
252 } else {
253 // Drop the active display
254 pActiveDisplay->forceShutdown();
255 sActiveDisplay = nullptr;
256 }
257
258 return Void();
259}
260
261
262Return<DisplayState> EvsEnumerator::getDisplayState() {
263 ALOGD("getDisplayState");
264
265 // Do we still have a display object we think should be active?
266 sp<IEvsDisplay> pActiveDisplay = sActiveDisplay.promote();
267 if (pActiveDisplay != nullptr) {
268 return pActiveDisplay->getDisplayState();
269 } else {
270 return DisplayState::NOT_OPEN;
271 }
272}
273
274
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700275// Methods from ::android::hardware::automotive::evs::V1_1::IEvsEnumerator follow.
276Return<void> EvsEnumerator::getCameraList_1_1(getCameraList_1_1_cb _hidl_cb) {
277 ALOGD("getCameraList");
278
279 const unsigned numCameras = sCameraList.size();
280
281 // Build up a packed array of CameraDesc for return
282 // NOTE: Only has to live until the callback returns
283 std::vector<CameraDesc_1_1> descriptions;
284 descriptions.reserve(numCameras);
285 for (const auto& cam : sCameraList) {
286 descriptions.push_back( cam.desc );
287 }
288
289 // Encapsulate our camera descriptions in the HIDL vec type
290 hidl_vec<CameraDesc_1_1> hidlCameras(descriptions);
291
292 // Send back the results
293 ALOGD("reporting %zu cameras available", hidlCameras.size());
294 _hidl_cb(hidlCameras);
295
296 // HIDL convention says we return Void if we sent our result back via callback
297 return Void();
298}
299
300Return<sp<IEvsCamera_1_1>>
301EvsEnumerator::openCamera_1_1(const hidl_string& cameraId,
302 const Stream& streamCfg) {
303 // Find the named camera
304 CameraRecord *pRecord = nullptr;
305 for (auto &&cam : sCameraList) {
306 if (cam.desc.v1.cameraId == cameraId) {
307 // Found a match!
308 pRecord = &cam;
309 break;
310 }
311 }
312
313 // Is this a recognized camera id?
314 if (!pRecord) {
315 ALOGE("Requested camera %s not found", cameraId.c_str());
316 return nullptr;
317 }
318
319 // Has this camera already been instantiated by another caller?
320 sp<EvsCamera> pActiveCamera = pRecord->activeInstance.promote();
321 if (pActiveCamera != nullptr) {
322 ALOGW("Killing previous camera because of new caller");
323 closeCamera(pActiveCamera);
324 }
325
326 // Construct a camera instance for the caller
327 if (sConfigManager == nullptr) {
328 pActiveCamera = EvsCamera::Create(cameraId.c_str());
329 } else {
330 pActiveCamera = EvsCamera::Create(cameraId.c_str(),
331 sConfigManager->getCameraInfo(cameraId),
332 &streamCfg);
333 }
334
335 pRecord->activeInstance = pActiveCamera;
336 if (pActiveCamera == nullptr) {
337 ALOGE("Failed to allocate new EvsCamera object for %s\n", cameraId.c_str());
338 }
339
340 return pActiveCamera;
341}
342
343
344EvsEnumerator::CameraRecord* EvsEnumerator::findCameraById(const std::string& cameraId) {
345 // Find the named camera
346 CameraRecord *pRecord = nullptr;
347 for (auto &&cam : sCameraList) {
348 if (cam.desc.v1.cameraId == cameraId) {
349 // Found a match!
350 pRecord = &cam;
351 break;
352 }
353 }
354
355 return pRecord;
356}
357
Changyeon Jo2400b692019-07-18 21:32:48 -0700358} // namespace implementation
359} // namespace V1_1
360} // namespace evs
361} // namespace automotive
362} // namespace hardware
363} // namespace android