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