Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2677c993 authored by Andre Le's avatar Andre Le
Browse files

AudioDetailsView: Store current input device in MediaSwitchingController

Add an instance to manage current input device, and also add
MediaSwitchingControllerExt to add a flow, that will be used to display
current input device in the audio details view.

Bug: 442004274
Test: manual
Flag: com.android.systemui.qs_tile_detailed_view
Change-Id: I8b1725701457f7a9143cbdc8f1a90ee00a4c097b
parent 70d1d172
Loading
Loading
Loading
Loading
+54 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.
 */

package com.android.systemui.media.dialog

import com.android.settingslib.media.MediaDevice
import com.android.systemui.kairos.awaitClose
import com.android.systemui.qs.flags.QsDetailedView
import com.android.systemui.util.kotlin.getOrNull
import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.onStart

val MediaSwitchingController.currentInputDevice: Flow<MediaDevice?>
    get() =
        conflatedCallbackFlow {
                if (!QsDetailedView.isEnabled) {
                    return@conflatedCallbackFlow
                }

                val callback =
                    object : MediaSwitchingController.Callback {
                        override fun onMediaChanged() {}

                        override fun onMediaStoppedOrPaused() {}

                        override fun onRouteChanged() {}

                        override fun onDeviceListChanged() {
                            trySend(mCurrentInputDevice.getOrNull())
                        }

                        override fun dismissDialog() {}

                        override fun onQuickAccessButtonsChanged() {}
                    }

                start(callback)
                awaitClose { stop() }
            }
            .onStart { emit(null) }
+5 −0
Original line number Diff line number Diff line
@@ -102,6 +102,7 @@ import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -177,6 +178,8 @@ public class MediaSwitchingController
    private boolean mInAudioSharing = false;
    @Nullable private Job mAudioShareJob = null;

    protected Optional<MediaDevice> mCurrentInputDevice;

    @VisibleForTesting
    final InputRouteManager.InputDeviceCallback mInputDeviceCallback =
            new InputRouteManager.InputDeviceCallback() {
@@ -184,6 +187,8 @@ public class MediaSwitchingController
                public void onInputDeviceListUpdated(@NonNull List<MediaDevice> devices) {
                    synchronized (mInputMediaDevicesLock) {
                        buildInputMediaItems(devices);
                        mCurrentInputDevice =
                                devices.stream().filter(MediaDevice::isSelected).findFirst();
                        mCallback.onDeviceListChanged();
                    }
                }
+38 −0
Original line number Diff line number Diff line
@@ -713,6 +713,44 @@ public class MediaSwitchingControllerTest extends SysuiTestCase {
        verify(mCb, atLeastOnce()).onDeviceListChanged();
    }

    @Test
    public void onInputDeviceListUpdate_verifyCurrentInputDevice() {
        mMediaSwitchingController.start(mCb);

        assertThat(mMediaSwitchingController.mCurrentInputDevice).isNull();

        final MediaDevice mediaDevice3 =
                InputMediaDevice.create(
                        mContext,
                        TEST_DEVICE_3_ID,
                        "",
                        AudioDeviceInfo.TYPE_BUILTIN_MIC,
                        MAX_VOLUME,
                        CURRENT_VOLUME,
                        VOLUME_FIXED_TRUE,
                        /* isSelected= */ true,
                        PRODUCT_NAME_BUILTIN_MIC);
        final MediaDevice mediaDevice4 =
                InputMediaDevice.create(
                        mContext,
                        TEST_DEVICE_4_ID,
                        "",
                        AudioDeviceInfo.TYPE_WIRED_HEADSET,
                        MAX_VOLUME,
                        CURRENT_VOLUME,
                        VOLUME_FIXED_TRUE,
                        /* isSelected= */ false,
                        PRODUCT_NAME_WIRED_HEADSET);
        final List<MediaDevice> inputDevices = new ArrayList<>();
        inputDevices.add(mediaDevice3);
        inputDevices.add(mediaDevice4);

        // Input devices have changed.
        mMediaSwitchingController.mInputDeviceCallback.onInputDeviceListUpdated(inputDevices);

        assertThat(mMediaSwitchingController.mCurrentInputDevice.get()).isEqualTo(mediaDevice3);
    }

    @Test
    public void advanced_categorizeMediaItems_withSuggestedDevice_verifyDeviceListSize() {
        when(mMediaDevice1.isSuggestedDevice()).thenReturn(true);