aaudio: keep track of streams using strong pointers

Maintain strong pointer to service stream during service calls.
Use simple AAudioStreamTracker instead of complex HandleTracker.

Bug: 65280854
Test: affects all MMAP streams, run all CTS tests, etcetera
Change-Id: I3d2ed8b588ea39c216dacd4dea503b11c33f36f3
diff --git a/media/libaaudio/src/Android.mk b/media/libaaudio/src/Android.mk
index cfcf27a..6861248 100644
--- a/media/libaaudio/src/Android.mk
+++ b/media/libaaudio/src/Android.mk
@@ -36,7 +36,6 @@
     legacy/AudioStreamLegacy.cpp \
     legacy/AudioStreamRecord.cpp \
     legacy/AudioStreamTrack.cpp \
-    utility/HandleTracker.cpp \
     utility/AAudioUtilities.cpp \
     utility/FixedBlockAdapter.cpp \
     utility/FixedBlockReader.cpp \
@@ -95,7 +94,6 @@
     legacy/AudioStreamLegacy.cpp \
     legacy/AudioStreamRecord.cpp \
     legacy/AudioStreamTrack.cpp \
-    utility/HandleTracker.cpp \
     utility/AAudioUtilities.cpp \
     utility/FixedBlockAdapter.cpp \
     utility/FixedBlockReader.cpp \
diff --git a/media/libaaudio/src/binding/AAudioCommon.h b/media/libaaudio/src/binding/AAudioCommon.h
new file mode 100644
index 0000000..e3e9e82
--- /dev/null
+++ b/media/libaaudio/src/binding/AAudioCommon.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_AAUDIO_COMMON_H
+#define ANDROID_AAUDIO_COMMON_H
+
+#include <stdint.h>
+
+/*
+ * Internal header that is common to both client and server.
+ *
+ */
+namespace aaudio {
+
+typedef int32_t aaudio_handle_t;
+
+} /* namespace aaudio */
+
+#endif // ANDROID_AAUDIO_COMMON_H
diff --git a/media/libaaudio/src/binding/IAAudioClient.h b/media/libaaudio/src/binding/IAAudioClient.h
index 21cc33b..f21fd93 100644
--- a/media/libaaudio/src/binding/IAAudioClient.h
+++ b/media/libaaudio/src/binding/IAAudioClient.h
@@ -22,7 +22,7 @@
 
 #include <aaudio/AAudio.h>
 
-#include "utility/HandleTracker.h"
+#include "binding/AAudioCommon.h"
 
 namespace android {
 
@@ -33,7 +33,7 @@
 
     DECLARE_META_INTERFACE(AAudioClient);
 
-    virtual void onStreamChange(aaudio_handle_t handle, int32_t opcode, int32_t value) = 0;
+    virtual void onStreamChange(aaudio::aaudio_handle_t handle, int32_t opcode, int32_t value) = 0;
 
 };
 
diff --git a/media/libaaudio/src/binding/IAAudioService.h b/media/libaaudio/src/binding/IAAudioService.h
index 30b3ead..6bdb826 100644
--- a/media/libaaudio/src/binding/IAAudioService.h
+++ b/media/libaaudio/src/binding/IAAudioService.h
@@ -24,12 +24,12 @@
 
 #include <aaudio/AAudio.h>
 
+#include "binding/AAudioCommon.h"
 #include "binding/AAudioServiceDefinitions.h"
-#include "binding/AudioEndpointParcelable.h"
-#include "binding/AAudioStreamRequest.h"
 #include "binding/AAudioStreamConfiguration.h"
+#include "binding/AAudioStreamRequest.h"
+#include "binding/AudioEndpointParcelable.h"
 #include "binding/IAAudioClient.h"
-#include "utility/HandleTracker.h"
 
 namespace android {
 
@@ -51,7 +51,7 @@
      * @param configuration contains information about the created stream
      * @return handle to the stream or a negative error
      */
-    virtual aaudio_handle_t openStream(const aaudio::AAudioStreamRequest &request,
+    virtual aaudio::aaudio_handle_t openStream(const aaudio::AAudioStreamRequest &request,
                                      aaudio::AAudioStreamConfiguration &configurationOutput) = 0;
 
     virtual aaudio_result_t closeStream(aaudio::aaudio_handle_t streamHandle) = 0;
@@ -89,11 +89,11 @@
     /**
      * Manage the specified thread as a low latency audio thread.
      */
-    virtual aaudio_result_t registerAudioThread(aaudio_handle_t streamHandle,
+    virtual aaudio_result_t registerAudioThread(aaudio::aaudio_handle_t streamHandle,
                                               pid_t clientThreadId,
                                               int64_t periodNanoseconds) = 0;
 
-    virtual aaudio_result_t unregisterAudioThread(aaudio_handle_t streamHandle,
+    virtual aaudio_result_t unregisterAudioThread(aaudio::aaudio_handle_t streamHandle,
                                                 pid_t clientThreadId) = 0;
 };
 
diff --git a/media/libaaudio/src/core/AAudioAudio.cpp b/media/libaaudio/src/core/AAudioAudio.cpp
index 58966e0..1eaee81 100644
--- a/media/libaaudio/src/core/AAudioAudio.cpp
+++ b/media/libaaudio/src/core/AAudioAudio.cpp
@@ -24,15 +24,14 @@
 #include <aaudio/AAudio.h>
 #include <aaudio/AAudioTesting.h>
 
+#include "AudioClock.h"
 #include "AudioStreamBuilder.h"
 #include "AudioStream.h"
-#include "AudioClock.h"
+#include "binding/AAudioCommon.h"
 #include "client/AudioStreamInternal.h"
-#include "HandleTracker.h"
 
 using namespace aaudio;
 
-
 // Macros for common code that includes a return.
 // TODO Consider using do{}while(0) construct. I tried but it hung AndroidStudio
 #define CONVERT_BUILDER_HANDLE_OR_RETURN() \
diff --git a/media/libaaudio/src/utility/HandleTracker.cpp b/media/libaaudio/src/utility/HandleTracker.cpp
deleted file mode 100644
index 35ce95a..0000000
--- a/media/libaaudio/src/utility/HandleTracker.cpp
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#define LOG_TAG "AAudio"
-//#define LOG_NDEBUG 0
-#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;
-
-// Handle format is: tgggiiii
-// where each letter is 4 bits, t=type, g=generation, i=index
-
-#define TYPE_SIZE           4
-#define GENERATION_SIZE    12
-#define INDEX_SIZE         16
-
-#define GENERATION_INVALID  0
-#define GENERATION_SHIFT    INDEX_SIZE
-
-#define TYPE_MASK           ((1 << TYPE_SIZE) - 1)
-#define GENERATION_MASK     ((1 << GENERATION_SIZE) - 1)
-#define INDEX_MASK          ((1 << INDEX_SIZE) - 1)
-
-#define SLOT_UNAVAILABLE    (-1)
-
-// Error if handle is negative so type is limited to bottom half.
-#define HANDLE_INVALID_TYPE TYPE_MASK
-
-static_assert(HANDLE_TRACKER_MAX_TYPES == (1 << (TYPE_SIZE - 1)),
-    "Mismatch between header and cpp.");
-static_assert(HANDLE_TRACKER_MAX_HANDLES == (1 << (INDEX_SIZE)),
-    "Mismatch between header and cpp.");
-
-HandleTracker::HandleTracker(uint32_t maxHandles)
-        : mMaxHandleCount(maxHandles)
-        , mHandleHeaders(nullptr)
-{
-    assert(maxHandles <= HANDLE_TRACKER_MAX_HANDLES);
-    // Allocate arrays to hold addresses and validation info.
-    mHandleAddresses = (handle_tracker_address_t *)
-            new(std::nothrow) handle_tracker_address_t[maxHandles];
-    if (mHandleAddresses != nullptr) {
-        mHandleHeaders = new(std::nothrow) handle_tracker_header_t[maxHandles];
-
-        if (mHandleHeaders != nullptr) {
-            handle_tracker_header_t initialHeader = buildHeader(0, 1);
-            // Initialize linked list of free nodes. nullptr terminated.
-            for (uint32_t i = 0; i < (maxHandles - 1); i++) {
-                mHandleAddresses[i] = &mHandleAddresses[i + 1]; // point to next node
-                mHandleHeaders[i] = initialHeader;
-            }
-            mNextFreeAddress = &mHandleAddresses[0];
-            mHandleAddresses[maxHandles - 1] = nullptr;
-            mHandleHeaders[maxHandles - 1] = 0;
-        } else {
-            delete[] mHandleAddresses; // so the class appears uninitialized
-            mHandleAddresses = nullptr;
-        }
-    }
-}
-
-HandleTracker::~HandleTracker()
-{
-    Mutex::Autolock _l(mLock);
-    delete[] mHandleAddresses;
-    delete[] mHandleHeaders;
-    mHandleAddresses = nullptr;
-}
-
-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 << "HandleTracker:\n";
-    result << "  HandleHeaders:\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) {
-        return SLOT_UNAVAILABLE;
-    }
-    // Remove this slot from the head of the linked list.
-    mNextFreeAddress = (void **) *allocated;
-    return (allocated - mHandleAddresses);
-}
-
-handle_tracker_generation_t HandleTracker::nextGeneration_l(handle_tracker_slot_t index) {
-    handle_tracker_generation_t generation = (mHandleHeaders[index] + 1) & GENERATION_MASK;
-    // Avoid generation zero so that 0x0 is not a valid handle.
-    if (generation == GENERATION_INVALID) {
-        generation++;
-    }
-    return generation;
-}
-
-aaudio_handle_t HandleTracker::put(handle_tracker_type_t type, void *address)
-{
-    if (type < 0 || type >= HANDLE_TRACKER_MAX_TYPES) {
-        return static_cast<aaudio_handle_t>(AAUDIO_ERROR_OUT_OF_RANGE);
-    }
-    if (!isInitialized()) {
-        return static_cast<aaudio_handle_t>(AAUDIO_ERROR_NO_MEMORY);
-    }
-
-    Mutex::Autolock _l(mLock);
-
-    // Find an empty slot.
-    handle_tracker_slot_t index = allocateSlot_l();
-    if (index == SLOT_UNAVAILABLE) {
-        ALOGE("HandleTracker::put() no room for more handles");
-        return static_cast<aaudio_handle_t>(AAUDIO_ERROR_NO_FREE_HANDLES);
-    }
-
-    // Cycle the generation counter so stale handles can be detected.
-    handle_tracker_generation_t generation = nextGeneration_l(index); // reads header table
-    handle_tracker_header_t inputHeader = buildHeader(type, generation);
-
-    // These two writes may need to be observed by other threads or cores during get().
-    mHandleHeaders[index] = inputHeader;
-    mHandleAddresses[index] = address;
-    // TODO use store release to enforce memory order with get()
-
-    // Generate a handle.
-    aaudio_handle_t handle = buildHandle(inputHeader, index);
-
-    ALOGV("HandleTracker::put(%p) returns 0x%08x", address, handle);
-    return handle;
-}
-
-handle_tracker_slot_t HandleTracker::handleToIndex(handle_tracker_type_t type,
-                                                   aaudio_handle_t handle) const
-{
-    // Validate the handle.
-    handle_tracker_slot_t index = extractIndex(handle);
-    if (index >= mMaxHandleCount) {
-        ALOGE("HandleTracker::handleToIndex() invalid handle = 0x%08X", handle);
-        return static_cast<aaudio_handle_t>(AAUDIO_ERROR_INVALID_HANDLE);
-    }
-    handle_tracker_generation_t handleGeneration = extractGeneration(handle);
-    handle_tracker_header_t inputHeader = buildHeader(type, handleGeneration);
-    // We do not need to synchronize this access to mHandleHeaders because it is constant for
-    // the lifetime of the handle.
-    if (inputHeader != mHandleHeaders[index]) {
-        ALOGE("HandleTracker::handleToIndex() inputHeader = 0x%08x != mHandleHeaders[%d] = 0x%08x",
-             inputHeader, index, mHandleHeaders[index]);
-        return static_cast<aaudio_handle_t>(AAUDIO_ERROR_INVALID_HANDLE);
-    }
-    return index;
-}
-
-handle_tracker_address_t HandleTracker::get(handle_tracker_type_t type, aaudio_handle_t handle) const
-{
-    if (!isInitialized()) {
-        return nullptr;
-    }
-    handle_tracker_slot_t index = handleToIndex(type, handle);
-    if (index >= 0) {
-        // We do not need to synchronize this access to mHandleHeaders because this slot
-        // is allocated and, therefore, not part of the linked list of free slots.
-        return mHandleAddresses[index];
-    } else {
-        return nullptr;
-    }
-}
-
-handle_tracker_address_t HandleTracker::remove(handle_tracker_type_t type, aaudio_handle_t handle) {
-    if (!isInitialized()) {
-        return nullptr;
-    }
-
-    Mutex::Autolock _l(mLock);
-
-    handle_tracker_slot_t index = handleToIndex(type,handle);
-    if (index >= 0) {
-        handle_tracker_address_t address = mHandleAddresses[index];
-
-        // Invalidate the header type but preserve the generation count.
-        handle_tracker_generation_t generation = mHandleHeaders[index] & GENERATION_MASK;
-        handle_tracker_header_t inputHeader = buildHeader(
-                (handle_tracker_type_t) HANDLE_INVALID_TYPE, generation);
-        mHandleHeaders[index] = inputHeader;
-
-        // Add this slot to the head of the linked list.
-        mHandleAddresses[index] = mNextFreeAddress;
-        mNextFreeAddress = (handle_tracker_address_t *) &mHandleAddresses[index];
-        return address;
-    } else {
-        return nullptr;
-    }
-}
-
-aaudio_handle_t HandleTracker::buildHandle(handle_tracker_header_t typeGeneration,
-                                         handle_tracker_slot_t index) {
-    return (aaudio_handle_t)((typeGeneration << GENERATION_SHIFT) | (index & INDEX_MASK));
-}
-
-handle_tracker_header_t HandleTracker::buildHeader(handle_tracker_type_t type,
-                                    handle_tracker_generation_t generation)
-{
-    return (handle_tracker_header_t) (((type & TYPE_MASK) << GENERATION_SIZE)
-        | (generation & GENERATION_MASK));
-}
-
-handle_tracker_slot_t HandleTracker::extractIndex(aaudio_handle_t handle)
-{
-    return handle & INDEX_MASK;
-}
-
-handle_tracker_generation_t HandleTracker::extractGeneration(aaudio_handle_t handle)
-{
-    return (handle >> GENERATION_SHIFT) & GENERATION_MASK;
-}
diff --git a/media/libaaudio/src/utility/HandleTracker.h b/media/libaaudio/src/utility/HandleTracker.h
deleted file mode 100644
index a4c51c0..0000000
--- a/media/libaaudio/src/utility/HandleTracker.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef UTILITY_HANDLE_TRACKER_H
-#define UTILITY_HANDLE_TRACKER_H
-
-#include <stdint.h>
-#include <string>
-#include <utils/Mutex.h>
-
-typedef int32_t  aaudio_handle_t;
-typedef int32_t  handle_tracker_type_t;       // what kind of handle
-typedef int32_t  handle_tracker_slot_t;       // index in allocation table
-typedef int32_t  handle_tracker_generation_t; // incremented when slot used
-typedef uint16_t handle_tracker_header_t;     // combines type and generation
-typedef void    *handle_tracker_address_t;    // address of something that is stored here
-
-#define HANDLE_TRACKER_MAX_TYPES    (1 << 3)
-#define HANDLE_TRACKER_MAX_HANDLES  (1 << 16)
-
-/**
- * Represent Objects using an integer handle that can be used with Java.
- * This also makes the 'C' ABI more robust.
- *
- * Note that this should only be called from a single thread.
- * If you call it from more than one thread then you need to use your own mutex.
- */
-class HandleTracker {
-
-public:
-    /**
-     * @param maxHandles cannot exceed HANDLE_TRACKER_MAX_HANDLES
-     */
-    HandleTracker(uint32_t maxHandles = 256);
-    virtual ~HandleTracker();
-
-    /**
-     * Don't use if this returns false;
-     * @return true if the internal allocation succeeded
-     */
-    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.
-     *
-     * It is safe to call put() or remove() from multiple threads.
-     *
-     * @param expectedType the type of the object to be tracked
-     * @param address pointer to be converted to a handle
-     * @return a valid handle or a negative error
-     */
-    aaudio_handle_t put(handle_tracker_type_t expectedType, handle_tracker_address_t address);
-
-    /**
-     * Get the original pointer associated with the handle.
-     * The handle will be validated to prevent stale handles from being reused.
-     * Note that the validation is designed to prevent common coding errors and not
-     * to prevent deliberate hacking.
-     *
-     * @param expectedType shouldmatch the type we passed to put()
-     * @param handle to be converted to a pointer
-     * @return address associated with handle or nullptr
-     */
-    handle_tracker_address_t get(handle_tracker_type_t expectedType, aaudio_handle_t handle) const;
-
-    /**
-     * Free up the storage associated with the handle.
-     * Subsequent attempts to use the handle will fail.
-     *
-     * Do NOT remove() a handle while get() is being called for the same handle from another thread.
-     *
-     * @param expectedType shouldmatch the type we passed to put()
-     * @param handle to be removed from tracking
-     * @return address associated with handle or nullptr if not found
-     */
-    handle_tracker_address_t remove(handle_tracker_type_t expectedType, aaudio_handle_t handle);
-
-private:
-    const int32_t               mMaxHandleCount;   // size of array
-    // This address is const after initialization.
-    handle_tracker_address_t  * mHandleAddresses;  // address of objects or a free linked list node
-    // This address is const after initialization.
-    handle_tracker_header_t   * mHandleHeaders;    // combination of type and generation
-    // head of the linked list of free nodes in mHandleAddresses
-    handle_tracker_address_t  * mNextFreeAddress;
-
-    // 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().
-    mutable android::Mutex      mLock;
-
-    /**
-     * Pull slot off of a list of empty slots.
-     * @return index or a negative error
-     */
-    handle_tracker_slot_t allocateSlot_l();
-
-    /**
-     * Increment the generation for the slot, avoiding zero.
-     */
-    handle_tracker_generation_t nextGeneration_l(handle_tracker_slot_t index);
-
-    /**
-     * Validate the handle and return the corresponding index.
-     * @return slot index or a negative error
-     */
-    handle_tracker_slot_t handleToIndex(aaudio_handle_t handle, handle_tracker_type_t type) const;
-
-    /**
-     * Construct a handle from a header and an index.
-     * @param header combination of a type and a generation
-     * @param index slot index returned from allocateSlot
-     * @return handle or a negative error
-     */
-    static aaudio_handle_t buildHandle(handle_tracker_header_t header, handle_tracker_slot_t index);
-
-    /**
-     * Combine a type and a generation field into a header.
-     */
-    static handle_tracker_header_t buildHeader(handle_tracker_type_t type,
-                handle_tracker_generation_t generation);
-
-    /**
-     * Extract the index from a handle.
-     * Does not validate the handle.
-     * @return index associated with a handle
-     */
-    static handle_tracker_slot_t extractIndex(aaudio_handle_t handle);
-
-    /**
-     * Extract the generation from a handle.
-     * Does not validate the handle.
-     * @return generation associated with a handle
-     */
-    static handle_tracker_generation_t extractGeneration(aaudio_handle_t handle);
-
-};
-
-#endif //UTILITY_HANDLE_TRACKER_H