Home | History | Annotate | Download | only in oboeservice
      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