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