Home | History | Annotate | Download | only in bufferpool
      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 
     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 
     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 
     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 
     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 
    112 sp<ConnectionDeathRecipient> Accessor::getConnectionDeathRecipient() {
    113     return sConnectionDeathRecipient;
    114 }
    115 
    116 // Methods from ::android::hardware::media::bufferpool::V1_0::IAccessor follow.
    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 
    134 Accessor::Accessor(const std::shared_ptr<BufferPoolAllocator> &allocator)
    135     : mImpl(new Impl(allocator)) {}
    136 
    137 Accessor::~Accessor() {
    138 }
    139 
    140 bool Accessor::isValid() {
    141     return (bool)mImpl;
    142 }
    143 
    144 ResultStatus Accessor::allocate(
    145         ConnectionId connectionId,
    146         const std::vector<uint8_t> &params,
    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 
    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 
    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 
    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 
    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