1 /*
2 * Copyright (C) 2016 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 <hwbinder/IPCThreadState.h>
18 #include <cutils/android_filesystem_config.h>
19
20 #include "Enumerator.h"
21 #include "HalDisplay.h"
22
23 namespace android {
24 namespace automotive {
25 namespace evs {
26 namespace V1_0 {
27 namespace implementation {
28
29
init(const char * hardwareServiceName)30 bool Enumerator::init(const char* hardwareServiceName) {
31 ALOGD("init");
32
33 // Connect with the underlying hardware enumerator
34 mHwEnumerator = IEvsEnumerator::getService(hardwareServiceName);
35 bool result = (mHwEnumerator.get() != nullptr);
36
37 return result;
38 }
39
40
checkPermission()41 bool Enumerator::checkPermission() {
42 hardware::IPCThreadState *ipc = hardware::IPCThreadState::self();
43 if (AID_AUTOMOTIVE_EVS != ipc->getCallingUid()) {
44 ALOGE("EVS access denied: pid = %d, uid = %d", ipc->getCallingPid(), ipc->getCallingUid());
45 return false;
46 }
47
48 return true;
49 }
50
51
52 // Methods from ::android::hardware::automotive::evs::V1_0::IEvsEnumerator follow.
getCameraList(getCameraList_cb list_cb)53 Return<void> Enumerator::getCameraList(getCameraList_cb list_cb) {
54 ALOGD("getCameraList");
55 if (!checkPermission()) {
56 return Void();
57 }
58
59 // Simply pass through to hardware layer
60 return mHwEnumerator->getCameraList(list_cb);
61 }
62
63
openCamera(const hidl_string & cameraId)64 Return<sp<IEvsCamera>> Enumerator::openCamera(const hidl_string& cameraId) {
65 ALOGD("openCamera");
66 if (!checkPermission()) {
67 return nullptr;
68 }
69
70 // Is the underlying hardware camera already open?
71 sp<HalCamera> hwCamera;
72 for (auto &&cam : mCameras) {
73 bool match = false;
74 cam->getHwCamera()->getCameraInfo([cameraId, &match](CameraDesc desc) {
75 if (desc.cameraId == cameraId) {
76 match = true;
77 }
78 }
79 );
80 if (match) {
81 hwCamera = cam;
82 break;
83 }
84 }
85
86 // Do we need to open a new hardware camera?
87 if (hwCamera == nullptr) {
88 // Is the hardware camera available?
89 sp<IEvsCamera> device = mHwEnumerator->openCamera(cameraId);
90 if (device == nullptr) {
91 ALOGE("Failed to open hardware camera %s", cameraId.c_str());
92 } else {
93 hwCamera = new HalCamera(device);
94 if (hwCamera == nullptr) {
95 ALOGE("Failed to allocate camera wrapper object");
96 mHwEnumerator->closeCamera(device);
97 }
98 }
99 }
100
101 // Construct a virtual camera wrapper for this hardware camera
102 sp<VirtualCamera> clientCamera;
103 if (hwCamera != nullptr) {
104 clientCamera = hwCamera->makeVirtualCamera();
105 }
106
107 // Add the hardware camera to our list, which will keep it alive via ref count
108 if (clientCamera != nullptr) {
109 mCameras.push_back(hwCamera);
110 } else {
111 ALOGE("Requested camera %s not found or not available", cameraId.c_str());
112 }
113
114 // Send the virtual camera object back to the client by strong pointer which will keep it alive
115 return clientCamera;
116 }
117
118
closeCamera(const::android::sp<IEvsCamera> & clientCamera)119 Return<void> Enumerator::closeCamera(const ::android::sp<IEvsCamera>& clientCamera) {
120 ALOGD("closeCamera");
121
122 if (clientCamera.get() == nullptr) {
123 ALOGE("Ignoring call with null camera pointer.");
124 return Void();
125 }
126
127 // All our client cameras are actually VirtualCamera objects
128 sp<VirtualCamera> virtualCamera = reinterpret_cast<VirtualCamera*>(clientCamera.get());
129
130 // Find the parent camera that backs this virtual camera
131 sp<HalCamera> halCamera = virtualCamera->getHalCamera();
132
133 // Tell the virtual camera's parent to clean it up and drop it
134 // NOTE: The camera objects will only actually destruct when the sp<> ref counts get to
135 // zero, so it is important to break all cyclic references.
136 halCamera->disownVirtualCamera(virtualCamera);
137
138 // Did we just remove the last client of this camera?
139 if (halCamera->getClientCount() == 0) {
140 // Take this now unused camera out of our list
141 // NOTE: This should drop our last reference to the camera, resulting in its
142 // destruction.
143 mCameras.remove(halCamera);
144 }
145
146 return Void();
147 }
148
149
openDisplay()150 Return<sp<IEvsDisplay>> Enumerator::openDisplay() {
151 ALOGD("openDisplay");
152
153 if (!checkPermission()) {
154 return nullptr;
155 }
156
157 // We simply keep track of the most recently opened display instance.
158 // In the underlying layers we expect that a new open will cause the previous
159 // object to be destroyed. This avoids any race conditions associated with
160 // create/destroy order and provides a cleaner restart sequence if the previous owner
161 // is non-responsive for some reason.
162 // Request exclusive access to the EVS display
163 sp<IEvsDisplay> pActiveDisplay = mHwEnumerator->openDisplay();
164 if (pActiveDisplay == nullptr) {
165 ALOGE("EVS Display unavailable");
166
167 return nullptr;
168 }
169
170 // Remember (via weak pointer) who we think the most recently opened display is so that
171 // we can proxy state requests from other callers to it.
172 // TODO: Because of b/129284474, an additional class, HalDisplay, has been defined and
173 // wraps the IEvsDisplay object the driver returns. We may want to remove this
174 // additional class when it is fixed properly.
175 sp<IEvsDisplay> pHalDisplay = new HalDisplay(pActiveDisplay);
176 mActiveDisplay = pHalDisplay;
177
178 return pHalDisplay;
179 }
180
181
closeDisplay(const::android::sp<IEvsDisplay> & display)182 Return<void> Enumerator::closeDisplay(const ::android::sp<IEvsDisplay>& display) {
183 ALOGD("closeDisplay");
184
185 sp<IEvsDisplay> pActiveDisplay = mActiveDisplay.promote();
186
187 // Drop the active display
188 if (display.get() != pActiveDisplay.get()) {
189 ALOGW("Ignoring call to closeDisplay with unrecognized display object.");
190 } else {
191 // Pass this request through to the hardware layer
192 sp<HalDisplay> halDisplay = reinterpret_cast<HalDisplay *>(pActiveDisplay.get());
193 mHwEnumerator->closeDisplay(halDisplay->getHwDisplay());
194 mActiveDisplay = nullptr;
195 }
196
197 return Void();
198 }
199
200
getDisplayState()201 Return<DisplayState> Enumerator::getDisplayState() {
202 ALOGD("getDisplayState");
203 if (!checkPermission()) {
204 return DisplayState::DEAD;
205 }
206
207 // Do we have a display object we think should be active?
208 sp<IEvsDisplay> pActiveDisplay = mActiveDisplay.promote();
209 if (pActiveDisplay != nullptr) {
210 // Pass this request through to the hardware layer
211 return pActiveDisplay->getDisplayState();
212 } else {
213 // We don't have a live display right now
214 mActiveDisplay = nullptr;
215 return DisplayState::NOT_OPEN;
216 }
217 }
218
219
220 } // namespace implementation
221 } // namespace V1_0
222 } // namespace evs
223 } // namespace automotive
224 } // namespace android
225