111e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk/*
211e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk * Copyright (C) 2017 The Android Open Source Project
311e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk *
411e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk * Licensed under the Apache License, Version 2.0 (the "License");
511e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk * you may not use this file except in compliance with the License.
611e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk * You may obtain a copy of the License at
711e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk *
811e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk *      http://www.apache.org/licenses/LICENSE-2.0
911e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk *
1011e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk * Unless required by applicable law or agreed to in writing, software
1111e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk * distributed under the License is distributed on an "AS IS" BASIS,
1211e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1311e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk * See the License for the specific language governing permissions and
1411e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk * limitations under the License.
1511e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk */
1611e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk
1711e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk
18fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk#define LOG_TAG "AAudioClientTracker"
1911e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk//#define LOG_NDEBUG 0
2011e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk#include <utils/Log.h>
2111e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk
2211e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk#include <assert.h>
2311e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk#include <binder/IPCThreadState.h>
2455e5eabf96af5a2964bfab1e64d81ad9be9ac975Phil Burk#include <iomanip>
2555e5eabf96af5a2964bfab1e64d81ad9be9ac975Phil Burk#include <iostream>
2611e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk#include <map>
2711e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk#include <mutex>
2811e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk#include <utils/Singleton.h>
2911e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk
3011e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk#include "utility/AAudioUtilities.h"
3111e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk#include "AAudioEndpointManager.h"
3211e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk#include "AAudioServiceEndpoint.h"
3311e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk#include "AAudioClientTracker.h"
3411e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk
3511e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burkusing namespace android;
3611e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burkusing namespace aaudio;
3711e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk
3811e8d335b1da528ee771b19b63df23ae6fd52f41Phil BurkANDROID_SINGLETON_STATIC_INSTANCE(AAudioClientTracker);
3911e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk
4011e8d335b1da528ee771b19b63df23ae6fd52f41Phil BurkAAudioClientTracker::AAudioClientTracker()
4111e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk        : Singleton<AAudioClientTracker>() {
4211e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk}
4311e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk
444501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burkstd::string AAudioClientTracker::dump() const {
454501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk    std::stringstream result;
464501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk    const bool isLocked = AAudio_tryUntilTrue(
474501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk            [this]()->bool { return mLock.try_lock(); } /* f */,
484501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk            50 /* times */,
494501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk            20 /* sleepMs */);
504501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk    if (!isLocked) {
514501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk        result << "AAudioClientTracker may be deadlocked\n";
524501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk    }
534501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk
544501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk    result << "AAudioClientTracker:\n";
554501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk    for (const auto&  it : mNotificationClients) {
564501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk        result << it.second->dump();
574501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk    }
584501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk
594501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk    if (isLocked) {
604501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk        mLock.unlock();
614501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk    }
624501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk    return result.str();
634501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk}
644501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk
6511e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk// Create a tracker for the client.
6611e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burkaaudio_result_t AAudioClientTracker::registerClient(pid_t pid,
6711e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk                                         const sp<IAAudioClient>& client) {
68fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk    ALOGV("registerClient(), calling pid = %d, getpid() = %d\n", pid, getpid());
6911e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk
7011e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk    std::lock_guard<std::mutex> lock(mLock);
7111e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk    if (mNotificationClients.count(pid) == 0) {
7211e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk        sp<NotificationClient> notificationClient = new NotificationClient(pid);
7311e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk        mNotificationClients[pid] = notificationClient;
7411e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk
7511e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk        sp<IBinder> binder = IInterface::asBinder(client);
7611e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk        status_t status = binder->linkToDeath(notificationClient);
77fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk        ALOGW_IF(status != NO_ERROR, "registerClient() linkToDeath = %d\n", status);
7811e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk        return AAudioConvert_androidToAAudioResult(status);
7911e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk    } else {
80fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk        ALOGW("registerClient(%d) already registered!", pid);
8111e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk        return AAUDIO_OK; // TODO should this be considered an error
8211e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk    }
8311e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk}
8411e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk
8511e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burkvoid AAudioClientTracker::unregisterClient(pid_t pid) {
86fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk    ALOGV("unregisterClient(), calling pid = %d, getpid() = %d\n", pid, getpid());
8711e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk    std::lock_guard<std::mutex> lock(mLock);
8811e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk    mNotificationClients.erase(pid);
8911e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk}
9011e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk
919169294539ad46e08e2fe76a93c37ed965c13058Phil Burkint32_t AAudioClientTracker::getStreamCount(pid_t pid) {
929169294539ad46e08e2fe76a93c37ed965c13058Phil Burk    std::lock_guard<std::mutex> lock(mLock);
939169294539ad46e08e2fe76a93c37ed965c13058Phil Burk    auto it = mNotificationClients.find(pid);
949169294539ad46e08e2fe76a93c37ed965c13058Phil Burk    if (it != mNotificationClients.end()) {
959169294539ad46e08e2fe76a93c37ed965c13058Phil Burk        return it->second->getStreamCount();
969169294539ad46e08e2fe76a93c37ed965c13058Phil Burk    } else {
979169294539ad46e08e2fe76a93c37ed965c13058Phil Burk        return 0; // no existing client
989169294539ad46e08e2fe76a93c37ed965c13058Phil Burk    }
999169294539ad46e08e2fe76a93c37ed965c13058Phil Burk}
1009169294539ad46e08e2fe76a93c37ed965c13058Phil Burk
10111e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burkaaudio_result_t
10211e8d335b1da528ee771b19b63df23ae6fd52f41Phil BurkAAudioClientTracker::registerClientStream(pid_t pid, sp<AAudioServiceStreamBase> serviceStream) {
10311e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk    aaudio_result_t result = AAUDIO_OK;
104fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk    ALOGV("registerClientStream(%d, %p)\n", pid, serviceStream.get());
10511e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk    std::lock_guard<std::mutex> lock(mLock);
10611e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk    sp<NotificationClient> notificationClient = mNotificationClients[pid];
10711e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk    if (notificationClient == 0) {
10811e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk        // This will get called the first time the audio server registers an internal stream.
109fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk        ALOGV("registerClientStream(%d,) unrecognized pid\n", pid);
11011e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk        notificationClient = new NotificationClient(pid);
11111e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk        mNotificationClients[pid] = notificationClient;
11211e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk    }
11311e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk    notificationClient->registerClientStream(serviceStream);
11411e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk    return result;
11511e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk}
11611e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk
11711e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk// Find the tracker for this process and remove it.
11811e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burkaaudio_result_t
11911e8d335b1da528ee771b19b63df23ae6fd52f41Phil BurkAAudioClientTracker::unregisterClientStream(pid_t pid,
12011e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk                                            sp<AAudioServiceStreamBase> serviceStream) {
121fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk    ALOGV("unregisterClientStream(%d, %p)\n", pid, serviceStream.get());
12211e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk    std::lock_guard<std::mutex> lock(mLock);
1239169294539ad46e08e2fe76a93c37ed965c13058Phil Burk    auto it = mNotificationClients.find(pid);
12411e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk    if (it != mNotificationClients.end()) {
125fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk        ALOGV("unregisterClientStream(%d, %p) found NotificationClient\n",
1264501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk              pid, serviceStream.get());
12711e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk        it->second->unregisterClientStream(serviceStream);
1284501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk    } else {
129fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk        ALOGE("unregisterClientStream(%d, %p) missing NotificationClient\n",
1304501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk              pid, serviceStream.get());
13111e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk    }
13211e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk    return AAUDIO_OK;
13311e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk}
13411e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk
13511e8d335b1da528ee771b19b63df23ae6fd52f41Phil BurkAAudioClientTracker::NotificationClient::NotificationClient(pid_t pid)
13611e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk        : mProcessId(pid) {
137fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk    //ALOGD("NotificationClient(%d) created %p\n", pid, this);
13811e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk}
13911e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk
14011e8d335b1da528ee771b19b63df23ae6fd52f41Phil BurkAAudioClientTracker::NotificationClient::~NotificationClient() {
141fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk    //ALOGD("~NotificationClient() destroyed %p\n", this);
14211e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk}
14311e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk
1449169294539ad46e08e2fe76a93c37ed965c13058Phil Burkint32_t AAudioClientTracker::NotificationClient::getStreamCount() {
1459169294539ad46e08e2fe76a93c37ed965c13058Phil Burk    std::lock_guard<std::mutex> lock(mLock);
1469169294539ad46e08e2fe76a93c37ed965c13058Phil Burk    return mStreams.size();
1479169294539ad46e08e2fe76a93c37ed965c13058Phil Burk}
1489169294539ad46e08e2fe76a93c37ed965c13058Phil Burk
14911e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burkaaudio_result_t AAudioClientTracker::NotificationClient::registerClientStream(
15011e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk        sp<AAudioServiceStreamBase> serviceStream) {
15111e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk    std::lock_guard<std::mutex> lock(mLock);
15211e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk    mStreams.insert(serviceStream);
15311e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk    return AAUDIO_OK;
15411e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk}
15511e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk
15611e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burkaaudio_result_t AAudioClientTracker::NotificationClient::unregisterClientStream(
15711e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk        sp<AAudioServiceStreamBase> serviceStream) {
15811e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk    std::lock_guard<std::mutex> lock(mLock);
15911e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk    mStreams.erase(serviceStream);
16011e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk    return AAUDIO_OK;
16111e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk}
16211e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk
16311e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk// Close any open streams for the client.
16411e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burkvoid AAudioClientTracker::NotificationClient::binderDied(const wp<IBinder>& who __unused) {
16511e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk    AAudioService *aaudioService = AAudioClientTracker::getInstance().getAAudioService();
16611e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk    if (aaudioService != nullptr) {
16711e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk        // Copy the current list of streams to another vector because closing them below
16811e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk        // will cause unregisterClientStream() calls back to this object.
1694501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk        std::set<sp<AAudioServiceStreamBase>>  streamsToClose;
17011e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk
17111e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk        {
17211e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk            std::lock_guard<std::mutex> lock(mLock);
17348fc6191823ffa0708f60802fb6724c232760b9aChih-Hung Hsieh            for (const auto& serviceStream : mStreams) {
17411e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk                streamsToClose.insert(serviceStream);
17511e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk            }
17611e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk        }
17711e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk
17848fc6191823ffa0708f60802fb6724c232760b9aChih-Hung Hsieh        for (const auto& serviceStream : streamsToClose) {
17911e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk            aaudio_handle_t handle = serviceStream->getHandle();
180fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk            ALOGW("binderDied() close abandoned stream 0x%08X\n", handle);
18111e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk            aaudioService->closeStream(handle);
18211e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk        }
18311e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk        // mStreams should be empty now
18411e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk    }
18511e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk    sp<NotificationClient> keep(this);
18611e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk    AAudioClientTracker::getInstance().unregisterClient(mProcessId);
18711e8d335b1da528ee771b19b63df23ae6fd52f41Phil Burk}
1884501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk
1894501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk
1904501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burkstd::string AAudioClientTracker::NotificationClient::dump() const {
1914501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk    std::stringstream result;
1924501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk    const bool isLocked = AAudio_tryUntilTrue(
1934501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk            [this]()->bool { return mLock.try_lock(); } /* f */,
1944501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk            50 /* times */,
1954501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk            20 /* sleepMs */);
1964501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk    if (!isLocked) {
1974501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk        result << "AAudioClientTracker::NotificationClient may be deadlocked\n";
1984501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk    }
1994501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk
2004501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk    result << "  client: pid = " << mProcessId << " has " << mStreams.size() << " streams\n";
20148fc6191823ffa0708f60802fb6724c232760b9aChih-Hung Hsieh    for (const auto& serviceStream : mStreams) {
20255e5eabf96af5a2964bfab1e64d81ad9be9ac975Phil Burk        result << "     stream: 0x" << std::setfill('0') << std::setw(8) << std::hex
20355e5eabf96af5a2964bfab1e64d81ad9be9ac975Phil Burk               << serviceStream->getHandle()
20455e5eabf96af5a2964bfab1e64d81ad9be9ac975Phil Burk               << std::dec << std::setfill(' ') << "\n";
2054501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk    }
2064501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk
2074501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk    if (isLocked) {
2084501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk        mLock.unlock();
2094501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk    }
2104501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk    return result.str();
2114501b3510f9b2af2ff63a0471de24e3feea1d0a8Phil Burk}
212