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#define LOG_TAG "android.hardware.automotive.evs@1.0-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_0 { 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; 36 37 38EvsEnumerator::EvsEnumerator() { 39 ALOGD("EvsEnumerator created"); 40 41 // Add sample camera data to our list of cameras 42 // In a real driver, this would be expected to can the available hardware 43 sCameraList.emplace_back(EvsCamera::kCameraName_Backup); 44 sCameraList.emplace_back("LaneView"); 45 sCameraList.emplace_back("right turn"); 46} 47 48 49// Methods from ::android::hardware::automotive::evs::V1_0::IEvsEnumerator follow. 50Return<void> EvsEnumerator::getCameraList(getCameraList_cb _hidl_cb) { 51 ALOGD("getCameraList"); 52 53 const unsigned numCameras = sCameraList.size(); 54 55 // Build up a packed array of CameraDesc for return 56 // NOTE: Only has to live until the callback returns 57 std::vector<CameraDesc> descriptions; 58 descriptions.reserve(numCameras); 59 for (const auto& cam : sCameraList) { 60 descriptions.push_back( cam.desc ); 61 } 62 63 // Encapsulate our camera descriptions in the HIDL vec type 64 hidl_vec<CameraDesc> hidlCameras(descriptions); 65 66 // Send back the results 67 ALOGD("reporting %zu cameras available", hidlCameras.size()); 68 _hidl_cb(hidlCameras); 69 70 // HIDL convention says we return Void if we sent our result back via callback 71 return Void(); 72} 73 74 75Return<sp<IEvsCamera>> EvsEnumerator::openCamera(const hidl_string& cameraId) { 76 ALOGD("openCamera"); 77 78 // Find the named camera 79 CameraRecord *pRecord = nullptr; 80 for (auto &&cam : sCameraList) { 81 if (cam.desc.cameraId == cameraId) { 82 // Found a match! 83 pRecord = &cam; 84 break; 85 } 86 } 87 88 // Is this a recognized camera id? 89 if (!pRecord) { 90 ALOGE("Requested camera %s not found", cameraId.c_str()); 91 return nullptr; 92 } 93 94 // Has this camera already been instantiated by another caller? 95 sp<EvsCamera> pActiveCamera = pRecord->activeInstance.promote(); 96 if (pActiveCamera != nullptr) { 97 ALOGW("Killing previous camera because of new caller"); 98 closeCamera(pActiveCamera); 99 } 100 101 // Construct a camera instance for the caller 102 pActiveCamera = new EvsCamera(cameraId.c_str()); 103 pRecord->activeInstance = pActiveCamera; 104 if (pActiveCamera == nullptr) { 105 ALOGE("Failed to allocate new EvsCamera object for %s\n", cameraId.c_str()); 106 } 107 108 return pActiveCamera; 109} 110 111 112Return<void> EvsEnumerator::closeCamera(const ::android::sp<IEvsCamera>& pCamera) { 113 ALOGD("closeCamera"); 114 115 if (pCamera == nullptr) { 116 ALOGE("Ignoring call to closeCamera with null camera ptr"); 117 return Void(); 118 } 119 120 // Get the camera id so we can find it in our list 121 std::string cameraId; 122 pCamera->getCameraInfo([&cameraId](CameraDesc desc) { 123// TODO(b/36532780) Should we able to just use a simple assignment? 124// cameraId = desc.cameraId; 125 cameraId.assign(desc.cameraId.c_str()); 126 } 127 ); 128 129 // Find the named camera 130 CameraRecord *pRecord = nullptr; 131 for (auto &&cam : sCameraList) { 132 if (cam.desc.cameraId == cameraId) { 133 // Found a match! 134 pRecord = &cam; 135 break; 136 } 137 } 138 139 // Is the display being destroyed actually the one we think is active? 140 if (!pRecord) { 141 ALOGE("Asked to close a camera who's name isn't recognized"); 142 } else { 143 sp<EvsCamera> pActiveCamera = pRecord->activeInstance.promote(); 144 145 if (pActiveCamera == nullptr) { 146 ALOGE("Somehow a camera is being destroyed when the enumerator didn't know one existed"); 147 } else if (pActiveCamera != pCamera) { 148 // This can happen if the camera was aggressively reopened, orphaning this previous instance 149 ALOGW("Ignoring close of previously orphaned camera - why did a client steal?"); 150 } else { 151 // Drop the active camera 152 pActiveCamera->forceShutdown(); 153 pRecord->activeInstance = nullptr; 154 } 155 } 156 157 return Void(); 158} 159 160 161Return<sp<IEvsDisplay>> EvsEnumerator::openDisplay() { 162 ALOGD("openDisplay"); 163 164 // If we already have a display active, then we need to shut it down so we can 165 // give exclusive access to the new caller. 166 sp<EvsDisplay> pActiveDisplay = sActiveDisplay.promote(); 167 if (pActiveDisplay != nullptr) { 168 ALOGW("Killing previous display because of new caller"); 169 closeDisplay(pActiveDisplay); 170 } 171 172 // Create a new display interface and return it 173 pActiveDisplay = new EvsDisplay(); 174 sActiveDisplay = pActiveDisplay; 175 176 ALOGD("Returning new EvsDisplay object %p", pActiveDisplay.get()); 177 return pActiveDisplay; 178} 179 180 181Return<void> EvsEnumerator::closeDisplay(const ::android::sp<IEvsDisplay>& pDisplay) { 182 ALOGD("closeDisplay"); 183 184 // Do we still have a display object we think should be active? 185 sp<EvsDisplay> pActiveDisplay = sActiveDisplay.promote(); 186 if (pActiveDisplay == nullptr) { 187 ALOGE("Somehow a display is being destroyed when the enumerator didn't know one existed"); 188 } else if (sActiveDisplay != pDisplay) { 189 ALOGW("Ignoring close of previously orphaned display - why did a client steal?"); 190 } else { 191 // Drop the active display 192 pActiveDisplay->forceShutdown(); 193 sActiveDisplay = nullptr; 194 } 195 196 return Void(); 197} 198 199 200Return<DisplayState> EvsEnumerator::getDisplayState() { 201 ALOGD("getDisplayState"); 202 203 // Do we still have a display object we think should be active? 204 sp<IEvsDisplay> pActiveDisplay = sActiveDisplay.promote(); 205 if (pActiveDisplay != nullptr) { 206 return pActiveDisplay->getDisplayState(); 207 } else { 208 return DisplayState::NOT_OPEN; 209 } 210} 211 212} // namespace implementation 213} // namespace V1_0 214} // namespace evs 215} // namespace automotive 216} // namespace hardware 217} // namespace android 218