1 /*
2 * Copyright (C) 2019 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 "ResourceManager.h"
18
19 namespace android {
20 namespace automotive {
21 namespace evs {
22 namespace support {
23
24 using ::std::lock_guard;
25
26 const string ResourceManager::kDefaultServiceName = "default";
27 sp<ResourceManager> ResourceManager::sInstance;
28 mutex ResourceManager::sLockSingleton;
29 mutex ResourceManager::sLockEvs;
30 sp<IEvsEnumerator> ResourceManager::sEvs;
31
getEvsEnumerator(string serviceName)32 sp<IEvsEnumerator> ResourceManager::getEvsEnumerator(string serviceName) {
33 lock_guard<mutex> lock(sLockEvs);
34 if (sEvs.get() == nullptr) {
35 sEvs = IEvsEnumerator::getService(serviceName);
36 }
37 return sEvs;
38 }
39
getInstance()40 sp<ResourceManager> ResourceManager::getInstance() {
41 lock_guard<mutex> lock(sLockSingleton);
42 if (sInstance == nullptr) {
43 ALOGD("Creating new ResourceManager instance");
44 sInstance = new ResourceManager();
45 }
46 return sInstance;
47 }
48
obtainStreamHandler(string pCameraId)49 sp<StreamHandler> ResourceManager::obtainStreamHandler(string pCameraId) {
50 ALOGD("ResourceManager::obtainStreamHandler");
51
52 // Lock for stream handler related methods.
53 lock_guard<mutex> lock(mLockStreamHandler);
54
55 auto result = mCameraInstances.find(pCameraId);
56 if (result == mCameraInstances.end()) {
57 sp<CameraInstance> instance = new CameraInstance();
58
59 // CameraInstance::useCaseCount
60 instance->useCaseCount++;
61
62 // CameraInstance::cameraId
63 instance->cameraId = pCameraId;
64
65 // CameraInstance::camera
66 instance->camera = getEvsEnumerator()->openCamera(pCameraId);
67 if (instance->camera.get() == nullptr) {
68 ALOGE("Failed to allocate new EVS Camera interface for %s",
69 pCameraId.c_str());
70 return nullptr;
71 }
72
73 // CameraInstance::handler
74 instance->handler = new StreamHandler(instance->camera);
75 if (instance->handler == nullptr) {
76 ALOGE("Failed to create stream handler for %s",
77 pCameraId.c_str());
78 }
79
80 // Move the newly-created instance into vector, and the vector takes
81 // ownership of the instance.
82 mCameraInstances.emplace(pCameraId, instance);
83
84 return instance->handler;
85 } else {
86 auto instance = result->second;
87 instance->useCaseCount++;
88
89 return instance->handler;
90 }
91 }
92
releaseStreamHandler(string pCameraId)93 void ResourceManager::releaseStreamHandler(string pCameraId) {
94 ALOGD("ResourceManager::releaseStreamHandler");
95
96 // Lock for stream handler related methods.
97 lock_guard<mutex> lock(mLockStreamHandler);
98
99 auto result = mCameraInstances.find(pCameraId);
100 if (result == mCameraInstances.end()) {
101 ALOGW("No stream handler is active with camera id %s", pCameraId.c_str());
102 } else {
103 auto instance = result->second;
104 instance->useCaseCount--;
105
106 if (instance->useCaseCount <= 0) {
107 // The vector keeps the only strong reference to the camera
108 // instance. Once the instance is erased from the vector, the
109 // override onLastStrongRef method for CameraInstance class will
110 // be called and clean up the resources.
111 mCameraInstances.erase(result);
112 }
113 }
114 }
115
116 // TODO(b/130246434): have further discussion about how the display resource
117 // should be managed.
openDisplay()118 sp<IEvsDisplay> ResourceManager::openDisplay() {
119 // Lock for display related methods.
120 lock_guard<mutex> lock(mLockDisplay);
121
122 if (mDisplay.get() == nullptr) {
123 mDisplay = getEvsEnumerator()->openDisplay();
124 if (mDisplay.get() != nullptr) {
125 ALOGD("Evs display is opened");
126 } else {
127 ALOGE("Failed to open evs display.");
128 }
129 }
130
131 return mDisplay;
132 }
133
closeDisplay(sp<IEvsDisplay> pDisplay)134 void ResourceManager::closeDisplay(sp<IEvsDisplay> pDisplay) {
135 // Lock for display related methods.
136 lock_guard<mutex> lock(mLockDisplay);
137
138 // Even though there are logics in evs manager to prevent errors from
139 // unrecognized IEvsDisplay object, we still want to check whether the
140 // incoming pDisplay is the one we opened earlier in resource manager. So
141 // when developer make mistakes by passing in incorrect IEvsDisplay object,
142 // we know that we should not proceed and the active display is still
143 // opened.
144 if (mDisplay.get() == pDisplay.get()) {
145 getEvsEnumerator()->closeDisplay(mDisplay);
146 mDisplay = nullptr;
147 ALOGD("Evs display is closed");
148 } else {
149 ALOGW("Ignored! Unrecognized display object for closeDisplay method");
150 }
151 }
152
isDisplayOpened()153 bool ResourceManager::isDisplayOpened() {
154 // Lock for display related methods.
155 lock_guard<mutex> lock(mLockDisplay);
156
157 return mDisplay.get() != nullptr;
158 }
159
160 } // namespace support
161 } // namespace evs
162 } // namespace automotive
163 } // namespace android
164