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

Commit 50e9532e authored by Derek Jedral's avatar Derek Jedral
Browse files

Update UI state to connecting when connecting to suggestion

Currently, suggestions only update to the connecting state if they're
discovered. They need to update to the connecting and failure state even
if they're never scanned.

Test: atest
Bug: 417240824
Flag: com.android.media.flags.enable_suggested_device_api
Change-Id: I8fcea4ef0824d00c5b912670c67d4d7adb27ed6b
parent ce82bf55
Loading
Loading
Loading
Loading
+50 −9
Original line number Diff line number Diff line
@@ -46,6 +46,10 @@ import static android.media.MediaRoute2Info.TYPE_WIRED_HEADSET;
import static android.media.session.MediaController.PlaybackInfo;

import static com.android.media.flags.Flags.avoidBinderCallsDuringRender;
import static com.android.settingslib.media.LocalMediaManager.MediaDeviceState.STATE_CONNECTING;
import static com.android.settingslib.media.LocalMediaManager.MediaDeviceState.STATE_CONNECTING_FAILED;
import static com.android.settingslib.media.LocalMediaManager.MediaDeviceState.STATE_DISCONNECTED;
import static com.android.settingslib.media.LocalMediaManager.MediaDeviceState.STATE_GROUPING;
import static com.android.settingslib.media.LocalMediaManager.MediaDeviceState.STATE_SELECTED;

import android.annotation.TargetApi;
@@ -139,16 +143,18 @@ public abstract class InfoMediaManager {
     * Wrapper class around SuggestedDeviceInfo and the corresponsing connection state of the
     * suggestion.
     */
    public class SuggestedDeviceState {
    public static class SuggestedDeviceState {
        private final SuggestedDeviceInfo mSuggestedDeviceInfo;
        private final @LocalMediaManager.MediaDeviceState int mConnectionState;

        private SuggestedDeviceState(@NonNull SuggestedDeviceInfo suggestedDeviceInfo) {
        @VisibleForTesting
        SuggestedDeviceState(@NonNull SuggestedDeviceInfo suggestedDeviceInfo) {
            mSuggestedDeviceInfo = suggestedDeviceInfo;
            mConnectionState = LocalMediaManager.MediaDeviceState.STATE_DISCONNECTED;
            mConnectionState = STATE_DISCONNECTED;
        }

        private SuggestedDeviceState(
        @VisibleForTesting
        SuggestedDeviceState(
                @NonNull SuggestedDeviceInfo suggestedDeviceInfo,
                @LocalMediaManager.MediaDeviceState int state) {
            mSuggestedDeviceInfo = suggestedDeviceInfo;
@@ -188,6 +194,11 @@ public abstract class InfoMediaManager {
        public int hashCode() {
            return Objects.hash(mSuggestedDeviceInfo, mConnectionState);
        }

        @Override
        public String toString() {
            return "info: " + mSuggestedDeviceInfo + " state " + mConnectionState;
        }
    }

    /** Checked exception that signals the specified package is not present in the system. */
@@ -805,11 +816,42 @@ public abstract class InfoMediaManager {
        }
        if (!Objects.equals(previousState, newSuggestedDeviceState)) {
            mSuggestedDeviceState = newSuggestedDeviceState;
            dispatchOnSuggestedDeviceUpdated();
        }
    }

    final void onConnectionAttemptedForSuggestion(@NonNull SuggestedDeviceState suggestion) {
        if (!Objects.equals(suggestion, mSuggestedDeviceState)) {
            return;
        }
        if (mSuggestedDeviceState.getConnectionState() == STATE_DISCONNECTED
                || mSuggestedDeviceState.getConnectionState() == STATE_CONNECTING_FAILED) {
            mSuggestedDeviceState =
                    new SuggestedDeviceState(
                            mSuggestedDeviceState.getSuggestedDeviceInfo(), STATE_CONNECTING);
            dispatchOnSuggestedDeviceUpdated();
        }
    }

    final void onConnectionAttemptCompletedForSuggestion(@NonNull SuggestedDeviceState suggestion) {
        if (!Objects.equals(suggestion, mSuggestedDeviceState)) {
            return;
        }
        if (mSuggestedDeviceState.getConnectionState() == STATE_CONNECTING
                || mSuggestedDeviceState.getConnectionState() == STATE_GROUPING) {
            mSuggestedDeviceState =
                    new SuggestedDeviceState(
                            mSuggestedDeviceState.getSuggestedDeviceInfo(),
                            STATE_CONNECTING_FAILED);
            dispatchOnSuggestedDeviceUpdated();
        }
    }

    private void dispatchOnSuggestedDeviceUpdated() {
        for (MediaDeviceCallback callback : getCallbacks()) {
            callback.onSuggestedDeviceUpdated(mSuggestedDeviceState);
        }
    }
    }

    @Nullable
    private List<SuggestedDeviceInfo> getSuggestions() {
@@ -1070,8 +1112,7 @@ public abstract class InfoMediaManager {

    private static Drawable getDrawableForSuggestion(
            Context context, SuggestedDeviceState suggestion) {
        if (suggestion.getConnectionState()
                == LocalMediaManager.MediaDeviceState.STATE_CONNECTING_FAILED) {
        if (suggestion.getConnectionState() == STATE_CONNECTING_FAILED) {
            return context.getDrawable(android.R.drawable.ic_info);
        }
        int deviceType = suggestion.getSuggestedDeviceInfo().getType();
+3 −0
Original line number Diff line number Diff line
@@ -920,6 +920,8 @@ public class LocalMediaManager implements BluetoothCallback {
                            }
                            unregisterCallback(mDeviceCallback);
                            stopScan();
                            mInfoMediaManager.onConnectionAttemptCompletedForSuggestion(
                                    mSuggestedDeviceState);
                        }
                    };
        }
@@ -929,6 +931,7 @@ public class LocalMediaManager implements BluetoothCallback {
            startScan();
            mConnectSuggestedDeviceHandler.postDelayed(
                    mConnectionAttemptFinishedRunnable, SCAN_DURATION_MS);
            mInfoMediaManager.onConnectionAttemptedForSuggestion(mSuggestedDeviceState);
        }
    }
}
+154 −0
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.media.InfoMediaManager.Api34Impl;
import com.android.settingslib.media.InfoMediaManager.SuggestedDeviceState;

import com.google.common.collect.ImmutableList;

@@ -1210,6 +1211,159 @@ public class InfoMediaManagerTest {
                .isEqualTo(LocalMediaManager.MediaDeviceState.STATE_CONNECTING);
    }

    @EnableFlags(Flags.FLAG_ENABLE_SUGGESTED_DEVICE_API)
    @Test
    public void onConnectionAttemptedForSuggestion_suggestionDoesNotMatch_callbackNotNotified() {
        SuggestedDeviceInfo suggestedDeviceInfo1 =
                new SuggestedDeviceInfo.Builder("device_name", TEST_ID_3, 0).build();
        SuggestedDeviceInfo suggestedDeviceInfo2 =
                new SuggestedDeviceInfo.Builder("device_name_2", TEST_ID_3, 0).build();
        RouterInfoMediaManager mediaManager = createRouterInfoMediaManager();
        setAvailableRoutesList(TEST_PACKAGE_NAME);
        mediaManager.registerCallback(mCallback);
        verify(mRouter2)
                .registerDeviceSuggestionsUpdatesCallback(
                        any(), mDeviceSuggestionsUpdatesCallback.capture());
        mDeviceSuggestionsUpdatesCallback
                .getValue()
                .onSuggestionsUpdated("random_package_name", List.of(suggestedDeviceInfo1));
        clearInvocations(mCallback);

        mediaManager.onConnectionAttemptedForSuggestion(
                new SuggestedDeviceState(suggestedDeviceInfo2));

        verify(mCallback, never()).onSuggestedDeviceUpdated(any());
    }

    @EnableFlags(Flags.FLAG_ENABLE_SUGGESTED_DEVICE_API)
    @Test
    public void onConnectionAttemptForSuggestion_notDisconnected_callbackNotNotified() {
        SuggestedDeviceInfo suggestedDeviceInfo =
                new SuggestedDeviceInfo.Builder("device_name", TEST_ID_3, 0).build();
        RouterInfoMediaManager mediaManager = createRouterInfoMediaManager();
        setAvailableRoutesList(TEST_PACKAGE_NAME);
        mediaManager.registerCallback(mCallback);
        verify(mRouter2)
                .registerDeviceSuggestionsUpdatesCallback(
                        any(), mDeviceSuggestionsUpdatesCallback.capture());
        mDeviceSuggestionsUpdatesCallback
                .getValue()
                .onSuggestionsUpdated("random_package_name", List.of(suggestedDeviceInfo));

        mediaManager.onConnectionAttemptedForSuggestion(
                new SuggestedDeviceState(suggestedDeviceInfo));
        clearInvocations(mCallback);
        mediaManager.onConnectionAttemptedForSuggestion(
                new SuggestedDeviceState(suggestedDeviceInfo));

        verify(mCallback, never()).onSuggestedDeviceUpdated(any());
    }

    @EnableFlags(Flags.FLAG_ENABLE_SUGGESTED_DEVICE_API)
    @Test
    public void onConnectionAttemptedForSuggestion_disconnected_callbackNotified() {
        SuggestedDeviceInfo suggestedDeviceInfo =
                new SuggestedDeviceInfo.Builder("device_name", TEST_ID_3, 0).build();
        RouterInfoMediaManager mediaManager = createRouterInfoMediaManager();
        setAvailableRoutesList(TEST_PACKAGE_NAME);
        mediaManager.registerCallback(mCallback);
        verify(mRouter2)
                .registerDeviceSuggestionsUpdatesCallback(
                        any(), mDeviceSuggestionsUpdatesCallback.capture());
        mDeviceSuggestionsUpdatesCallback
                .getValue()
                .onSuggestionsUpdated("random_package_name", List.of(suggestedDeviceInfo));
        clearInvocations(mCallback);

        mediaManager.onConnectionAttemptedForSuggestion(
                new SuggestedDeviceState(suggestedDeviceInfo));

        verify(mCallback).onSuggestedDeviceUpdated(mSuggestedDeviceStateCaptor.capture());
        assertThat(mSuggestedDeviceStateCaptor.getValue().getConnectionState())
                .isEqualTo(LocalMediaManager.MediaDeviceState.STATE_CONNECTING);
    }

    @EnableFlags(Flags.FLAG_ENABLE_SUGGESTED_DEVICE_API)
    @Test
    public void
            onConnectionAttemptCompletedForSuggestion_suggestionDoesNotMatch_callbackNotNotified() {
        SuggestedDeviceInfo suggestedDeviceInfo1 =
                new SuggestedDeviceInfo.Builder("device_name", TEST_ID_3, 0).build();
        SuggestedDeviceInfo suggestedDeviceInfo2 =
                new SuggestedDeviceInfo.Builder("device_name_2", TEST_ID_3, 0).build();
        RouterInfoMediaManager mediaManager = createRouterInfoMediaManager();
        setAvailableRoutesList(TEST_PACKAGE_NAME);
        mediaManager.registerCallback(mCallback);
        verify(mRouter2)
                .registerDeviceSuggestionsUpdatesCallback(
                        any(), mDeviceSuggestionsUpdatesCallback.capture());
        mDeviceSuggestionsUpdatesCallback
                .getValue()
                .onSuggestionsUpdated("random_package_name", List.of(suggestedDeviceInfo1));

        mediaManager.onConnectionAttemptedForSuggestion(
                new SuggestedDeviceState(suggestedDeviceInfo1));
        clearInvocations(mCallback);
        mediaManager.onConnectionAttemptCompletedForSuggestion(
                new SuggestedDeviceState(suggestedDeviceInfo2));

        verify(mCallback, never()).onSuggestedDeviceUpdated(any());
    }

    @EnableFlags(Flags.FLAG_ENABLE_SUGGESTED_DEVICE_API)
    @Test
    public void onConnectionAttemptedForSuggestion_notConnecting_callbackNotNotified() {
        SuggestedDeviceInfo suggestedDeviceInfo =
                new SuggestedDeviceInfo.Builder("device_name", TEST_ID_3, 0).build();
        RouterInfoMediaManager mediaManager = createRouterInfoMediaManager();
        setAvailableRoutesList(TEST_PACKAGE_NAME);
        mediaManager.registerCallback(mCallback);
        verify(mRouter2)
                .registerDeviceSuggestionsUpdatesCallback(
                        any(), mDeviceSuggestionsUpdatesCallback.capture());
        mDeviceSuggestionsUpdatesCallback
                .getValue()
                .onSuggestionsUpdated("random_package_name", List.of(suggestedDeviceInfo));

        mediaManager.onConnectionAttemptedForSuggestion(
                new SuggestedDeviceState(suggestedDeviceInfo));
        mediaManager.onConnectionAttemptCompletedForSuggestion(
                new SuggestedDeviceState(
                        suggestedDeviceInfo, LocalMediaManager.MediaDeviceState.STATE_CONNECTING));
        clearInvocations(mCallback);
        mediaManager.onConnectionAttemptCompletedForSuggestion(
                new SuggestedDeviceState(suggestedDeviceInfo));

        verify(mCallback, never()).onSuggestedDeviceUpdated(any());
    }

    @EnableFlags(Flags.FLAG_ENABLE_SUGGESTED_DEVICE_API)
    @Test
    public void onConnectionAttemptCompletedForSuggestion_connecting_callbackNotified() {
        SuggestedDeviceInfo suggestedDeviceInfo =
                new SuggestedDeviceInfo.Builder("device_name", TEST_ID_3, 0).build();
        RouterInfoMediaManager mediaManager = createRouterInfoMediaManager();
        setAvailableRoutesList(TEST_PACKAGE_NAME);
        mediaManager.registerCallback(mCallback);
        verify(mRouter2)
                .registerDeviceSuggestionsUpdatesCallback(
                        any(), mDeviceSuggestionsUpdatesCallback.capture());
        mDeviceSuggestionsUpdatesCallback
                .getValue()
                .onSuggestionsUpdated("random_package_name", List.of(suggestedDeviceInfo));

        mediaManager.onConnectionAttemptedForSuggestion(
                new SuggestedDeviceState(suggestedDeviceInfo));
        clearInvocations(mCallback);
        mediaManager.onConnectionAttemptCompletedForSuggestion(
                new SuggestedDeviceState(
                        suggestedDeviceInfo, LocalMediaManager.MediaDeviceState.STATE_CONNECTING));

        verify(mCallback).onSuggestedDeviceUpdated(mSuggestedDeviceStateCaptor.capture());
        assertThat(mSuggestedDeviceStateCaptor.getValue().getConnectionState())
                .isEqualTo(LocalMediaManager.MediaDeviceState.STATE_CONNECTING_FAILED);
    }

    @EnableFlags(Flags.FLAG_ENABLE_OUTPUT_SWITCHER_DEVICE_GROUPING)
    @Test
    public void composePreferenceRouteListing_useSystemOrderingIsFalse() {