aaudio: modify endpoint sharing logic

A new Client stream in shared mode can share an existing endpoint
if it has no preferences or compatible device, sample rate and channel
count requests.

Bug: 62961537
Test: play and capture with AAudio in mmap mode
Change-Id: I38536fb486dfc06f4399f7d02248384583fd3a17
diff --git a/services/oboeservice/AAudioEndpointManager.cpp b/services/oboeservice/AAudioEndpointManager.cpp
index 94577a6..d8b9101 100644
--- a/services/oboeservice/AAudioEndpointManager.cpp
+++ b/services/oboeservice/AAudioEndpointManager.cpp
@@ -51,13 +51,13 @@
     size_t inputs = mInputs.size();
     result << "Inputs: " << inputs << "\n";
     for (const auto &input : mInputs) {
-        result << "  Input(" << input.first << ", " << input.second << ")\n";
+        result << "  Input(" << input << ")\n";
     }
 
     size_t outputs = mOutputs.size();
     result << "Outputs: " << outputs << "\n";
     for (const auto &output : mOutputs) {
-        result << "  Output(" << output.first << ", " << output.second << ")\n";
+        result << "  Output(" << output << ")\n";
     }
 
     if (isLocked) {
@@ -66,27 +66,40 @@
     return result.str();
 }
 
-AAudioServiceEndpoint *AAudioEndpointManager::openEndpoint(AAudioService &audioService, int32_t deviceId,
-                                                           aaudio_direction_t direction) {
+AAudioServiceEndpoint *AAudioEndpointManager::openEndpoint(AAudioService &audioService,
+        const AAudioStreamConfiguration& configuration, aaudio_direction_t direction) {
     AAudioServiceEndpoint *endpoint = nullptr;
     AAudioServiceEndpointCapture *capture = nullptr;
     AAudioServiceEndpointPlay *player = nullptr;
     std::lock_guard<std::mutex> lock(mLock);
 
     // Try to find an existing endpoint.
+
+
+
     switch (direction) {
         case AAUDIO_DIRECTION_INPUT:
-            endpoint = mInputs[deviceId];
+            for (AAudioServiceEndpoint *ep : mInputs) {
+                if (ep->matches(configuration)) {
+                    endpoint = ep;
+                    break;
+                }
+            }
             break;
         case AAUDIO_DIRECTION_OUTPUT:
-            endpoint = mOutputs[deviceId];
+            for (AAudioServiceEndpoint *ep : mOutputs) {
+                if (ep->matches(configuration)) {
+                    endpoint = ep;
+                    break;
+                }
+            }
             break;
         default:
             assert(false); // There are only two possible directions.
             break;
     }
     ALOGD("AAudioEndpointManager::openEndpoint(), found %p for device = %d, dir = %d",
-          endpoint, deviceId, (int)direction);
+          endpoint, configuration.getDeviceId(), (int)direction);
 
     // If we can't find an existing one then open a new one.
     if (endpoint == nullptr) {
@@ -105,7 +118,7 @@
     }
 
     if (endpoint != nullptr) {
-        aaudio_result_t result = endpoint->open(deviceId);
+        aaudio_result_t result = endpoint->open(configuration);
         if (result != AAUDIO_OK) {
             ALOGE("AAudioEndpointManager::findEndpoint(), open failed");
             delete endpoint;
@@ -113,17 +126,17 @@
         } else {
             switch(direction) {
                 case AAUDIO_DIRECTION_INPUT:
-                    mInputs[deviceId] = capture;
+                    mInputs.push_back(capture);
                     break;
                 case AAUDIO_DIRECTION_OUTPUT:
-                    mOutputs[deviceId] = player;
+                    mOutputs.push_back(player);
                     break;
                 default:
                     break;
             }
         }
         ALOGD("AAudioEndpointManager::openEndpoint(), created %p for device = %d, dir = %d",
-              endpoint, deviceId, (int)direction);
+              endpoint, configuration.getDeviceId(), (int)direction);
     }
 
     if (endpoint != nullptr) {
@@ -156,10 +169,12 @@
 
         switch (direction) {
             case AAUDIO_DIRECTION_INPUT:
-                mInputs.erase(deviceId);
+                mInputs.erase(
+                  std::remove(mInputs.begin(), mInputs.end(), serviceEndpoint), mInputs.end());
                 break;
             case AAUDIO_DIRECTION_OUTPUT:
-                mOutputs.erase(deviceId);
+                mOutputs.erase(
+                  std::remove(mOutputs.begin(), mOutputs.end(), serviceEndpoint), mOutputs.end());
                 break;
             default:
                 break;
diff --git a/services/oboeservice/AAudioEndpointManager.h b/services/oboeservice/AAudioEndpointManager.h
index 6dc5adf..6d3b52b 100644
--- a/services/oboeservice/AAudioEndpointManager.h
+++ b/services/oboeservice/AAudioEndpointManager.h
@@ -54,7 +54,7 @@
      * @return endpoint or nullptr
      */
     AAudioServiceEndpoint *openEndpoint(android::AAudioService &audioService,
-                                        int32_t deviceId,
+                                        const AAudioStreamConfiguration& configuration,
                                         aaudio_direction_t direction);
 
     void closeEndpoint(AAudioServiceEndpoint *serviceEndpoint);
@@ -63,8 +63,8 @@
 
     mutable std::mutex mLock;
 
-    std::map<int32_t, AAudioServiceEndpointCapture *> mInputs;
-    std::map<int32_t, AAudioServiceEndpointPlay *> mOutputs;
+    std::vector<AAudioServiceEndpointCapture *> mInputs;
+    std::vector<AAudioServiceEndpointPlay *> mOutputs;
 
 };
 
diff --git a/services/oboeservice/AAudioServiceEndpoint.cpp b/services/oboeservice/AAudioServiceEndpoint.cpp
index 3815711..488063f 100644
--- a/services/oboeservice/AAudioServiceEndpoint.cpp
+++ b/services/oboeservice/AAudioServiceEndpoint.cpp
@@ -45,15 +45,18 @@
 #define DEFAULT_BUFFER_CAPACITY   (48 * 8)
 
 // Set up an EXCLUSIVE MMAP stream that will be shared.
-aaudio_result_t AAudioServiceEndpoint::open(int32_t deviceId) {
-    mRequestedDeviceId = deviceId;
+aaudio_result_t AAudioServiceEndpoint::open(const AAudioStreamConfiguration& configuration) {
+    mRequestedDeviceId = configuration.getDeviceId();
     mStreamInternal = getStreamInternal();
 
     AudioStreamBuilder builder;
     builder.setSharingMode(AAUDIO_SHARING_MODE_EXCLUSIVE);
     // Don't fall back to SHARED because that would cause recursion.
     builder.setSharingModeMatchRequired(true);
-    builder.setDeviceId(deviceId);
+    builder.setDeviceId(mRequestedDeviceId);
+    builder.setFormat(configuration.getAudioFormat());
+    builder.setSampleRate(configuration.getSampleRate());
+    builder.setSamplesPerFrame(configuration.getSamplesPerFrame());
     builder.setDirection(getDirection());
     builder.setBufferCapacity(DEFAULT_BUFFER_CAPACITY);
 
@@ -139,3 +142,20 @@
     }
     mRegisteredStreams.clear();
 }
+
+bool AAudioServiceEndpoint::matches(const AAudioStreamConfiguration& configuration) {
+    if (configuration.getDeviceId() != AAUDIO_UNSPECIFIED &&
+            configuration.getDeviceId() != mStreamInternal->getDeviceId()) {
+        return false;
+    }
+    if (configuration.getSampleRate() != AAUDIO_UNSPECIFIED &&
+            configuration.getSampleRate() != mStreamInternal->getSampleRate()) {
+        return false;
+    }
+    if (configuration.getSamplesPerFrame() != AAUDIO_UNSPECIFIED &&
+            configuration.getSamplesPerFrame() != mStreamInternal->getSamplesPerFrame()) {
+        return false;
+    }
+
+    return true;
+}
diff --git a/services/oboeservice/AAudioServiceEndpoint.h b/services/oboeservice/AAudioServiceEndpoint.h
index 090b1dd..72015b1 100644
--- a/services/oboeservice/AAudioServiceEndpoint.h
+++ b/services/oboeservice/AAudioServiceEndpoint.h
@@ -36,7 +36,7 @@
 public:
     virtual ~AAudioServiceEndpoint() = default;
 
-    virtual aaudio_result_t open(int32_t deviceId);
+    virtual aaudio_result_t open(const AAudioStreamConfiguration& configuration);
 
     int32_t getSampleRate() const { return mStreamInternal->getSampleRate(); }
     int32_t getSamplesPerFrame() const { return mStreamInternal->getSamplesPerFrame();  }
@@ -67,6 +67,8 @@
         mReferenceCount = count;
     }
 
+    bool matches(const AAudioStreamConfiguration& configuration);
+
     virtual AudioStreamInternal *getStreamInternal() = 0;
 
     std::atomic<bool>        mCallbackEnabled;
diff --git a/services/oboeservice/AAudioServiceEndpointCapture.cpp b/services/oboeservice/AAudioServiceEndpointCapture.cpp
index 2bb79bf..a144c54 100644
--- a/services/oboeservice/AAudioServiceEndpointCapture.cpp
+++ b/services/oboeservice/AAudioServiceEndpointCapture.cpp
@@ -42,8 +42,8 @@
     delete mDistributionBuffer;
 }
 
-aaudio_result_t AAudioServiceEndpointCapture::open(int32_t deviceId) {
-    aaudio_result_t result = AAudioServiceEndpoint::open(deviceId);
+aaudio_result_t AAudioServiceEndpointCapture::open(const AAudioStreamConfiguration& configuration) {
+    aaudio_result_t result = AAudioServiceEndpoint::open(configuration);
     if (result == AAUDIO_OK) {
         delete mDistributionBuffer;
         int distributionBufferSizeBytes = getStreamInternal()->getFramesPerBurst()
diff --git a/services/oboeservice/AAudioServiceEndpointCapture.h b/services/oboeservice/AAudioServiceEndpointCapture.h
index 35857d1..8a3d72f 100644
--- a/services/oboeservice/AAudioServiceEndpointCapture.h
+++ b/services/oboeservice/AAudioServiceEndpointCapture.h
@@ -27,7 +27,7 @@
     explicit AAudioServiceEndpointCapture(android::AAudioService &audioService);
     virtual ~AAudioServiceEndpointCapture();
 
-    aaudio_result_t open(int32_t deviceId) override;
+    aaudio_result_t open(const AAudioStreamConfiguration& configuration) override;
 
     AudioStreamInternal *getStreamInternal() override {
         return &mStreamInternalCapture;
diff --git a/services/oboeservice/AAudioServiceEndpointPlay.cpp b/services/oboeservice/AAudioServiceEndpointPlay.cpp
index bbe4788..7ab3bcd 100644
--- a/services/oboeservice/AAudioServiceEndpointPlay.cpp
+++ b/services/oboeservice/AAudioServiceEndpointPlay.cpp
@@ -46,8 +46,8 @@
 AAudioServiceEndpointPlay::~AAudioServiceEndpointPlay() {
 }
 
-aaudio_result_t AAudioServiceEndpointPlay::open(int32_t deviceId) {
-    aaudio_result_t result = AAudioServiceEndpoint::open(deviceId);
+aaudio_result_t AAudioServiceEndpointPlay::open(const AAudioStreamConfiguration& configuration) {
+    aaudio_result_t result = AAudioServiceEndpoint::open(configuration);
     if (result == AAUDIO_OK) {
         mMixer.allocate(getStreamInternal()->getSamplesPerFrame(),
                         getStreamInternal()->getFramesPerBurst());
diff --git a/services/oboeservice/AAudioServiceEndpointPlay.h b/services/oboeservice/AAudioServiceEndpointPlay.h
index 89935ae..c22f510 100644
--- a/services/oboeservice/AAudioServiceEndpointPlay.h
+++ b/services/oboeservice/AAudioServiceEndpointPlay.h
@@ -40,7 +40,7 @@
     explicit AAudioServiceEndpointPlay(android::AAudioService &audioService);
     virtual ~AAudioServiceEndpointPlay();
 
-    aaudio_result_t open(int32_t deviceId) override;
+    aaudio_result_t open(const AAudioStreamConfiguration& configuration) override;
 
     AudioStreamInternal *getStreamInternal() override {
         return &mStreamInternalPlay;
diff --git a/services/oboeservice/AAudioServiceStreamShared.cpp b/services/oboeservice/AAudioServiceStreamShared.cpp
index 7515ea7..7475692 100644
--- a/services/oboeservice/AAudioServiceStreamShared.cpp
+++ b/services/oboeservice/AAudioServiceStreamShared.cpp
@@ -106,11 +106,10 @@
     }
 
     const AAudioStreamConfiguration &configurationInput = request.getConstantConfiguration();
-    int32_t deviceId = configurationInput.getDeviceId();
     aaudio_direction_t direction = request.getDirection();
 
     AAudioEndpointManager &mEndpointManager = AAudioEndpointManager::getInstance();
-    mServiceEndpoint = mEndpointManager.openEndpoint(mAudioService, deviceId, direction);
+    mServiceEndpoint = mEndpointManager.openEndpoint(mAudioService, configurationOutput, direction);
     if (mServiceEndpoint == nullptr) {
         ALOGE("AAudioServiceStreamShared::open() mServiceEndPoint = %p", mServiceEndpoint);
         return AAUDIO_ERROR_UNAVAILABLE;