1*ec779b8eSAndroid Build Coastguard Worker /* 2*ec779b8eSAndroid Build Coastguard Worker * Copyright (C) 2016 The Android Open Source Project 3*ec779b8eSAndroid Build Coastguard Worker * 4*ec779b8eSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*ec779b8eSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*ec779b8eSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*ec779b8eSAndroid Build Coastguard Worker * 8*ec779b8eSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*ec779b8eSAndroid Build Coastguard Worker * 10*ec779b8eSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*ec779b8eSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*ec779b8eSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*ec779b8eSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*ec779b8eSAndroid Build Coastguard Worker * limitations under the License. 15*ec779b8eSAndroid Build Coastguard Worker */ 16*ec779b8eSAndroid Build Coastguard Worker 17*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "AAudioStreamTracker" 18*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0 19*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h> 20*ec779b8eSAndroid Build Coastguard Worker 21*ec779b8eSAndroid Build Coastguard Worker #include <iomanip> 22*ec779b8eSAndroid Build Coastguard Worker #include <iostream> 23*ec779b8eSAndroid Build Coastguard Worker #include <sstream> 24*ec779b8eSAndroid Build Coastguard Worker 25*ec779b8eSAndroid Build Coastguard Worker #include <aaudio/AAudio.h> 26*ec779b8eSAndroid Build Coastguard Worker #include <utils/String16.h> 27*ec779b8eSAndroid Build Coastguard Worker 28*ec779b8eSAndroid Build Coastguard Worker #include "AAudioStreamTracker.h" 29*ec779b8eSAndroid Build Coastguard Worker 30*ec779b8eSAndroid Build Coastguard Worker using namespace android; 31*ec779b8eSAndroid Build Coastguard Worker using namespace aaudio; 32*ec779b8eSAndroid Build Coastguard Worker removeStreamByHandle(aaudio_handle_t streamHandle)33*ec779b8eSAndroid Build Coastguard Workerint32_t AAudioStreamTracker::removeStreamByHandle( 34*ec779b8eSAndroid Build Coastguard Worker aaudio_handle_t streamHandle) { 35*ec779b8eSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mHandleLock); 36*ec779b8eSAndroid Build Coastguard Worker auto count = mStreamsByHandle.erase(streamHandle); 37*ec779b8eSAndroid Build Coastguard Worker return static_cast<int32_t>(count); 38*ec779b8eSAndroid Build Coastguard Worker } 39*ec779b8eSAndroid Build Coastguard Worker getStreamByHandle(aaudio_handle_t streamHandle)40*ec779b8eSAndroid Build Coastguard Workersp<AAudioServiceStreamBase> AAudioStreamTracker::getStreamByHandle( 41*ec779b8eSAndroid Build Coastguard Worker aaudio_handle_t streamHandle) { 42*ec779b8eSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mHandleLock); 43*ec779b8eSAndroid Build Coastguard Worker sp<AAudioServiceStreamBase> serviceStream; 44*ec779b8eSAndroid Build Coastguard Worker auto it = mStreamsByHandle.find(streamHandle); 45*ec779b8eSAndroid Build Coastguard Worker if (it != mStreamsByHandle.end()) { 46*ec779b8eSAndroid Build Coastguard Worker serviceStream = it->second; 47*ec779b8eSAndroid Build Coastguard Worker } 48*ec779b8eSAndroid Build Coastguard Worker return serviceStream; 49*ec779b8eSAndroid Build Coastguard Worker } 50*ec779b8eSAndroid Build Coastguard Worker 51*ec779b8eSAndroid Build Coastguard Worker // The port handle is only available when the stream is started. 52*ec779b8eSAndroid Build Coastguard Worker // So we have to iterate over all the streams. 53*ec779b8eSAndroid Build Coastguard Worker // Luckily this rarely happens. findStreamByPortHandle(audio_port_handle_t portHandle)54*ec779b8eSAndroid Build Coastguard Workersp<AAudioServiceStreamBase> AAudioStreamTracker::findStreamByPortHandle( 55*ec779b8eSAndroid Build Coastguard Worker audio_port_handle_t portHandle) { 56*ec779b8eSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mHandleLock); 57*ec779b8eSAndroid Build Coastguard Worker sp<AAudioServiceStreamBase> serviceStream; 58*ec779b8eSAndroid Build Coastguard Worker auto it = mStreamsByHandle.begin(); 59*ec779b8eSAndroid Build Coastguard Worker while (it != mStreamsByHandle.end()) { 60*ec779b8eSAndroid Build Coastguard Worker auto candidate = it->second; 61*ec779b8eSAndroid Build Coastguard Worker if (candidate->getPortHandle() == portHandle) { 62*ec779b8eSAndroid Build Coastguard Worker serviceStream = candidate; 63*ec779b8eSAndroid Build Coastguard Worker break; 64*ec779b8eSAndroid Build Coastguard Worker } 65*ec779b8eSAndroid Build Coastguard Worker it++; 66*ec779b8eSAndroid Build Coastguard Worker } 67*ec779b8eSAndroid Build Coastguard Worker return serviceStream; 68*ec779b8eSAndroid Build Coastguard Worker } 69*ec779b8eSAndroid Build Coastguard Worker 70*ec779b8eSAndroid Build Coastguard Worker // advance to next legal handle value 71*ec779b8eSAndroid Build Coastguard Worker __attribute__((no_sanitize("integer"))) bumpHandle(aaudio_handle_t handle)72*ec779b8eSAndroid Build Coastguard Workeraaudio_handle_t AAudioStreamTracker::bumpHandle(aaudio_handle_t handle) { 73*ec779b8eSAndroid Build Coastguard Worker handle++; 74*ec779b8eSAndroid Build Coastguard Worker // Only use positive integers. 75*ec779b8eSAndroid Build Coastguard Worker if (handle <= 0) { 76*ec779b8eSAndroid Build Coastguard Worker handle = 1; 77*ec779b8eSAndroid Build Coastguard Worker } 78*ec779b8eSAndroid Build Coastguard Worker return handle; 79*ec779b8eSAndroid Build Coastguard Worker } 80*ec779b8eSAndroid Build Coastguard Worker addStreamForHandle(const sp<AAudioServiceStreamBase> & serviceStream)81*ec779b8eSAndroid Build Coastguard Workeraaudio_handle_t AAudioStreamTracker::addStreamForHandle( 82*ec779b8eSAndroid Build Coastguard Worker const sp<AAudioServiceStreamBase>& serviceStream) { 83*ec779b8eSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mHandleLock); 84*ec779b8eSAndroid Build Coastguard Worker aaudio_handle_t handle = mPreviousHandle; 85*ec779b8eSAndroid Build Coastguard Worker // Assign a unique handle. 86*ec779b8eSAndroid Build Coastguard Worker while (true) { 87*ec779b8eSAndroid Build Coastguard Worker handle = bumpHandle(handle); 88*ec779b8eSAndroid Build Coastguard Worker sp<AAudioServiceStreamBase> oldServiceStream = mStreamsByHandle[handle]; 89*ec779b8eSAndroid Build Coastguard Worker // Is this an unused handle? It would be extremely unlikely to wrap 90*ec779b8eSAndroid Build Coastguard Worker // around and collide with a very old handle. But just in case. 91*ec779b8eSAndroid Build Coastguard Worker if (oldServiceStream.get() == nullptr) { 92*ec779b8eSAndroid Build Coastguard Worker mStreamsByHandle[handle] = serviceStream; 93*ec779b8eSAndroid Build Coastguard Worker break; 94*ec779b8eSAndroid Build Coastguard Worker } 95*ec779b8eSAndroid Build Coastguard Worker } 96*ec779b8eSAndroid Build Coastguard Worker mPreviousHandle = handle; 97*ec779b8eSAndroid Build Coastguard Worker return handle; 98*ec779b8eSAndroid Build Coastguard Worker } 99*ec779b8eSAndroid Build Coastguard Worker dump() const100*ec779b8eSAndroid Build Coastguard Workerstd::string AAudioStreamTracker::dump() const NO_THREAD_SAFETY_ANALYSIS { 101*ec779b8eSAndroid Build Coastguard Worker std::stringstream result; 102*ec779b8eSAndroid Build Coastguard Worker const bool isLocked = AAudio_tryUntilTrue( 103*ec779b8eSAndroid Build Coastguard Worker [this]()->bool { return mHandleLock.try_lock(); } /* f */, 104*ec779b8eSAndroid Build Coastguard Worker 50 /* times */, 105*ec779b8eSAndroid Build Coastguard Worker 20 /* sleepMs */); 106*ec779b8eSAndroid Build Coastguard Worker if (!isLocked) { 107*ec779b8eSAndroid Build Coastguard Worker result << "AAudioStreamTracker may be deadlocked\n"; 108*ec779b8eSAndroid Build Coastguard Worker } else { 109*ec779b8eSAndroid Build Coastguard Worker result << "Stream Handles:\n"; 110*ec779b8eSAndroid Build Coastguard Worker for (const auto& it : mStreamsByHandle) { 111*ec779b8eSAndroid Build Coastguard Worker aaudio_handle_t handle = it.second->getHandle(); 112*ec779b8eSAndroid Build Coastguard Worker result << " 0x" << std::setfill('0') << std::setw(8) << std::hex << handle 113*ec779b8eSAndroid Build Coastguard Worker << std::dec << std::setfill(' ') << "\n"; 114*ec779b8eSAndroid Build Coastguard Worker } 115*ec779b8eSAndroid Build Coastguard Worker 116*ec779b8eSAndroid Build Coastguard Worker mHandleLock.unlock(); 117*ec779b8eSAndroid Build Coastguard Worker } 118*ec779b8eSAndroid Build Coastguard Worker return result.str(); 119*ec779b8eSAndroid Build Coastguard Worker } 120