1 /*
2  * Copyright (C) 2023 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 "VirtualCameraSessionContext.h"
18 
19 #include <memory>
20 #include <mutex>
21 #include <unordered_set>
22 
23 #include "VirtualCameraStream.h"
24 #include "aidl/android/hardware/camera/device/StreamConfiguration.h"
25 
26 namespace android {
27 namespace companion {
28 namespace virtualcamera {
29 
30 using ::aidl::android::hardware::camera::device::BufferCache;
31 using ::aidl::android::hardware::camera::device::Stream;
32 using ::aidl::android::hardware::camera::device::StreamBuffer;
33 using ::aidl::android::hardware::camera::device::StreamConfiguration;
34 
initializeStream(const::aidl::android::hardware::camera::device::Stream & stream)35 bool VirtualCameraSessionContext::initializeStream(
36     const ::aidl::android::hardware::camera::device::Stream& stream) {
37   std::lock_guard<std::mutex> lock(mLock);
38 
39   auto s = std::make_unique<VirtualCameraStream>(stream);
40 
41   const auto& [_, newlyInserted] = mStreams.emplace(
42       std::piecewise_construct, std::forward_as_tuple(stream.id),
43       std::forward_as_tuple(std::move(s)));
44   return newlyInserted;
45 }
46 
closeAllStreams()47 void VirtualCameraSessionContext::closeAllStreams() {
48   std::lock_guard<std::mutex> lock(mLock);
49   mStreams.clear();
50 }
51 
importBuffersFromCaptureRequest(const::aidl::android::hardware::camera::device::CaptureRequest & captureRequest)52 bool VirtualCameraSessionContext::importBuffersFromCaptureRequest(
53     const ::aidl::android::hardware::camera::device::CaptureRequest&
54         captureRequest) {
55   std::lock_guard<std::mutex> lock(mLock);
56 
57   for (const StreamBuffer& buffer : captureRequest.outputBuffers) {
58     auto it = mStreams.find(buffer.streamId);
59     if (it == mStreams.end()) {
60       ALOGE("%s: Cannot import buffer for unknown stream with id %d", __func__,
61             buffer.streamId);
62       return false;
63     }
64     VirtualCameraStream& stream = *it->second;
65     if (stream.getHardwareBuffer(buffer.bufferId) != nullptr) {
66       // This buffer is already imported.
67       continue;
68     }
69 
70     if (stream.importBuffer(buffer) == nullptr) {
71       ALOGE("%s: Failed to import buffer %" PRId64 " for streamId %d", __func__,
72             buffer.bufferId, buffer.streamId);
73       return false;
74     }
75   }
76 
77   return true;
78 }
79 
removeBufferCaches(const std::vector<BufferCache> & cachesToRemove)80 void VirtualCameraSessionContext::removeBufferCaches(
81     const std::vector<BufferCache>& cachesToRemove) {
82   std::lock_guard<std::mutex> lock(mLock);
83   for (const auto& bufferCache : cachesToRemove) {
84     auto it = mStreams.find(bufferCache.streamId);
85     if (it == mStreams.end()) {
86       ALOGE("%s: Ask to remove buffer %" PRId64 " from unknown stream %d",
87             __func__, bufferCache.bufferId, bufferCache.streamId);
88       continue;
89     }
90     if (it->second->removeBuffer(bufferCache.bufferId)) {
91       ALOGD("%s: Successfully removed buffer %" PRId64
92             " from cache of stream %d",
93             __func__, bufferCache.bufferId, bufferCache.streamId);
94     } else {
95       ALOGE("%s: Failed to remove buffer %" PRId64 " from cache of stream %d",
96             __func__, bufferCache.bufferId, bufferCache.streamId);
97     }
98   }
99 }
100 
removeStreamsNotInStreamConfiguration(const StreamConfiguration & streamConfiguration)101 void VirtualCameraSessionContext::removeStreamsNotInStreamConfiguration(
102     const StreamConfiguration& streamConfiguration) {
103   std::unordered_set<int> newConfigurationStreamIds;
104   for (const Stream& stream : streamConfiguration.streams) {
105     newConfigurationStreamIds.insert(stream.id);
106   }
107 
108   std::lock_guard<std::mutex> lock(mLock);
109   for (auto it = mStreams.begin(); it != mStreams.end();) {
110     if (newConfigurationStreamIds.find(it->first) ==
111         newConfigurationStreamIds.end()) {
112       ALOGV(
113           "Disposing of stream %d, since it is not referenced by new "
114           "configuration.",
115           it->first);
116       it = mStreams.erase(it);
117     } else {
118       ++it;
119     }
120   }
121 }
122 
getStreamConfig(int streamId) const123 std::optional<Stream> VirtualCameraSessionContext::getStreamConfig(
124     int streamId) const {
125   std::lock_guard<std::mutex> lock(mLock);
126   auto it = mStreams.find(streamId);
127   if (it == mStreams.end()) {
128     ALOGE("%s: StreamBuffer references buffer of unknown streamId %d", __func__,
129           streamId);
130     return std::optional<Stream>();
131   }
132   VirtualCameraStream& stream = *it->second;
133   return {stream.getStreamConfig()};
134 }
135 
fetchHardwareBuffer(const int streamId,const int bufferId) const136 std::shared_ptr<AHardwareBuffer> VirtualCameraSessionContext::fetchHardwareBuffer(
137     const int streamId, const int bufferId) const {
138   std::lock_guard<std::mutex> lock(mLock);
139   auto it = mStreams.find(streamId);
140   if (it == mStreams.end()) {
141     ALOGE("%s: StreamBuffer references buffer of unknown streamId %d", __func__,
142           streamId);
143     return nullptr;
144   }
145   VirtualCameraStream& stream = *it->second;
146   return stream.getHardwareBuffer(bufferId);
147 }
148 
149 std::shared_ptr<EglFrameBuffer>
fetchOrCreateEglFramebuffer(const EGLDisplay eglDisplay,const int streamId,const int bufferId)150 VirtualCameraSessionContext::fetchOrCreateEglFramebuffer(
151     const EGLDisplay eglDisplay, const int streamId, const int bufferId) {
152   std::lock_guard<std::mutex> lock(mLock);
153   auto it = mStreams.find(streamId);
154   if (it == mStreams.end()) {
155     ALOGE("%s: StreamBuffer references buffer of unknown streamId %d", __func__,
156           streamId);
157     return nullptr;
158   }
159   VirtualCameraStream& stream = *it->second;
160   return stream.getEglFrameBuffer(eglDisplay, bufferId);
161 }
162 
getStreamIds() const163 std::set<int> VirtualCameraSessionContext::getStreamIds() const {
164   std::set<int> result;
165   std::lock_guard<std::mutex> lock(mLock);
166   for (const auto& [streamId, _] : mStreams) {
167     result.insert(streamId);
168   }
169   return result;
170 }
171 
172 }  // namespace virtualcamera
173 }  // namespace companion
174 }  // namespace android
175