1 /*
2  * Copyright (C) 2018 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 #define LOG_TAG "BufferPoolConnection"
17 
18 #include "Accessor.h"
19 #include "AccessorImpl.h"
20 #include "Connection.h"
21 
22 namespace android {
23 namespace hardware {
24 namespace media {
25 namespace bufferpool {
26 namespace V2_0 {
27 namespace implementation {
28 
add(int64_t connectionId,const sp<Accessor> & accessor)29 void ConnectionDeathRecipient::add(
30         int64_t connectionId,
31         const sp<Accessor> &accessor) {
32     std::lock_guard<std::mutex> lock(mLock);
33     if (mAccessors.find(connectionId) == mAccessors.end()) {
34         mAccessors.insert(std::make_pair(connectionId, accessor));
35     }
36 }
37 
remove(int64_t connectionId)38 void ConnectionDeathRecipient::remove(int64_t connectionId) {
39     std::lock_guard<std::mutex> lock(mLock);
40     mAccessors.erase(connectionId);
41     auto it = mConnectionToCookie.find(connectionId);
42     if (it != mConnectionToCookie.end()) {
43         uint64_t cookie = it->second;
44         mConnectionToCookie.erase(it);
45         auto cit = mCookieToConnections.find(cookie);
46         if (cit != mCookieToConnections.end()) {
47             cit->second.erase(connectionId);
48             if (cit->second.size() == 0) {
49                 mCookieToConnections.erase(cit);
50             }
51         }
52     }
53 }
54 
addCookieToConnection(uint64_t cookie,int64_t connectionId)55 void ConnectionDeathRecipient::addCookieToConnection(
56         uint64_t cookie,
57         int64_t connectionId) {
58     std::lock_guard<std::mutex> lock(mLock);
59     if (mAccessors.find(connectionId) == mAccessors.end()) {
60         return;
61     }
62     mConnectionToCookie.insert(std::make_pair(connectionId, cookie));
63     auto it = mCookieToConnections.find(cookie);
64     if (it != mCookieToConnections.end()) {
65         it->second.insert(connectionId);
66     } else {
67         mCookieToConnections.insert(std::make_pair(
68                 cookie, std::set<int64_t>{connectionId}));
69     }
70 }
71 
serviceDied(uint64_t cookie,const wp<::android::hidl::base::V1_0::IBase> &)72 void ConnectionDeathRecipient::serviceDied(
73         uint64_t cookie,
74         const wp<::android::hidl::base::V1_0::IBase>& /* who */
75         ) {
76     std::map<int64_t, const wp<Accessor>> connectionsToClose;
77     {
78         std::lock_guard<std::mutex> lock(mLock);
79 
80         auto it = mCookieToConnections.find(cookie);
81         if (it != mCookieToConnections.end()) {
82             for (auto conIt = it->second.begin(); conIt != it->second.end(); ++conIt) {
83                 auto accessorIt = mAccessors.find(*conIt);
84                 if (accessorIt != mAccessors.end()) {
85                     connectionsToClose.insert(std::make_pair(*conIt, accessorIt->second));
86                     mAccessors.erase(accessorIt);
87                 }
88                 mConnectionToCookie.erase(*conIt);
89             }
90             mCookieToConnections.erase(it);
91         }
92     }
93 
94     if (connectionsToClose.size() > 0) {
95         sp<Accessor> accessor;
96         for (auto it = connectionsToClose.begin(); it != connectionsToClose.end(); ++it) {
97             accessor = it->second.promote();
98 
99             if (accessor) {
100                 accessor->close(it->first);
101                 ALOGD("connection %lld closed on death", (long long)it->first);
102             }
103         }
104     }
105 }
106 
107 namespace {
108 static sp<ConnectionDeathRecipient> sConnectionDeathRecipient =
109         new ConnectionDeathRecipient();
110 }
111 
getConnectionDeathRecipient()112 sp<ConnectionDeathRecipient> Accessor::getConnectionDeathRecipient() {
113     return sConnectionDeathRecipient;
114 }
115 
createInvalidator()116 void Accessor::createInvalidator() {
117     Accessor::Impl::createInvalidator();
118 }
119 
createEvictor()120 void Accessor::createEvictor() {
121     Accessor::Impl::createEvictor();
122 }
123 
124 // Methods from ::android::hardware::media::bufferpool::V2_0::IAccessor follow.
connect(const sp<::android::hardware::media::bufferpool::V2_0::IObserver> & observer,connect_cb _hidl_cb)125 Return<void> Accessor::connect(
126         const sp<::android::hardware::media::bufferpool::V2_0::IObserver>& observer,
127         connect_cb _hidl_cb) {
128     sp<Connection> connection;
129     ConnectionId connectionId;
130     uint32_t msgId;
131     const StatusDescriptor* fmqDesc;
132     const InvalidationDescriptor* invDesc;
133 
134     ResultStatus status = connect(
135             observer, false, &connection, &connectionId, &msgId, &fmqDesc, &invDesc);
136     if (status == ResultStatus::OK) {
137         _hidl_cb(status, connection, connectionId, msgId, *fmqDesc, *invDesc);
138     } else {
139         _hidl_cb(status, nullptr, -1LL, 0,
140                  android::hardware::MQDescriptorSync<BufferStatusMessage>(
141                          std::vector<android::hardware::GrantorDescriptor>(),
142                          nullptr /* nhandle */, 0 /* size */),
143                  android::hardware::MQDescriptorUnsync<BufferInvalidationMessage>(
144                          std::vector<android::hardware::GrantorDescriptor>(),
145                          nullptr /* nhandle */, 0 /* size */));
146     }
147     return Void();
148 }
149 
Accessor(const std::shared_ptr<BufferPoolAllocator> & allocator)150 Accessor::Accessor(const std::shared_ptr<BufferPoolAllocator> &allocator)
151     : mImpl(new Impl(allocator)) {}
152 
~Accessor()153 Accessor::~Accessor() {
154 }
155 
isValid()156 bool Accessor::isValid() {
157     return (bool)mImpl && mImpl->isValid();
158 }
159 
flush()160 ResultStatus Accessor::flush() {
161     if (mImpl) {
162         mImpl->flush();
163         return ResultStatus::OK;
164     }
165     return ResultStatus::CRITICAL_ERROR;
166 }
167 
allocate(ConnectionId connectionId,const std::vector<uint8_t> & params,BufferId * bufferId,const native_handle_t ** handle)168 ResultStatus Accessor::allocate(
169         ConnectionId connectionId,
170         const std::vector<uint8_t> &params,
171         BufferId *bufferId, const native_handle_t** handle) {
172     if (mImpl) {
173         return mImpl->allocate(connectionId, params, bufferId, handle);
174     }
175     return ResultStatus::CRITICAL_ERROR;
176 }
177 
fetch(ConnectionId connectionId,TransactionId transactionId,BufferId bufferId,const native_handle_t ** handle)178 ResultStatus Accessor::fetch(
179         ConnectionId connectionId, TransactionId transactionId,
180         BufferId bufferId, const native_handle_t** handle) {
181     if (mImpl) {
182         return mImpl->fetch(connectionId, transactionId, bufferId, handle);
183     }
184     return ResultStatus::CRITICAL_ERROR;
185 }
186 
connect(const sp<IObserver> & observer,bool local,sp<Connection> * connection,ConnectionId * pConnectionId,uint32_t * pMsgId,const StatusDescriptor ** statusDescPtr,const InvalidationDescriptor ** invDescPtr)187 ResultStatus Accessor::connect(
188         const sp<IObserver> &observer, bool local,
189         sp<Connection> *connection, ConnectionId *pConnectionId,
190         uint32_t *pMsgId,
191         const StatusDescriptor** statusDescPtr,
192         const InvalidationDescriptor** invDescPtr) {
193     if (mImpl) {
194         ResultStatus status = mImpl->connect(
195                 this, observer, connection, pConnectionId, pMsgId,
196                 statusDescPtr, invDescPtr);
197         if (!local && status == ResultStatus::OK) {
198             sp<Accessor> accessor(this);
199             sConnectionDeathRecipient->add(*pConnectionId, accessor);
200         }
201         return status;
202     }
203     return ResultStatus::CRITICAL_ERROR;
204 }
205 
close(ConnectionId connectionId)206 ResultStatus Accessor::close(ConnectionId connectionId) {
207     if (mImpl) {
208         ResultStatus status = mImpl->close(connectionId);
209         sConnectionDeathRecipient->remove(connectionId);
210         return status;
211     }
212     return ResultStatus::CRITICAL_ERROR;
213 }
214 
cleanUp(bool clearCache)215 void Accessor::cleanUp(bool clearCache) {
216     if (mImpl) {
217         mImpl->cleanUp(clearCache);
218     }
219 }
220 
221 //IAccessor* HIDL_FETCH_IAccessor(const char* /* name */) {
222 //    return new Accessor();
223 //}
224 
225 }  // namespace implementation
226 }  // namespace V2_0
227 }  // namespace bufferpool
228 }  // namespace media
229 }  // namespace hardware
230 }  // namespace android
231