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 V1_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
116 // Methods from ::android::hardware::media::bufferpool::V1_0::IAccessor follow.
connect(connect_cb _hidl_cb)117 Return<void> Accessor::connect(connect_cb _hidl_cb) {
118 sp<Connection> connection;
119 ConnectionId connectionId;
120 const QueueDescriptor* fmqDesc;
121
122 ResultStatus status = connect(&connection, &connectionId, &fmqDesc, false);
123 if (status == ResultStatus::OK) {
124 _hidl_cb(status, connection, connectionId, *fmqDesc);
125 } else {
126 _hidl_cb(status, nullptr, -1LL,
127 android::hardware::MQDescriptorSync<BufferStatusMessage>(
128 std::vector<android::hardware::GrantorDescriptor>(),
129 nullptr /* nhandle */, 0 /* size */));
130 }
131 return Void();
132 }
133
Accessor(const std::shared_ptr<BufferPoolAllocator> & allocator)134 Accessor::Accessor(const std::shared_ptr<BufferPoolAllocator> &allocator)
135 : mImpl(new Impl(allocator)) {}
136
~Accessor()137 Accessor::~Accessor() {
138 }
139
isValid()140 bool Accessor::isValid() {
141 return (bool)mImpl;
142 }
143
allocate(ConnectionId connectionId,const std::vector<uint8_t> & params,BufferId * bufferId,const native_handle_t ** handle)144 ResultStatus Accessor::allocate(
145 ConnectionId connectionId,
146 const std::vector<uint8_t> ¶ms,
147 BufferId *bufferId, const native_handle_t** handle) {
148 if (mImpl) {
149 return mImpl->allocate(connectionId, params, bufferId, handle);
150 }
151 return ResultStatus::CRITICAL_ERROR;
152 }
153
fetch(ConnectionId connectionId,TransactionId transactionId,BufferId bufferId,const native_handle_t ** handle)154 ResultStatus Accessor::fetch(
155 ConnectionId connectionId, TransactionId transactionId,
156 BufferId bufferId, const native_handle_t** handle) {
157 if (mImpl) {
158 return mImpl->fetch(connectionId, transactionId, bufferId, handle);
159 }
160 return ResultStatus::CRITICAL_ERROR;
161 }
162
connect(sp<Connection> * connection,ConnectionId * pConnectionId,const QueueDescriptor ** fmqDescPtr,bool local)163 ResultStatus Accessor::connect(
164 sp<Connection> *connection, ConnectionId *pConnectionId,
165 const QueueDescriptor** fmqDescPtr, bool local) {
166 if (mImpl) {
167 ResultStatus status = mImpl->connect(this, connection, pConnectionId, fmqDescPtr);
168 if (!local && status == ResultStatus::OK) {
169 sp<Accessor> accessor(this);
170 sConnectionDeathRecipient->add(*pConnectionId, accessor);
171 }
172 return status;
173 }
174 return ResultStatus::CRITICAL_ERROR;
175 }
176
close(ConnectionId connectionId)177 ResultStatus Accessor::close(ConnectionId connectionId) {
178 if (mImpl) {
179 ResultStatus status = mImpl->close(connectionId);
180 sConnectionDeathRecipient->remove(connectionId);
181 return status;
182 }
183 return ResultStatus::CRITICAL_ERROR;
184 }
185
cleanUp(bool clearCache)186 void Accessor::cleanUp(bool clearCache) {
187 if (mImpl) {
188 mImpl->cleanUp(clearCache);
189 }
190 }
191
192 //IAccessor* HIDL_FETCH_IAccessor(const char* /* name */) {
193 // return new Accessor();
194 //}
195
196 } // namespace implementation
197 } // namespace V1_0
198 } // namespace bufferpool
199 } // namespace media
200 } // namespace hardware
201 } // namespace android
202