Loading src/com/android/settings/Utils.java +33 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; } } src/com/android/settings/media/RemoteMediaSlice.java +31 −5 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -59,6 +64,9 @@ public class RemoteMediaSlice implements CustomSliceable { private MediaDeviceUpdateWorker mWorker; @VisibleForTesting MediaRouter2Manager mRouterManager; public RemoteMediaSlice(Context context) { mContext = context; } Loading @@ -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()) { Loading @@ -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) Loading @@ -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(); } Loading Loading @@ -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, Loading src/com/android/settings/notification/RemoteVolumeGroupController.java +11 −2 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading @@ -65,6 +68,7 @@ public class RemoteVolumeGroupController extends BasePreferenceController implem mLocalMediaManager.registerCallback(this); mLocalMediaManager.startScan(); } mRouterManager = MediaRouter2Manager.getInstance(context); } @Override Loading Loading @@ -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); Loading @@ -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); } } Loading tests/robotests/src/com/android/settings/UtilsTest.java +31 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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(); } } tests/robotests/src/com/android/settings/media/RemoteMediaSliceTest.java +2 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 Loading
src/com/android/settings/Utils.java +33 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; } }
src/com/android/settings/media/RemoteMediaSlice.java +31 −5 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -59,6 +64,9 @@ public class RemoteMediaSlice implements CustomSliceable { private MediaDeviceUpdateWorker mWorker; @VisibleForTesting MediaRouter2Manager mRouterManager; public RemoteMediaSlice(Context context) { mContext = context; } Loading @@ -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()) { Loading @@ -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) Loading @@ -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(); } Loading Loading @@ -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, Loading
src/com/android/settings/notification/RemoteVolumeGroupController.java +11 −2 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading @@ -65,6 +68,7 @@ public class RemoteVolumeGroupController extends BasePreferenceController implem mLocalMediaManager.registerCallback(this); mLocalMediaManager.startScan(); } mRouterManager = MediaRouter2Manager.getInstance(context); } @Override Loading Loading @@ -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); Loading @@ -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); } } Loading
tests/robotests/src/com/android/settings/UtilsTest.java +31 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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(); } }
tests/robotests/src/com/android/settings/media/RemoteMediaSliceTest.java +2 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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