1 /* 2 * Copyright (C) 2016 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 "AAudioStreamTracker" 18 //#define LOG_NDEBUG 0 19 #include <utils/Log.h> 20 21 #include <iomanip> 22 #include <iostream> 23 #include <sstream> 24 25 #include <aaudio/AAudio.h> 26 #include <utils/String16.h> 27 28 #include "AAudioStreamTracker.h" 29 30 using namespace android; 31 using namespace aaudio; 32 33 sp<AAudioServiceStreamBase> AAudioStreamTracker::removeStreamByHandle( 34 aaudio_handle_t streamHandle) { 35 std::lock_guard<std::mutex> lock(mHandleLock); 36 sp<AAudioServiceStreamBase> serviceStream; 37 auto it = mStreamsByHandle.find(streamHandle); 38 if (it != mStreamsByHandle.end()) { 39 serviceStream = it->second; 40 mStreamsByHandle.erase(it); 41 } 42 return serviceStream; 43 } 44 45 sp<AAudioServiceStreamBase> AAudioStreamTracker::getStreamByHandle( 46 aaudio_handle_t streamHandle) { 47 std::lock_guard<std::mutex> lock(mHandleLock); 48 sp<AAudioServiceStreamBase> serviceStream; 49 auto it = mStreamsByHandle.find(streamHandle); 50 if (it != mStreamsByHandle.end()) { 51 serviceStream = it->second; 52 } 53 return serviceStream; 54 } 55 56 // advance to next legal handle value 57 __attribute__((no_sanitize("integer"))) 58 aaudio_handle_t AAudioStreamTracker::bumpHandle(aaudio_handle_t handle) { 59 handle++; 60 // Only use positive integers. 61 if (handle <= 0) { 62 handle = 1; 63 } 64 return handle; 65 } 66 67 aaudio_handle_t AAudioStreamTracker::addStreamForHandle(sp<AAudioServiceStreamBase> serviceStream) { 68 std::lock_guard<std::mutex> lock(mHandleLock); 69 aaudio_handle_t handle = mPreviousHandle.load(); 70 // Assign a unique handle. 71 while (true) { 72 handle = bumpHandle(handle); 73 sp<AAudioServiceStreamBase> oldServiceStream = mStreamsByHandle[handle]; 74 // Is this an unused handle? It would be extremely unlikely to wrap 75 // around and collide with a very old handle. But just in case. 76 if (oldServiceStream.get() == nullptr) { 77 mStreamsByHandle[handle] = serviceStream; 78 break; 79 } 80 } 81 mPreviousHandle.store(handle); 82 return handle; 83 } 84 85 std::string AAudioStreamTracker::dump() const { 86 std::stringstream result; 87 const bool isLocked = AAudio_tryUntilTrue( 88 [this]()->bool { return mHandleLock.try_lock(); } /* f */, 89 50 /* times */, 90 20 /* sleepMs */); 91 if (!isLocked) { 92 result << "AAudioStreamTracker may be deadlocked\n"; 93 } else { 94 result << "Stream Handles:\n"; 95 for (const auto& it : mStreamsByHandle) { 96 aaudio_handle_t handle = it.second->getHandle(); 97 result << " 0x" << std::setfill('0') << std::setw(8) << std::hex << handle 98 << std::dec << std::setfill(' ') << "\n"; 99 } 100 101 mHandleLock.unlock(); 102 } 103 return result.str(); 104 } 105