blob: 731e21bd3f5f0f25437284abb1627f4d90672f91 [file] [log] [blame]
Scott Randolph5c99d852016-11-15 17:01:23 -08001/*
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 Randolph83422792017-03-01 20:32:59 -080017#define LOG_TAG "android.hardware.automotive.evs@1.0-service"
Scott Randolph5c99d852016-11-15 17:01:23 -080018
19#include "EvsEnumerator.h"
20#include "EvsCamera.h"
21#include "EvsDisplay.h"
22
23namespace android {
24namespace hardware {
Scott Randolph83422792017-03-01 20:32:59 -080025namespace automotive {
Scott Randolph5c99d852016-11-15 17:01:23 -080026namespace evs {
27namespace V1_0 {
28namespace implementation {
29
30
Scott Randolphde9880e2017-03-30 14:04:12 -070031// 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;
Scott Randolphdb5a5982017-01-23 12:35:05 -080036
37
Scott Randolph5c99d852016-11-15 17:01:23 -080038EvsEnumerator::EvsEnumerator() {
39 ALOGD("EvsEnumerator created");
40
41 // Add sample camera data to our list of cameras
Scott Randolphde9880e2017-03-30 14:04:12 -070042 // 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");
Scott Randolph5c99d852016-11-15 17:01:23 -080046}
47
Scott Randolphde9880e2017-03-30 14:04:12 -070048
Scott Randolph83422792017-03-01 20:32:59 -080049// Methods from ::android::hardware::automotive::evs::V1_0::IEvsEnumerator follow.
Scott Randolph5c99d852016-11-15 17:01:23 -080050Return<void> EvsEnumerator::getCameraList(getCameraList_cb _hidl_cb) {
51 ALOGD("getCameraList");
52
Scott Randolphde9880e2017-03-30 14:04:12 -070053 const unsigned numCameras = sCameraList.size();
Scott Randolph5c99d852016-11-15 17:01:23 -080054
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);
Scott Randolphde9880e2017-03-30 14:04:12 -070059 for (const auto& cam : sCameraList) {
60 descriptions.push_back( cam.desc );
Scott Randolph5c99d852016-11-15 17:01:23 -080061 }
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
Scott Randolphde9880e2017-03-30 14:04:12 -070074
Martijn Coenen527924a2017-01-04 12:59:48 +010075Return<sp<IEvsCamera>> EvsEnumerator::openCamera(const hidl_string& cameraId) {
Scott Randolph5c99d852016-11-15 17:01:23 -080076 ALOGD("openCamera");
77
78 // Find the named camera
79 CameraRecord *pRecord = nullptr;
Scott Randolphde9880e2017-03-30 14:04:12 -070080 for (auto &&cam : sCameraList) {
81 if (cam.desc.cameraId == cameraId) {
Scott Randolph5c99d852016-11-15 17:01:23 -080082 // Found a match!
83 pRecord = &cam;
84 break;
85 }
86 }
87
Scott Randolphde9880e2017-03-30 14:04:12 -070088 // Is this a recognized camera id?
Scott Randolph5c99d852016-11-15 17:01:23 -080089 if (!pRecord) {
90 ALOGE("Requested camera %s not found", cameraId.c_str());
Martijn Coenen527924a2017-01-04 12:59:48 +010091 return nullptr;
Scott Randolph5c99d852016-11-15 17:01:23 -080092 }
Scott Randolphde9880e2017-03-30 14:04:12 -070093
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);
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;
Scott Randolph5c99d852016-11-15 17:01:23 -0800109}
110
Scott Randolphde9880e2017-03-30 14:04:12 -0700111
112Return<void> EvsEnumerator::closeCamera(const ::android::sp<IEvsCamera>& pCamera) {
Scott Randolph5c99d852016-11-15 17:01:23 -0800113 ALOGD("closeCamera");
114
Scott Randolphde9880e2017-03-30 14:04:12 -0700115 if (pCamera == nullptr) {
116 ALOGE("Ignoring call to closeCamera with null camera ptr");
117 return Void();
118 }
Scott Randolph5c99d852016-11-15 17:01:23 -0800119
Scott Randolphde9880e2017-03-30 14:04:12 -0700120 // 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;
Scott Randolphdb5a5982017-01-23 12:35:05 -0800154 }
Scott Randolph5c99d852016-11-15 17:01:23 -0800155 }
156
157 return Void();
158}
159
Scott Randolphde9880e2017-03-30 14:04:12 -0700160
Martijn Coenen527924a2017-01-04 12:59:48 +0100161Return<sp<IEvsDisplay>> EvsEnumerator::openDisplay() {
Scott Randolph5c99d852016-11-15 17:01:23 -0800162 ALOGD("openDisplay");
163
Scott Randolphde9880e2017-03-30 14:04:12 -0700164 // 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();
Scott Randolphdb5a5982017-01-23 12:35:05 -0800167 if (pActiveDisplay != nullptr) {
Scott Randolphde9880e2017-03-30 14:04:12 -0700168 ALOGW("Killing previous display because of new caller");
169 closeDisplay(pActiveDisplay);
Scott Randolph5c99d852016-11-15 17:01:23 -0800170 }
Scott Randolphde9880e2017-03-30 14:04:12 -0700171
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;
Scott Randolph5c99d852016-11-15 17:01:23 -0800178}
179
Scott Randolphde9880e2017-03-30 14:04:12 -0700180
181Return<void> EvsEnumerator::closeDisplay(const ::android::sp<IEvsDisplay>& pDisplay) {
Scott Randolph5c99d852016-11-15 17:01:23 -0800182 ALOGD("closeDisplay");
183
Scott Randolphdb5a5982017-01-23 12:35:05 -0800184 // Do we still have a display object we think should be active?
Scott Randolphde9880e2017-03-30 14:04:12 -0700185 sp<EvsDisplay> pActiveDisplay = sActiveDisplay.promote();
Scott Randolphdb5a5982017-01-23 12:35:05 -0800186 if (pActiveDisplay == nullptr) {
Scott Randolphde9880e2017-03-30 14:04:12 -0700187 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?");
Scott Randolphdb5a5982017-01-23 12:35:05 -0800190 } else {
Scott Randolph5c99d852016-11-15 17:01:23 -0800191 // Drop the active display
Scott Randolphde9880e2017-03-30 14:04:12 -0700192 pActiveDisplay->forceShutdown();
193 sActiveDisplay = nullptr;
Scott Randolph5c99d852016-11-15 17:01:23 -0800194 }
195
196 return Void();
197}
198
Scott Randolphde9880e2017-03-30 14:04:12 -0700199
Scott Randolphdb5a5982017-01-23 12:35:05 -0800200Return<DisplayState> EvsEnumerator::getDisplayState() {
201 ALOGD("getDisplayState");
Scott Randolph5c99d852016-11-15 17:01:23 -0800202
Scott Randolphdb5a5982017-01-23 12:35:05 -0800203 // Do we still have a display object we think should be active?
Scott Randolphde9880e2017-03-30 14:04:12 -0700204 sp<IEvsDisplay> pActiveDisplay = sActiveDisplay.promote();
Scott Randolphdb5a5982017-01-23 12:35:05 -0800205 if (pActiveDisplay != nullptr) {
206 return pActiveDisplay->getDisplayState();
207 } else {
208 return DisplayState::NOT_OPEN;
209 }
210}
Scott Randolph5c99d852016-11-15 17:01:23 -0800211
212} // namespace implementation
213} // namespace V1_0
214} // namespace evs
Scott Randolph83422792017-03-01 20:32:59 -0800215} // namespace automotive
Scott Randolph5c99d852016-11-15 17:01:23 -0800216} // namespace hardware
217} // namespace android