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 
     18 #define LOG_TAG "AAudioClientTracker"
     19 //#define LOG_NDEBUG 0
     20 #include <utils/Log.h>
     21 
     22 #include <assert.h>
     23 #include <binder/IPCThreadState.h>
     24 #include <iomanip>
     25 #include <iostream>
     26 #include <map>
     27 #include <mutex>
     28 #include <utils/Singleton.h>
     29 
     30 #include "utility/AAudioUtilities.h"
     31 #include "AAudioEndpointManager.h"
     32 #include "AAudioServiceEndpoint.h"
     33 #include "AAudioClientTracker.h"
     34 
     35 using namespace android;
     36 using namespace aaudio;
     37 
     38 ANDROID_SINGLETON_STATIC_INSTANCE(AAudioClientTracker);
     39 
     40 AAudioClientTracker::AAudioClientTracker()
     41         : Singleton<AAudioClientTracker>() {
     42 }
     43 
     44 std::string AAudioClientTracker::dump() const {
     45     std::stringstream result;
     46     const bool isLocked = AAudio_tryUntilTrue(
     47             [this]()->bool { return mLock.try_lock(); } /* f */,
     48             50 /* times */,
     49             20 /* sleepMs */);
     50     if (!isLocked) {
     51         result << "AAudioClientTracker may be deadlocked\n";
     52     }
     53 
     54     result << "AAudioClientTracker:\n";
     55     for (const auto&  it : mNotificationClients) {
     56         result << it.second->dump();
     57     }
     58 
     59     if (isLocked) {
     60         mLock.unlock();
     61     }
     62     return result.str();
     63 }
     64 
     65 // Create a tracker for the client.
     66 aaudio_result_t AAudioClientTracker::registerClient(pid_t pid,
     67                                          const sp<IAAudioClient>& client) {
     68     ALOGV("registerClient(), calling pid = %d, getpid() = %d\n", pid, getpid());
     69 
     70     if (client.get() == nullptr) {
     71         ALOGE("AAudioClientTracker::%s() client is NULL!", __func__);
     72         android_errorWriteLog(0x534e4554, "116230453");
     73         return AAUDIO_ERROR_NULL;
     74     }
     75 
     76     std::lock_guard<std::mutex> lock(mLock);
     77     if (mNotificationClients.count(pid) == 0) {
     78         sp<NotificationClient> notificationClient = new NotificationClient(pid);
     79         mNotificationClients[pid] = notificationClient;
     80 
     81         sp<IBinder> binder = IInterface::asBinder(client);
     82         status_t status = binder->linkToDeath(notificationClient);
     83         ALOGW_IF(status != NO_ERROR, "registerClient() linkToDeath = %d\n", status);
     84         return AAudioConvert_androidToAAudioResult(status);
     85     } else {
     86         ALOGW("registerClient(%d) already registered!", pid);
     87         return AAUDIO_OK; // TODO should this be considered an error
     88     }
     89 }
     90 
     91 void AAudioClientTracker::unregisterClient(pid_t pid) {
     92     ALOGV("unregisterClient(), calling pid = %d, getpid() = %d\n", pid, getpid());
     93     std::lock_guard<std::mutex> lock(mLock);
     94     mNotificationClients.erase(pid);
     95 }
     96 
     97 int32_t AAudioClientTracker::getStreamCount(pid_t pid) {
     98     std::lock_guard<std::mutex> lock(mLock);
     99     auto it = mNotificationClients.find(pid);
    100     if (it != mNotificationClients.end()) {
    101         return it->second->getStreamCount();
    102     } else {
    103         return 0; // no existing client
    104     }
    105 }
    106 
    107 aaudio_result_t
    108 AAudioClientTracker::registerClientStream(pid_t pid, sp<AAudioServiceStreamBase> serviceStream) {
    109     aaudio_result_t result = AAUDIO_OK;
    110     ALOGV("registerClientStream(%d,)\n", pid);
    111     std::lock_guard<std::mutex> lock(mLock);
    112     sp<NotificationClient> notificationClient = mNotificationClients[pid];
    113     if (notificationClient == 0) {
    114         // This will get called the first time the audio server registers an internal stream.
    115         ALOGV("registerClientStream(%d,) unrecognized pid\n", pid);
    116         notificationClient = new NotificationClient(pid);
    117         mNotificationClients[pid] = notificationClient;
    118     }
    119     notificationClient->registerClientStream(serviceStream);
    120     return result;
    121 }
    122 
    123 // Find the tracker for this process and remove it.
    124 aaudio_result_t
    125 AAudioClientTracker::unregisterClientStream(pid_t pid,
    126                                             sp<AAudioServiceStreamBase> serviceStream) {
    127     ALOGV("unregisterClientStream(%d,)\n", pid);
    128     std::lock_guard<std::mutex> lock(mLock);
    129     auto it = mNotificationClients.find(pid);
    130     if (it != mNotificationClients.end()) {
    131         ALOGV("unregisterClientStream(%d,) found NotificationClient\n", pid);
    132         it->second->unregisterClientStream(serviceStream);
    133     } else {
    134         ALOGE("unregisterClientStream(%d,) missing NotificationClient\n", pid);
    135     }
    136     return AAUDIO_OK;
    137 }
    138 
    139 AAudioClientTracker::NotificationClient::NotificationClient(pid_t pid)
    140         : mProcessId(pid) {
    141 }
    142 
    143 AAudioClientTracker::NotificationClient::~NotificationClient() {
    144 }
    145 
    146 int32_t AAudioClientTracker::NotificationClient::getStreamCount() {
    147     std::lock_guard<std::mutex> lock(mLock);
    148     return mStreams.size();
    149 }
    150 
    151 aaudio_result_t AAudioClientTracker::NotificationClient::registerClientStream(
    152         sp<AAudioServiceStreamBase> serviceStream) {
    153     std::lock_guard<std::mutex> lock(mLock);
    154     mStreams.insert(serviceStream);
    155     return AAUDIO_OK;
    156 }
    157 
    158 aaudio_result_t AAudioClientTracker::NotificationClient::unregisterClientStream(
    159         sp<AAudioServiceStreamBase> serviceStream) {
    160     std::lock_guard<std::mutex> lock(mLock);
    161     mStreams.erase(serviceStream);
    162     return AAUDIO_OK;
    163 }
    164 
    165 // Close any open streams for the client.
    166 void AAudioClientTracker::NotificationClient::binderDied(const wp<IBinder>& who __unused) {
    167     AAudioService *aaudioService = AAudioClientTracker::getInstance().getAAudioService();
    168     if (aaudioService != nullptr) {
    169         // Copy the current list of streams to another vector because closing them below
    170         // will cause unregisterClientStream() calls back to this object.
    171         std::set<sp<AAudioServiceStreamBase>>  streamsToClose;
    172 
    173         {
    174             std::lock_guard<std::mutex> lock(mLock);
    175             for (const auto& serviceStream : mStreams) {
    176                 streamsToClose.insert(serviceStream);
    177             }
    178         }
    179 
    180         for (const auto& serviceStream : streamsToClose) {
    181             aaudio_handle_t handle = serviceStream->getHandle();
    182             ALOGW("binderDied() close abandoned stream 0x%08X\n", handle);
    183             aaudioService->closeStream(handle);
    184         }
    185         // mStreams should be empty now
    186     }
    187     sp<NotificationClient> keep(this);
    188     AAudioClientTracker::getInstance().unregisterClient(mProcessId);
    189 }
    190 
    191 
    192 std::string AAudioClientTracker::NotificationClient::dump() const {
    193     std::stringstream result;
    194     const bool isLocked = AAudio_tryUntilTrue(
    195             [this]()->bool { return mLock.try_lock(); } /* f */,
    196             50 /* times */,
    197             20 /* sleepMs */);
    198     if (!isLocked) {
    199         result << "AAudioClientTracker::NotificationClient may be deadlocked\n";
    200     }
    201 
    202     result << "  client: pid = " << mProcessId << " has " << mStreams.size() << " streams\n";
    203     for (const auto& serviceStream : mStreams) {
    204         result << "     stream: 0x" << std::setfill('0') << std::setw(8) << std::hex
    205                << serviceStream->getHandle()
    206                << std::dec << std::setfill(' ') << "\n";
    207     }
    208 
    209     if (isLocked) {
    210         mLock.unlock();
    211     }
    212     return result.str();
    213 }
    214