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/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;
 }