OSDN Git Service

audio: several concurrent capture fixes
authorEric Laurent <elaurent@google.com>
Wed, 8 Feb 2017 02:17:24 +0000 (18:17 -0800)
committerEric Laurent <elaurent@google.com>
Fri, 10 Feb 2017 05:09:55 +0000 (21:09 -0800)
Make sure AudioRecord clients are invalidated synchronously
when closing an input stream instead of when the capture thread
exits.

Fix AudioPolicyManager::getInputForDevice() logic to make sure that
not only the first opened input encountered is considered when looking
for a compatible input to reuse for concurrent capture.

Bug: 22702906
Test: run CTS test
Change-Id: I7f69609d4ee70a37ab06753ff970b12df17d885b

services/audioflinger/Threads.cpp
services/audioflinger/Threads.h
services/audiopolicy/managerdefault/AudioPolicyManager.cpp

index a1d81f9..b42bd05 100644 (file)
@@ -5976,6 +5976,18 @@ void AudioFlinger::RecordThread::onFirstRef()
     run(mThreadName, PRIORITY_URGENT_AUDIO);
 }
 
+void AudioFlinger::RecordThread::preExit()
+{
+    ALOGV("  preExit()");
+    Mutex::Autolock _l(mLock);
+    for (size_t i = 0; i < mTracks.size(); i++) {
+        sp<RecordTrack> track = mTracks[i];
+        track->invalidate();
+    }
+    mActiveTracks.clear();
+    mStartStopCond.broadcast();
+}
+
 bool AudioFlinger::RecordThread::threadLoop()
 {
     nsecs_t lastWarning = 0;
index 3fb0b07..9d0c32c 100644 (file)
@@ -1346,6 +1346,7 @@ public:
 
     // Thread virtuals
     virtual bool        threadLoop();
+    virtual void        preExit();
 
     // RefBase
     virtual void        onFirstRef();
index 564ed56..edbff1b 100644 (file)
@@ -1631,8 +1631,8 @@ audio_io_handle_t AudioPolicyManager::getInputForDevice(audio_devices_t device,
                                                               isSoundTrigger,
                                                               policyMix, mpClientInterface);
 
-
     // reuse an open input if possible
+    sp<AudioInputDescriptor> reusedInputDesc;
     for (size_t i = 0; i < mInputs.size(); i++) {
         sp<AudioInputDescriptor> desc = mInputs.valueAt(i);
         // reuse input if:
@@ -1656,28 +1656,27 @@ audio_io_handle_t AudioPolicyManager::getInputForDevice(audio_devices_t device,
                 } else {
                     ALOGW("getInputForDevice() record with different attributes"
                           " exists for session %d", session);
-                    break;
+                    continue;
                 }
             } else if (isSoundTrigger) {
-                break;
+                continue;
             }
 
-            // force close input if current source is now the highest priority request on this input
-            // and current input properties are not exactly as requested.
-            if (!isConcurrentSource(inputSource) && !isConcurrentSource(desc->inputSource()) &&
+            // Reuse the already opened input stream on this profile if:
+            // - the new capture source is background OR
+            // - the path requested configurations match OR
+            // - the new source priority is less than the highest source priority on this input
+            // If the input stream cannot be reused, close it before opening a new stream
+            // on the same profile for the new client so that the requested path configuration
+            // can be selected.
+            if (!isConcurrentSource(inputSource) &&
                     ((desc->mSamplingRate != samplingRate ||
                     desc->mChannelMask != channelMask ||
                     !audio_formats_match(desc->mFormat, format)) &&
                     (source_priority(desc->getHighestPrioritySource(false /*activeOnly*/)) <
                      source_priority(inputSource)))) {
-                ALOGV("%s: ", __FUNCTION__);
-                AudioSessionCollection sessions = desc->getAudioSessions(false /*activeOnly*/);
-                for (size_t j = 0; j < sessions.size(); j++) {
-                    audio_session_t currentSession = sessions.keyAt(j);
-                    stopInput(desc->mIoHandle, currentSession);
-                    releaseInput(desc->mIoHandle, currentSession);
-                }
-                break;
+                reusedInputDesc = desc;
+                continue;
             } else {
                 desc->addAudioSession(session, audioSession);
                 ALOGV("%s: reusing input %d", __FUNCTION__, mInputs.keyAt(i));
@@ -1686,6 +1685,15 @@ audio_io_handle_t AudioPolicyManager::getInputForDevice(audio_devices_t device,
         }
     }
 
+    if (reusedInputDesc != 0) {
+        AudioSessionCollection sessions = reusedInputDesc->getAudioSessions(false /*activeOnly*/);
+        for (size_t j = 0; j < sessions.size(); j++) {
+            audio_session_t currentSession = sessions.keyAt(j);
+            stopInput(reusedInputDesc->mIoHandle, currentSession);
+            releaseInput(reusedInputDesc->mIoHandle, currentSession);
+        }
+    }
+
     audio_config_t config = AUDIO_CONFIG_INITIALIZER;
     config.sample_rate = profileSamplingRate;
     config.channel_mask = profileChannelMask;