Home | History | Annotate | Download | only in oboeservice
      1 /*
      2  * Copyright (C) 2017 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 #define LOG_TAG "AAudioEndpointManager"
     18 //#define LOG_NDEBUG 0
     19 #include <utils/Log.h>
     20 
     21 #include <assert.h>
     22 #include <functional>
     23 #include <map>
     24 #include <mutex>
     25 #include <sstream>
     26 #include <utility/AAudioUtilities.h>
     27 
     28 #include "AAudioEndpointManager.h"
     29 #include "AAudioServiceEndpointShared.h"
     30 #include "AAudioServiceEndpointMMAP.h"
     31 #include "AAudioServiceEndpointCapture.h"
     32 #include "AAudioServiceEndpointPlay.h"
     33 
     34 using namespace android;
     35 using namespace aaudio;
     36 
     37 ANDROID_SINGLETON_STATIC_INSTANCE(AAudioEndpointManager);
     38 
     39 AAudioEndpointManager::AAudioEndpointManager()
     40         : Singleton<AAudioEndpointManager>()
     41         , mSharedStreams()
     42         , mExclusiveStreams() {
     43 }
     44 
     45 std::string AAudioEndpointManager::dump() const {
     46     std::stringstream result;
     47     int index = 0;
     48 
     49     result << "AAudioEndpointManager:" << "\n";
     50 
     51     const bool isSharedLocked = AAudio_tryUntilTrue(
     52             [this]()->bool { return mSharedLock.try_lock(); } /* f */,
     53             50 /* times */,
     54             20 /* sleepMs */);
     55     if (!isSharedLocked) {
     56         result << "AAudioEndpointManager Shared may be deadlocked\n";
     57     }
     58 
     59     {
     60         const bool isExclusiveLocked = AAudio_tryUntilTrue(
     61                 [this]() -> bool { return mExclusiveLock.try_lock(); } /* f */,
     62                 50 /* times */,
     63                 20 /* sleepMs */);
     64         if (!isExclusiveLocked) {
     65             result << "AAudioEndpointManager Exclusive may be deadlocked\n";
     66         }
     67 
     68         result << "Exclusive MMAP Endpoints: " << mExclusiveStreams.size() << "\n";
     69         index = 0;
     70         for (const auto &stream : mExclusiveStreams) {
     71             result << "  #" << index++ << ":";
     72             result << stream->dump() << "\n";
     73         }
     74 
     75         result << "  ExclusiveSearchCount:  " << mExclusiveSearchCount << "\n";
     76         result << "  ExclusiveFoundCount:   " << mExclusiveFoundCount << "\n";
     77         result << "  ExclusiveOpenCount:    " << mExclusiveOpenCount << "\n";
     78         result << "  ExclusiveCloseCount:   " << mExclusiveCloseCount << "\n";
     79         result << "\n";
     80 
     81         if (isExclusiveLocked) {
     82             mExclusiveLock.unlock();
     83         }
     84     }
     85 
     86     result << "Shared Endpoints: " << mSharedStreams.size() << "\n";
     87     index = 0;
     88     for (const auto &stream : mSharedStreams) {
     89         result << "  #" << index++ << ":";
     90         result << stream->dump() << "\n";
     91     }
     92 
     93     result << "  SharedSearchCount:     " << mSharedSearchCount << "\n";
     94     result << "  SharedFoundCount:      " << mSharedFoundCount << "\n";
     95     result << "  SharedOpenCount:       " << mSharedOpenCount << "\n";
     96     result << "  SharedCloseCount:      " << mSharedCloseCount << "\n";
     97     result << "\n";
     98 
     99     if (isSharedLocked) {
    100         mSharedLock.unlock();
    101     }
    102     return result.str();
    103 }
    104 
    105 
    106 // Try to find an existing endpoint.
    107 sp<AAudioServiceEndpoint> AAudioEndpointManager::findExclusiveEndpoint_l(
    108         const AAudioStreamConfiguration &configuration) {
    109     sp<AAudioServiceEndpoint> endpoint;
    110     mExclusiveSearchCount++;
    111     for (const auto ep : mExclusiveStreams) {
    112         if (ep->matches(configuration)) {
    113             mExclusiveFoundCount++;
    114             endpoint = ep;
    115             break;
    116         }
    117     }
    118 
    119     ALOGV("findExclusiveEndpoint_l(), found %p for device = %d, sessionId = %d",
    120           endpoint.get(), configuration.getDeviceId(), configuration.getSessionId());
    121     return endpoint;
    122 }
    123 
    124 // Try to find an existing endpoint.
    125 sp<AAudioServiceEndpointShared> AAudioEndpointManager::findSharedEndpoint_l(
    126         const AAudioStreamConfiguration &configuration) {
    127     sp<AAudioServiceEndpointShared> endpoint;
    128     mSharedSearchCount++;
    129     for (const auto ep  : mSharedStreams) {
    130         if (ep->matches(configuration)) {
    131             mSharedFoundCount++;
    132             endpoint = ep;
    133             break;
    134         }
    135     }
    136 
    137     ALOGV("findSharedEndpoint_l(), found %p for device = %d, sessionId = %d",
    138           endpoint.get(), configuration.getDeviceId(), configuration.getSessionId());
    139     return endpoint;
    140 }
    141 
    142 sp<AAudioServiceEndpoint> AAudioEndpointManager::openEndpoint(AAudioService &audioService,
    143                                         const aaudio::AAudioStreamRequest &request,
    144                                         aaudio_sharing_mode_t sharingMode) {
    145     if (sharingMode == AAUDIO_SHARING_MODE_EXCLUSIVE) {
    146         return openExclusiveEndpoint(audioService, request);
    147     } else {
    148         return openSharedEndpoint(audioService, request);
    149     }
    150 }
    151 
    152 sp<AAudioServiceEndpoint> AAudioEndpointManager::openExclusiveEndpoint(
    153         AAudioService &aaudioService,
    154         const aaudio::AAudioStreamRequest &request) {
    155 
    156     std::lock_guard<std::mutex> lock(mExclusiveLock);
    157 
    158     const AAudioStreamConfiguration &configuration = request.getConstantConfiguration();
    159 
    160     // Try to find an existing endpoint.
    161     sp<AAudioServiceEndpoint> endpoint = findExclusiveEndpoint_l(configuration);
    162 
    163     // If we find an existing one then this one cannot be exclusive.
    164     if (endpoint.get() != nullptr) {
    165         ALOGW("openExclusiveEndpoint() already in use");
    166         // Already open so do not allow a second stream.
    167         return nullptr;
    168     } else {
    169         sp<AAudioServiceEndpointMMAP> endpointMMap = new AAudioServiceEndpointMMAP(aaudioService);
    170         ALOGV("openExclusiveEndpoint(), no match so try to open MMAP %p for dev %d",
    171               endpointMMap.get(), configuration.getDeviceId());
    172         endpoint = endpointMMap;
    173 
    174         aaudio_result_t result = endpoint->open(request);
    175         if (result != AAUDIO_OK) {
    176             ALOGE("openExclusiveEndpoint(), open failed");
    177             endpoint.clear();
    178         } else {
    179             mExclusiveStreams.push_back(endpointMMap);
    180             mExclusiveOpenCount++;
    181         }
    182     }
    183 
    184     if (endpoint.get() != nullptr) {
    185         // Increment the reference count under this lock.
    186         endpoint->setOpenCount(endpoint->getOpenCount() + 1);
    187     }
    188     return endpoint;
    189 }
    190 
    191 sp<AAudioServiceEndpoint> AAudioEndpointManager::openSharedEndpoint(
    192         AAudioService &aaudioService,
    193         const aaudio::AAudioStreamRequest &request) {
    194 
    195     std::lock_guard<std::mutex> lock(mSharedLock);
    196 
    197     const AAudioStreamConfiguration &configuration = request.getConstantConfiguration();
    198     aaudio_direction_t direction = configuration.getDirection();
    199 
    200     // Try to find an existing endpoint.
    201     sp<AAudioServiceEndpointShared> endpoint = findSharedEndpoint_l(configuration);
    202 
    203     // If we can't find an existing one then open a new one.
    204     if (endpoint.get() == nullptr) {
    205         // we must call openStream with audioserver identity
    206         int64_t token = IPCThreadState::self()->clearCallingIdentity();
    207         switch (direction) {
    208             case AAUDIO_DIRECTION_INPUT:
    209                 endpoint = new AAudioServiceEndpointCapture(aaudioService);
    210                 break;
    211             case AAUDIO_DIRECTION_OUTPUT:
    212                 endpoint = new AAudioServiceEndpointPlay(aaudioService);
    213                 break;
    214             default:
    215                 break;
    216         }
    217 
    218         if (endpoint.get() != nullptr) {
    219             aaudio_result_t result = endpoint->open(request);
    220             if (result != AAUDIO_OK) {
    221                 endpoint.clear();
    222             } else {
    223                 mSharedStreams.push_back(endpoint);
    224                 mSharedOpenCount++;
    225             }
    226         }
    227         ALOGV("%s(), created endpoint %p, requested device = %d, dir = %d",
    228               __func__, endpoint.get(), configuration.getDeviceId(), (int)direction);
    229         IPCThreadState::self()->restoreCallingIdentity(token);
    230     }
    231 
    232     if (endpoint.get() != nullptr) {
    233         // Increment the reference count under this lock.
    234         endpoint->setOpenCount(endpoint->getOpenCount() + 1);
    235     }
    236     return endpoint;
    237 }
    238 
    239 void AAudioEndpointManager::closeEndpoint(sp<AAudioServiceEndpoint>serviceEndpoint) {
    240     if (serviceEndpoint->getSharingMode() == AAUDIO_SHARING_MODE_EXCLUSIVE) {
    241         return closeExclusiveEndpoint(serviceEndpoint);
    242     } else {
    243         return closeSharedEndpoint(serviceEndpoint);
    244     }
    245 }
    246 
    247 void AAudioEndpointManager::closeExclusiveEndpoint(sp<AAudioServiceEndpoint> serviceEndpoint) {
    248     if (serviceEndpoint.get() == nullptr) {
    249         return;
    250     }
    251 
    252     // Decrement the reference count under this lock.
    253     std::lock_guard<std::mutex> lock(mExclusiveLock);
    254     int32_t newRefCount = serviceEndpoint->getOpenCount() - 1;
    255     serviceEndpoint->setOpenCount(newRefCount);
    256 
    257     // If no longer in use then actually close it.
    258     if (newRefCount <= 0) {
    259         mExclusiveStreams.erase(
    260                 std::remove(mExclusiveStreams.begin(), mExclusiveStreams.end(), serviceEndpoint),
    261                 mExclusiveStreams.end());
    262 
    263         serviceEndpoint->close();
    264         mExclusiveCloseCount++;
    265         ALOGV("%s() %p for device %d",
    266               __func__, serviceEndpoint.get(), serviceEndpoint->getDeviceId());
    267     }
    268 }
    269 
    270 void AAudioEndpointManager::closeSharedEndpoint(sp<AAudioServiceEndpoint> serviceEndpoint) {
    271     if (serviceEndpoint.get() == nullptr) {
    272         return;
    273     }
    274 
    275     // Decrement the reference count under this lock.
    276     std::lock_guard<std::mutex> lock(mSharedLock);
    277     int32_t newRefCount = serviceEndpoint->getOpenCount() - 1;
    278     serviceEndpoint->setOpenCount(newRefCount);
    279 
    280     // If no longer in use then actually close it.
    281     if (newRefCount <= 0) {
    282         mSharedStreams.erase(
    283                 std::remove(mSharedStreams.begin(), mSharedStreams.end(), serviceEndpoint),
    284                 mSharedStreams.end());
    285 
    286         serviceEndpoint->close();
    287         mSharedCloseCount++;
    288         ALOGV("%s() %p for device %d",
    289               __func__, serviceEndpoint.get(), serviceEndpoint->getDeviceId());
    290     }
    291 }
    292