blob: 4bf77f34a6400cf802a4de4e5a09bccfc055e5dc [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
17#define LOG_TAG "android.hardware.evs@1.0-service"
18
19#include "EvsEnumerator.h"
20#include "EvsCamera.h"
21#include "EvsDisplay.h"
22
23namespace android {
24namespace hardware {
25namespace evs {
26namespace V1_0 {
27namespace implementation {
28
29
Scott Randolphdb5a5982017-01-23 12:35:05 -080030// TODO(b/31632518): Need to get notification when our client dies so we can close the camera.
31// As it stands, if the client dies suddenly, the camera will be stuck "open".
32// NOTE: Display should already be safe by virtue of holding only a weak pointer.
33
34
Scott Randolph5c99d852016-11-15 17:01:23 -080035EvsEnumerator::EvsEnumerator() {
36 ALOGD("EvsEnumerator created");
37
38 // Add sample camera data to our list of cameras
39 // NOTE: The id strings trigger special initialization inside the EvsCamera constructor
40 mCameraList.emplace_back( new EvsCamera(EvsCamera::kCameraName_Backup), false );
41 mCameraList.emplace_back( new EvsCamera("LaneView"), false );
42 mCameraList.emplace_back( new EvsCamera(EvsCamera::kCameraName_RightTurn), false );
43}
44
45// Methods from ::android::hardware::evs::V1_0::IEvsEnumerator follow.
46Return<void> EvsEnumerator::getCameraList(getCameraList_cb _hidl_cb) {
47 ALOGD("getCameraList");
48
49 const unsigned numCameras = mCameraList.size();
50
51 // Build up a packed array of CameraDesc for return
52 // NOTE: Only has to live until the callback returns
53 std::vector<CameraDesc> descriptions;
54 descriptions.reserve(numCameras);
55 for (const auto& cam : mCameraList) {
56 descriptions.push_back( cam.pCamera->getDesc() );
57 }
58
59 // Encapsulate our camera descriptions in the HIDL vec type
60 hidl_vec<CameraDesc> hidlCameras(descriptions);
61
62 // Send back the results
63 ALOGD("reporting %zu cameras available", hidlCameras.size());
64 _hidl_cb(hidlCameras);
65
66 // HIDL convention says we return Void if we sent our result back via callback
67 return Void();
68}
69
Martijn Coenen527924a2017-01-04 12:59:48 +010070Return<sp<IEvsCamera>> EvsEnumerator::openCamera(const hidl_string& cameraId) {
Scott Randolph5c99d852016-11-15 17:01:23 -080071 ALOGD("openCamera");
72
73 // Find the named camera
74 CameraRecord *pRecord = nullptr;
75 for (auto &&cam : mCameraList) {
76 if (cam.pCamera->getDesc().cameraId == cameraId) {
77 // Found a match!
78 pRecord = &cam;
79 break;
80 }
81 }
82
83 if (!pRecord) {
84 ALOGE("Requested camera %s not found", cameraId.c_str());
Martijn Coenen527924a2017-01-04 12:59:48 +010085 return nullptr;
Scott Randolphdb5a5982017-01-23 12:35:05 -080086 } else if (pRecord->inUse) {
Scott Randolph5c99d852016-11-15 17:01:23 -080087 ALOGE("Cannot open camera %s which is already in use", cameraId.c_str());
Martijn Coenen527924a2017-01-04 12:59:48 +010088 return nullptr;
Scott Randolphdb5a5982017-01-23 12:35:05 -080089 } else {
Scott Randolph5c99d852016-11-15 17:01:23 -080090 pRecord->inUse = true;
Martijn Coenen527924a2017-01-04 12:59:48 +010091 return(pRecord->pCamera);
Scott Randolph5c99d852016-11-15 17:01:23 -080092 }
Scott Randolph5c99d852016-11-15 17:01:23 -080093}
94
95Return<void> EvsEnumerator::closeCamera(const ::android::sp<IEvsCamera>& camera) {
96 ALOGD("closeCamera");
97
98 if (camera == nullptr) {
99 ALOGE("Ignoring call to closeCamera with null camera pointer");
Scott Randolphdb5a5982017-01-23 12:35:05 -0800100 } else {
101 // Find this camera in our list
102 auto it = std::find_if(mCameraList.begin(),
103 mCameraList.end(),
104 [camera](const CameraRecord& rec) {
105 return (rec.pCamera == camera);
106 });
107 if (it == mCameraList.end()) {
108 ALOGE("Ignoring close on unrecognized camera");
109 } else {
110 // Make sure the camera has stopped streaming
111 camera->stopVideoStream();
Scott Randolph5c99d852016-11-15 17:01:23 -0800112
Scott Randolphdb5a5982017-01-23 12:35:05 -0800113 it->inUse = false;
114 }
Scott Randolph5c99d852016-11-15 17:01:23 -0800115 }
116
117 return Void();
118}
119
Martijn Coenen527924a2017-01-04 12:59:48 +0100120Return<sp<IEvsDisplay>> EvsEnumerator::openDisplay() {
Scott Randolph5c99d852016-11-15 17:01:23 -0800121 ALOGD("openDisplay");
122
123 // If we already have a display active, then this request must be denied
Scott Randolphdb5a5982017-01-23 12:35:05 -0800124 sp<IEvsDisplay> pActiveDisplay = mActiveDisplay.promote();
125 if (pActiveDisplay != nullptr) {
Scott Randolph5c99d852016-11-15 17:01:23 -0800126 ALOGW("Rejecting openDisplay request the display is already in use.");
Martijn Coenen527924a2017-01-04 12:59:48 +0100127 return nullptr;
Scott Randolphdb5a5982017-01-23 12:35:05 -0800128 } else {
Scott Randolph5c99d852016-11-15 17:01:23 -0800129 // Create a new display interface and return it
Scott Randolphdb5a5982017-01-23 12:35:05 -0800130 pActiveDisplay = new EvsDisplay();
131 mActiveDisplay = pActiveDisplay;
132 ALOGD("Returning new EvsDisplay object %p", pActiveDisplay.get());
133 return pActiveDisplay;
Scott Randolph5c99d852016-11-15 17:01:23 -0800134 }
Scott Randolph5c99d852016-11-15 17:01:23 -0800135}
136
137Return<void> EvsEnumerator::closeDisplay(const ::android::sp<IEvsDisplay>& display) {
138 ALOGD("closeDisplay");
139
Scott Randolphdb5a5982017-01-23 12:35:05 -0800140 // Do we still have a display object we think should be active?
141 sp<IEvsDisplay> pActiveDisplay = mActiveDisplay.promote();
142
143 if (pActiveDisplay == nullptr) {
144 ALOGE("Ignoring closeDisplay when there is no active display.");
145 } else if (display != pActiveDisplay) {
146 ALOGE("Ignoring closeDisplay on a display we didn't issue");
147 ALOGI("Got %p while active display is %p.", display.get(), pActiveDisplay.get());
148 } else {
Scott Randolph5c99d852016-11-15 17:01:23 -0800149 // Drop the active display
Scott Randolph5c99d852016-11-15 17:01:23 -0800150 mActiveDisplay = nullptr;
151 }
152
153 return Void();
154}
155
Scott Randolphdb5a5982017-01-23 12:35:05 -0800156Return<DisplayState> EvsEnumerator::getDisplayState() {
157 ALOGD("getDisplayState");
Scott Randolph5c99d852016-11-15 17:01:23 -0800158
Scott Randolphdb5a5982017-01-23 12:35:05 -0800159 // Do we still have a display object we think should be active?
160 sp<IEvsDisplay> pActiveDisplay = mActiveDisplay.promote();
161 if (pActiveDisplay != nullptr) {
162 return pActiveDisplay->getDisplayState();
163 } else {
164 return DisplayState::NOT_OPEN;
165 }
166}
Scott Randolph5c99d852016-11-15 17:01:23 -0800167
168} // namespace implementation
169} // namespace V1_0
170} // namespace evs
171} // namespace hardware
172} // namespace android