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