audioflinger: fix mmap device selection

Preserve initial device selection on mmap streams in order to
reuse it when a new client starts on the same stream so that
audiopolicy does not use the default route for the new client.

Bug: 64981153
Test: verify AAudio playback over MMAP with forced device selection to
speaker while headset is connected.

Change-Id: I7c117c3c0f8e7ad08f8e63ea804c19ce21808874
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 0df9a39..a15b256 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -326,7 +326,7 @@
     sp<MmapThread> thread = mMmapThreads.valueFor(io);
     if (thread != 0) {
         interface = new MmapThreadHandle(thread);
-        thread->configure(attr, streamType, sessionId, callback, portId);
+        thread->configure(attr, streamType, sessionId, callback, *deviceId, portId);
         *handle = portId;
     } else {
         ret = NO_INIT;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 8c4531a..d951e93 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -7545,6 +7545,8 @@
         AudioHwDevice *hwDev, sp<StreamHalInterface> stream,
         audio_devices_t outDevice, audio_devices_t inDevice, bool systemReady)
     : ThreadBase(audioFlinger, id, outDevice, inDevice, MMAP, systemReady),
+      mSessionId(AUDIO_SESSION_NONE),
+      mDeviceId(AUDIO_PORT_HANDLE_NONE), mPortId(AUDIO_PORT_HANDLE_NONE),
       mHalStream(stream), mHalDevice(hwDev->hwDevice()), mAudioHwDev(hwDev),
       mActiveTracks(&this->mLocalLog)
 {
@@ -7580,11 +7582,13 @@
                                                 audio_stream_type_t streamType __unused,
                                                 audio_session_t sessionId,
                                                 const sp<MmapStreamCallback>& callback,
+                                                audio_port_handle_t deviceId,
                                                 audio_port_handle_t portId)
 {
     mAttr = *attr;
     mSessionId = sessionId;
     mCallback = callback;
+    mDeviceId = deviceId;
     mPortId = portId;
 }
 
@@ -7640,7 +7644,7 @@
         audio_stream_type_t stream = streamType();
         audio_output_flags_t flags =
                 (audio_output_flags_t)(AUDIO_OUTPUT_FLAG_MMAP_NOIRQ | AUDIO_OUTPUT_FLAG_DIRECT);
-        audio_port_handle_t deviceId = AUDIO_PORT_HANDLE_NONE;
+        audio_port_handle_t deviceId = mDeviceId;
         ret = AudioSystem::getOutputForAttr(&mAttr, &io,
                                             mSessionId,
                                             &stream,
@@ -7654,7 +7658,7 @@
         config.sample_rate = mSampleRate;
         config.channel_mask = mChannelMask;
         config.format = mFormat;
-        audio_port_handle_t deviceId = AUDIO_PORT_HANDLE_NONE;
+        audio_port_handle_t deviceId = mDeviceId;
         ret = AudioSystem::getInputForAttr(&mAttr, &io,
                                               mSessionId,
                                               client.clientPid,
@@ -7991,17 +7995,19 @@
         mPrevOutDevice = type;
         sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);
         sp<MmapStreamCallback> callback = mCallback.promote();
-        if (callback != 0) {
+        if (mDeviceId != deviceId && callback != 0) {
             callback->onRoutingChanged(deviceId);
         }
+        mDeviceId = deviceId;
     }
     if (!isOutput() && mPrevInDevice != mInDevice) {
         mPrevInDevice = type;
         sendIoConfigEvent_l(AUDIO_INPUT_CONFIG_CHANGED);
         sp<MmapStreamCallback> callback = mCallback.promote();
-        if (callback != 0) {
+        if (mDeviceId != deviceId && callback != 0) {
             callback->onRoutingChanged(deviceId);
         }
+        mDeviceId = deviceId;
     }
     return status;
 }
@@ -8242,9 +8248,10 @@
                                                 audio_stream_type_t streamType,
                                                 audio_session_t sessionId,
                                                 const sp<MmapStreamCallback>& callback,
+                                                audio_port_handle_t deviceId,
                                                 audio_port_handle_t portId)
 {
-    MmapThread::configure(attr, streamType, sessionId, callback, portId);
+    MmapThread::configure(attr, streamType, sessionId, callback, deviceId, portId);
     mStreamType = streamType;
 }
 
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 32f2bc4..8d7bb1a 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -1479,6 +1479,7 @@
                                       audio_stream_type_t streamType,
                                       audio_session_t sessionId,
                                       const sp<MmapStreamCallback>& callback,
+                                      audio_port_handle_t deviceId,
                                       audio_port_handle_t portId);
 
                 void        disconnect();
@@ -1540,6 +1541,7 @@
 
                 audio_attributes_t      mAttr;
                 audio_session_t         mSessionId;
+                audio_port_handle_t     mDeviceId;
                 audio_port_handle_t     mPortId;
 
                 wp<MmapStreamCallback>  mCallback;
@@ -1562,6 +1564,7 @@
                                       audio_stream_type_t streamType,
                                       audio_session_t sessionId,
                                       const sp<MmapStreamCallback>& callback,
+                                      audio_port_handle_t deviceId,
                                       audio_port_handle_t portId);
 
                 AudioStreamOut* clearOutput();