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

Commit 455a0a31 authored by Hugh Chen's avatar Hugh Chen
Browse files

Disable entry point of output switcher

It adds a minimum value if it shows only one available
cast device in the output switcher. Because users can only
change the volume slider or stop control in the output switcher.
It's too hidden to have the user stop cast in the UI.

- This CL will disable the entry point of the output switcher
  if there is only one available cast device in the list.
- Update test cases.

Bug: 163095048
Test: make -j42 RunSettingsRoboTests
Change-Id: I8906878e1ba769d6940041f17d83b5de6b2a32c0
Merged-In: I8906878e1ba769d6940041f17d83b5de6b2a32c0
(cherry picked from commit b6840ced)
parent 434bffe9
Loading
Loading
Loading
Loading
+33 −0
Original line number Diff line number Diff line
@@ -18,6 +18,10 @@ package com.android.settings;

import static android.content.Intent.EXTRA_USER;
import static android.content.Intent.EXTRA_USER_ID;
import static android.media.MediaRoute2Info.TYPE_GROUP;
import static android.media.MediaRoute2Info.TYPE_REMOTE_SPEAKER;
import static android.media.MediaRoute2Info.TYPE_REMOTE_TV;
import static android.media.MediaRoute2Info.TYPE_UNKNOWN;
import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH;
import static android.text.format.DateUtils.FORMAT_SHOW_DATE;

@@ -53,6 +57,8 @@ import android.graphics.drawable.Drawable;
import android.graphics.drawable.VectorDrawable;
import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;
import android.media.MediaRoute2Info;
import android.media.MediaRouter2Manager;
import android.net.ConnectivityManager;
import android.net.LinkProperties;
import android.net.Network;
@@ -1137,4 +1143,31 @@ public final class Utils extends com.android.settingslib.Utils {
        drawable.draw(canvas);
        return roundedBitmap;
    }

    /**
     * Returns {@code true} if needed to disable media output, otherwise returns {@code false}.
     */
    public static boolean isMediaOutputDisabled(
            MediaRouter2Manager router2Manager, String packageName) {
        boolean isMediaOutputDisabled = false;
        if (!TextUtils.isEmpty(packageName)) {
            final List<MediaRoute2Info> infos = router2Manager.getAvailableRoutes(packageName);
            if (infos.size() == 1) {
                final MediaRoute2Info info = infos.get(0);
                final int deviceType = info.getType();
                switch (deviceType) {
                    case TYPE_UNKNOWN:
                    case TYPE_REMOTE_TV:
                    case TYPE_REMOTE_SPEAKER:
                    case TYPE_GROUP:
                        isMediaOutputDisabled = true;
                        break;
                    default:
                        isMediaOutputDisabled = false;
                        break;
                }
            }
        }
        return isMediaOutputDisabled;
    }
}
+31 −5
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.settings.media;

import static android.app.slice.Slice.EXTRA_RANGE_VALUE;
import static android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;

import static com.android.settings.slices.CustomSliceRegistry.REMOTE_MEDIA_SLICE_URI;

@@ -24,11 +25,15 @@ import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.media.MediaRouter2Manager;
import android.media.RoutingSessionInfo;
import android.net.Uri;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import android.util.Log;

import androidx.annotation.VisibleForTesting;
import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice;
import androidx.slice.builders.ListBuilder;
@@ -59,6 +64,9 @@ public class RemoteMediaSlice implements CustomSliceable {

    private MediaDeviceUpdateWorker mWorker;

    @VisibleForTesting
    MediaRouter2Manager mRouterManager;

    public RemoteMediaSlice(Context context) {
        mContext = context;
    }
@@ -80,6 +88,9 @@ public class RemoteMediaSlice implements CustomSliceable {
            Log.e(TAG, "Unable to get the slice worker.");
            return listBuilder.build();
        }
        if (mRouterManager == null) {
            mRouterManager = MediaRouter2Manager.getInstance(mContext);
        }
        // Only displaying remote devices
        final List<RoutingSessionInfo> infos = getWorker().getActiveRemoteMediaDevice();
        if (infos.isEmpty()) {
@@ -98,8 +109,10 @@ public class RemoteMediaSlice implements CustomSliceable {
                        + maxVolume);
                continue;
            }
            final CharSequence appName = Utils.getApplicationLabel(
                    mContext, info.getClientPackageName());
            final CharSequence outputTitle = mContext.getString(R.string.media_output_label_title,
                    Utils.getApplicationLabel(mContext, info.getClientPackageName()));
                    appName);
            listBuilder.addInputRange(new InputRangeBuilder()
                    .setTitleItem(icon, ListBuilder.ICON_IMAGE)
                    .setTitle(castVolume)
@@ -107,11 +120,21 @@ public class RemoteMediaSlice implements CustomSliceable {
                    .setPrimaryAction(getSoundSettingAction(castVolume, icon, info.getId()))
                    .setMax(maxVolume)
                    .setValue(info.getVolume()));

            final boolean isMediaOutputDisabled =
                    Utils.isMediaOutputDisabled(mRouterManager, info.getClientPackageName());
            final SpannableString spannableTitle = new SpannableString(
                    TextUtils.isEmpty(appName) ? "" : appName);
            spannableTitle.setSpan(new ForegroundColorSpan(
                            Utils.getColorAttrDefaultColor(
                                    mContext, android.R.attr.textColorSecondary)), 0,
                    spannableTitle.length(), SPAN_EXCLUSIVE_EXCLUSIVE);
            listBuilder.addRow(new ListBuilder.RowBuilder()
                    .setTitle(outputTitle)
                    .setTitle(isMediaOutputDisabled ? spannableTitle : outputTitle)
                    .setSubtitle(info.getName())
                    .setTitleItem(emptyIcon, ListBuilder.ICON_IMAGE)
                    .setPrimaryAction(getMediaOutputSliceAction(info.getClientPackageName())));
                    .setPrimaryAction(getMediaOutputSliceAction(
                            info.getClientPackageName(), isMediaOutputDisabled)));
        }
        return listBuilder.build();
    }
@@ -144,9 +167,12 @@ public class RemoteMediaSlice implements CustomSliceable {
        return primarySliceAction;
    }

    private SliceAction getMediaOutputSliceAction(String packageName) {
    private SliceAction getMediaOutputSliceAction(
            String packageName, boolean isMediaOutputDisabled) {
        final Intent intent = new Intent()
                .setAction(MediaOutputSliceConstants.ACTION_MEDIA_OUTPUT)
                .setAction(isMediaOutputDisabled
                        ? ""
                        : MediaOutputSliceConstants.ACTION_MEDIA_OUTPUT)
                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                .putExtra(MediaOutputSliceConstants.EXTRA_PACKAGE_NAME, packageName);
        final IconCompat icon = IconCompat.createWithResource(mContext,
+11 −2
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.settings.notification;

import android.content.Context;
import android.content.Intent;
import android.media.MediaRouter2Manager;
import android.media.RoutingSessionInfo;
import android.text.TextUtils;

@@ -57,6 +58,8 @@ public class RemoteVolumeGroupController extends BasePreferenceController implem

    @VisibleForTesting
    LocalMediaManager mLocalMediaManager;
    @VisibleForTesting
    MediaRouter2Manager mRouterManager;

    public RemoteVolumeGroupController(Context context, String preferenceKey) {
        super(context, preferenceKey);
@@ -65,6 +68,7 @@ public class RemoteVolumeGroupController extends BasePreferenceController implem
            mLocalMediaManager.registerCallback(this);
            mLocalMediaManager.startScan();
        }
        mRouterManager = MediaRouter2Manager.getInstance(context);
    }

    @Override
@@ -111,8 +115,10 @@ public class RemoteVolumeGroupController extends BasePreferenceController implem
            if (mPreferenceCategory.findPreference(info.getId()) != null) {
                continue;
            }
            final CharSequence appName = Utils.getApplicationLabel(
                    mContext, info.getClientPackageName());
            final CharSequence outputTitle = mContext.getString(R.string.media_output_label_title,
                    Utils.getApplicationLabel(mContext, info.getClientPackageName()));
                    appName);
            // Add slider
            final RemoteVolumeSeekBarPreference seekBarPreference =
                    new RemoteVolumeSeekBarPreference(mContext);
@@ -125,10 +131,13 @@ public class RemoteVolumeGroupController extends BasePreferenceController implem
            seekBarPreference.setIcon(R.drawable.ic_volume_remote);
            mPreferenceCategory.addPreference(seekBarPreference);
            // Add output indicator
            final boolean isMediaOutputDisabled = Utils.isMediaOutputDisabled(
                    mRouterManager, info.getClientPackageName());
            final Preference preference = new Preference(mContext);
            preference.setKey(SWITCHER_PREFIX + info.getId());
            preference.setTitle(outputTitle);
            preference.setTitle(isMediaOutputDisabled ? appName : outputTitle);
            preference.setSummary(info.getName());
            preference.setEnabled(!isMediaOutputDisabled);
            mPreferenceCategory.addPreference(preference);
        }
    }
+31 −0
Original line number Diff line number Diff line
@@ -40,6 +40,8 @@ import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.VectorDrawable;
import android.media.MediaRoute2Info;
import android.media.MediaRouter2Manager;
import android.net.ConnectivityManager;
import android.net.LinkAddress;
import android.net.LinkProperties;
@@ -299,4 +301,33 @@ public class UtilsTest {

        assertThat(Utils.isSettingsIntelligence(mContext)).isFalse();
    }

    @Test
    public void isMediaOutputDisabled_infosSizeEqual1_returnsTrue() {
        final MediaRouter2Manager router2Manager = mock(MediaRouter2Manager.class);
        final MediaRoute2Info info = mock(MediaRoute2Info.class);
        final List<MediaRoute2Info> infos = new ArrayList<>();
        infos.add(info);

        when(router2Manager.getAvailableRoutes(anyString())).thenReturn(infos);
        when(info.getType()).thenReturn(0);

        assertThat(Utils.isMediaOutputDisabled(router2Manager, "test")).isTrue();
    }

    @Test
    public void isMediaOutputDisabled_infosSizeOverThan1_returnsFalse() {
        final MediaRouter2Manager router2Manager = mock(MediaRouter2Manager.class);
        final MediaRoute2Info info = mock(MediaRoute2Info.class);
        final MediaRoute2Info info2 = mock(MediaRoute2Info.class);
        final List<MediaRoute2Info> infos = new ArrayList<>();
        infos.add(info);
        infos.add(info2);

        when(router2Manager.getAvailableRoutes(anyString())).thenReturn(infos);
        when(info.getType()).thenReturn(0);
        when(info2.getType()).thenReturn(0);

        assertThat(Utils.isMediaOutputDisabled(router2Manager, "test")).isFalse();
    }
}
+2 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import static org.mockito.Mockito.when;

import android.content.Context;
import android.content.Intent;
import android.media.MediaRouter2Manager;
import android.media.RoutingSessionInfo;
import android.net.Uri;

@@ -87,6 +88,7 @@ public class RemoteMediaSliceTest {
        SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);

        mRemoteMediaSlice = new RemoteMediaSlice(mContext);
        mRemoteMediaSlice.mRouterManager = mock(MediaRouter2Manager.class);
        sMediaDeviceUpdateWorker = spy(new MediaDeviceUpdateWorker(mContext,
                REMOTE_MEDIA_SLICE_URI));
        sMediaDeviceUpdateWorker.mLocalMediaManager = mLocalMediaManager;
Loading