Loading media/libaaudio/src/utility/AAudioUtilities.h +25 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ #ifndef UTILITY_AAUDIO_UTILITIES_H #define UTILITY_AAUDIO_UTILITIES_H #include <algorithm> #include <functional> #include <stdint.h> #include <sys/types.h> Loading Loading @@ -211,4 +213,27 @@ int32_t AAudioProperty_getMixerBursts(); */ int32_t AAudioProperty_getHardwareBurstMinMicros(); /** * Try a function f until it returns true. * * The function is always called at least once. * * @param f the function to evaluate, which returns a bool. * @param times the number of times to evaluate f. * @param sleepMs the sleep time per check of f, if greater than 0. * @return true if f() eventually returns true. */ static inline bool AAudio_tryUntilTrue( std::function<bool()> f, int times, int sleepMs) { static const useconds_t US_PER_MS = 1000; sleepMs = std::max(sleepMs, 0); for (;;) { if (f()) return true; if (times <= 1) return false; --times; usleep(sleepMs * US_PER_MS); } } #endif //UTILITY_AAUDIO_UTILITIES_H media/libaaudio/src/utility/HandleTracker.cpp +44 −0 Original line number Diff line number Diff line Loading @@ -20,11 +20,15 @@ #include <utils/Log.h> #include <assert.h> #include <functional> #include <iomanip> #include <new> #include <sstream> #include <stdint.h> #include <utils/Mutex.h> #include <aaudio/AAudio.h> #include "AAudioUtilities.h" #include "HandleTracker.h" using android::Mutex; Loading Loading @@ -93,6 +97,46 @@ bool HandleTracker::isInitialized() const { return mHandleAddresses != nullptr; } std::string HandleTracker::dump() const { if (!isInitialized()) { return "HandleTracker is not initialized\n"; } std::stringstream result; const bool isLocked = AAudio_tryUntilTrue( [this]()->bool { return mLock.tryLock(); } /* f */, 50 /* times */, 20 /* sleepMs */); if (!isLocked) { result << "HandleTracker may be deadlocked\n"; } result << "Handles:\n"; // atLineStart() can be changed to support an arbitrary line breaking algorithm; // it should return true when a new line starts. // For simplicity, we will use a constant 16 items per line. const auto atLineStart = [](int index) -> bool { // Magic constant of 0xf used for mask to detect start every 16 items. return (index & 0xf) == 0; }; const auto atLineEnd = [this, &atLineStart](int index) -> bool { return atLineStart(index + 1) || index == mMaxHandleCount - 1; }; for (int i = 0; i < mMaxHandleCount; ++i) { if (atLineStart(i)) { result << " "; } result << std::hex << std::setw(4) << std::setfill('0') << mHandleHeaders[i] << (atLineEnd(i) ? "\n" : " "); } if (isLocked) { mLock.unlock(); } return result.str(); } handle_tracker_slot_t HandleTracker::allocateSlot_l() { void **allocated = mNextFreeAddress; if (allocated == nullptr) { Loading media/libaaudio/src/utility/HandleTracker.h +14 −1 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #define UTILITY_HANDLE_TRACKER_H #include <stdint.h> #include <string> #include <utils/Mutex.h> typedef int32_t aaudio_handle_t; Loading Loading @@ -52,6 +53,18 @@ public: */ bool isInitialized() const; /** * Returns HandleTracker information. * * Will attempt to get the object lock, but will proceed * even if it cannot. * * Each line of information ends with a newline. * * @return a string representing the HandleTracker info. */ std::string dump() const; /** * Store a pointer and return a handle that can be used to retrieve the pointer. * Loading Loading @@ -99,7 +112,7 @@ private: // This Mutex protects the linked list of free nodes. // The list is managed using mHandleAddresses and mNextFreeAddress. // The data in mHandleHeaders is only changed by put() and remove(). android::Mutex mLock; mutable android::Mutex mLock; /** * Pull slot off of a list of empty slots. Loading services/oboeservice/AAudioEndpointManager.cpp +31 −0 Original line number Diff line number Diff line Loading @@ -19,8 +19,11 @@ #include <utils/Log.h> #include <assert.h> #include <functional> #include <map> #include <mutex> #include <sstream> #include <utility/AAudioUtilities.h> #include "AAudioEndpointManager.h" Loading @@ -35,6 +38,34 @@ AAudioEndpointManager::AAudioEndpointManager() , mOutputs() { } std::string AAudioEndpointManager::dump() const { std::stringstream result; const bool isLocked = AAudio_tryUntilTrue( [this]()->bool { return mLock.try_lock(); } /* f */, 50 /* times */, 20 /* sleepMs */); if (!isLocked) { result << "EndpointManager may be deadlocked\n"; } size_t inputs = mInputs.size(); result << "Inputs: " << inputs << "\n"; for (const auto &input : mInputs) { result << " Input(" << input.first << ", " << input.second << ")\n"; } size_t outputs = mOutputs.size(); result << "Outputs: " << outputs << "\n"; for (const auto &output : mOutputs) { result << " Output(" << output.first << ", " << output.second << ")\n"; } if (isLocked) { mLock.unlock(); } return result.str(); } AAudioServiceEndpoint *AAudioEndpointManager::openEndpoint(AAudioService &audioService, int32_t deviceId, aaudio_direction_t direction) { AAudioServiceEndpoint *endpoint = nullptr; Loading services/oboeservice/AAudioEndpointManager.h +13 −1 Original line number Diff line number Diff line Loading @@ -33,6 +33,18 @@ public: AAudioEndpointManager(); ~AAudioEndpointManager() = default; /** * Returns EndpointManager information. * * Will attempt to get the object lock, but will proceed * even if it cannot. * * Each line of information ends with a newline. * * @return a string representing the EndpointManager info */ std::string dump() const; /** * Find a service endpoint for the given deviceId and direction. * If an endpoint does not already exist then try to create one. Loading @@ -49,7 +61,7 @@ public: private: std::mutex mLock; mutable std::mutex mLock; std::map<int32_t, AAudioServiceEndpointCapture *> mInputs; std::map<int32_t, AAudioServiceEndpointPlay *> mOutputs; Loading Loading
media/libaaudio/src/utility/AAudioUtilities.h +25 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ #ifndef UTILITY_AAUDIO_UTILITIES_H #define UTILITY_AAUDIO_UTILITIES_H #include <algorithm> #include <functional> #include <stdint.h> #include <sys/types.h> Loading Loading @@ -211,4 +213,27 @@ int32_t AAudioProperty_getMixerBursts(); */ int32_t AAudioProperty_getHardwareBurstMinMicros(); /** * Try a function f until it returns true. * * The function is always called at least once. * * @param f the function to evaluate, which returns a bool. * @param times the number of times to evaluate f. * @param sleepMs the sleep time per check of f, if greater than 0. * @return true if f() eventually returns true. */ static inline bool AAudio_tryUntilTrue( std::function<bool()> f, int times, int sleepMs) { static const useconds_t US_PER_MS = 1000; sleepMs = std::max(sleepMs, 0); for (;;) { if (f()) return true; if (times <= 1) return false; --times; usleep(sleepMs * US_PER_MS); } } #endif //UTILITY_AAUDIO_UTILITIES_H
media/libaaudio/src/utility/HandleTracker.cpp +44 −0 Original line number Diff line number Diff line Loading @@ -20,11 +20,15 @@ #include <utils/Log.h> #include <assert.h> #include <functional> #include <iomanip> #include <new> #include <sstream> #include <stdint.h> #include <utils/Mutex.h> #include <aaudio/AAudio.h> #include "AAudioUtilities.h" #include "HandleTracker.h" using android::Mutex; Loading Loading @@ -93,6 +97,46 @@ bool HandleTracker::isInitialized() const { return mHandleAddresses != nullptr; } std::string HandleTracker::dump() const { if (!isInitialized()) { return "HandleTracker is not initialized\n"; } std::stringstream result; const bool isLocked = AAudio_tryUntilTrue( [this]()->bool { return mLock.tryLock(); } /* f */, 50 /* times */, 20 /* sleepMs */); if (!isLocked) { result << "HandleTracker may be deadlocked\n"; } result << "Handles:\n"; // atLineStart() can be changed to support an arbitrary line breaking algorithm; // it should return true when a new line starts. // For simplicity, we will use a constant 16 items per line. const auto atLineStart = [](int index) -> bool { // Magic constant of 0xf used for mask to detect start every 16 items. return (index & 0xf) == 0; }; const auto atLineEnd = [this, &atLineStart](int index) -> bool { return atLineStart(index + 1) || index == mMaxHandleCount - 1; }; for (int i = 0; i < mMaxHandleCount; ++i) { if (atLineStart(i)) { result << " "; } result << std::hex << std::setw(4) << std::setfill('0') << mHandleHeaders[i] << (atLineEnd(i) ? "\n" : " "); } if (isLocked) { mLock.unlock(); } return result.str(); } handle_tracker_slot_t HandleTracker::allocateSlot_l() { void **allocated = mNextFreeAddress; if (allocated == nullptr) { Loading
media/libaaudio/src/utility/HandleTracker.h +14 −1 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #define UTILITY_HANDLE_TRACKER_H #include <stdint.h> #include <string> #include <utils/Mutex.h> typedef int32_t aaudio_handle_t; Loading Loading @@ -52,6 +53,18 @@ public: */ bool isInitialized() const; /** * Returns HandleTracker information. * * Will attempt to get the object lock, but will proceed * even if it cannot. * * Each line of information ends with a newline. * * @return a string representing the HandleTracker info. */ std::string dump() const; /** * Store a pointer and return a handle that can be used to retrieve the pointer. * Loading Loading @@ -99,7 +112,7 @@ private: // This Mutex protects the linked list of free nodes. // The list is managed using mHandleAddresses and mNextFreeAddress. // The data in mHandleHeaders is only changed by put() and remove(). android::Mutex mLock; mutable android::Mutex mLock; /** * Pull slot off of a list of empty slots. Loading
services/oboeservice/AAudioEndpointManager.cpp +31 −0 Original line number Diff line number Diff line Loading @@ -19,8 +19,11 @@ #include <utils/Log.h> #include <assert.h> #include <functional> #include <map> #include <mutex> #include <sstream> #include <utility/AAudioUtilities.h> #include "AAudioEndpointManager.h" Loading @@ -35,6 +38,34 @@ AAudioEndpointManager::AAudioEndpointManager() , mOutputs() { } std::string AAudioEndpointManager::dump() const { std::stringstream result; const bool isLocked = AAudio_tryUntilTrue( [this]()->bool { return mLock.try_lock(); } /* f */, 50 /* times */, 20 /* sleepMs */); if (!isLocked) { result << "EndpointManager may be deadlocked\n"; } size_t inputs = mInputs.size(); result << "Inputs: " << inputs << "\n"; for (const auto &input : mInputs) { result << " Input(" << input.first << ", " << input.second << ")\n"; } size_t outputs = mOutputs.size(); result << "Outputs: " << outputs << "\n"; for (const auto &output : mOutputs) { result << " Output(" << output.first << ", " << output.second << ")\n"; } if (isLocked) { mLock.unlock(); } return result.str(); } AAudioServiceEndpoint *AAudioEndpointManager::openEndpoint(AAudioService &audioService, int32_t deviceId, aaudio_direction_t direction) { AAudioServiceEndpoint *endpoint = nullptr; Loading
services/oboeservice/AAudioEndpointManager.h +13 −1 Original line number Diff line number Diff line Loading @@ -33,6 +33,18 @@ public: AAudioEndpointManager(); ~AAudioEndpointManager() = default; /** * Returns EndpointManager information. * * Will attempt to get the object lock, but will proceed * even if it cannot. * * Each line of information ends with a newline. * * @return a string representing the EndpointManager info */ std::string dump() const; /** * Find a service endpoint for the given deviceId and direction. * If an endpoint does not already exist then try to create one. Loading @@ -49,7 +61,7 @@ public: private: std::mutex mLock; mutable std::mutex mLock; std::map<int32_t, AAudioServiceEndpointCapture *> mInputs; std::map<int32_t, AAudioServiceEndpointPlay *> mOutputs; Loading