diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java index b73e7a3628db1..d708e577b68eb 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java @@ -30,6 +30,7 @@ import static android.media.MediaRoute2Info.TYPE_USB_DEVICE; import static android.media.MediaRoute2Info.TYPE_USB_HEADSET; import static android.media.MediaRoute2Info.TYPE_WIRED_HEADPHONES; import static android.media.MediaRoute2Info.TYPE_WIRED_HEADSET; +import static android.media.RouteListingPreference.Item.DISABLE_REASON_NONE; import static android.media.RouteListingPreference.Item.FLAG_SUGGESTED_ROUTE; import static com.android.settingslib.media.LocalMediaManager.MediaDeviceState.STATE_SELECTED; @@ -192,6 +193,27 @@ public abstract class MediaDevice implements Comparable { */ public abstract String getId(); + /** + * Get disabled reason of device + * + * @return disabled reason of device + */ + @RouteListingPreference.Item.DisableReason + public int getDisableReason() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE && mItem != null + ? mItem.getDisableReason() : -1; + } + + /** + * Checks if device is has disabled reason + * + * @return true if device has disabled reason + */ + public boolean hasDisabledReason() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE && mItem != null + && mItem.getDisableReason() != DISABLE_REASON_NONE; + } + /** * Checks if device is suggested device from application * diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 4a89bb4dc2695..6043a3c9f463a 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -2522,6 +2522,8 @@ Speakers & Displays Suggested Devices + + Requires premium account diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java index 51b5a3d1a08c0..d6c6a81fbfc0f 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java @@ -16,17 +16,24 @@ package com.android.systemui.media.dialog; +import static android.media.RouteListingPreference.Item.DISABLE_REASON_SUBSCRIPTION_REQUIRED; + +import android.content.Context; import android.content.res.ColorStateList; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.drawable.Drawable; +import android.media.RouteListingPreference; +import android.os.Build; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.CheckBox; import android.widget.TextView; +import androidx.annotation.DoNotInline; import androidx.annotation.NonNull; +import androidx.annotation.RequiresApi; import androidx.core.widget.CompoundButtonCompat; import androidx.recyclerview.widget.RecyclerView; @@ -186,6 +193,17 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { mCurrentActivePosition = position; updateFullItemClickListener(v -> onItemClick(v, device)); setSingleLineLayout(getItemTitle(device)); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU + && mController.isSubStatusSupported() && device.hasDisabledReason()) { + //update to subtext with device status + setUpDeviceIcon(device); + mSubTitleText.setText( + Api34Impl.composeDisabledReason(device.getDisableReason(), mContext)); + updateConnectionFailedStatusIcon(); + updateFullItemClickListener(null); + setTwoLineLayout(device, false /* bFocused */, false /* showSeekBar */, + false /* showProgressBar */, true /* showSubtitle */, + true /* showStatus */); } else if (device.getState() == MediaDeviceState.STATE_CONNECTING_FAILED) { setUpDeviceIcon(device); updateConnectionFailedStatusIcon(); @@ -389,4 +407,17 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { mTitleText.setText(groupDividerTitle); } } + + @RequiresApi(34) + private static class Api34Impl { + @DoNotInline + static String composeDisabledReason(@RouteListingPreference.Item.DisableReason int reason, + Context context) { + switch(reason) { + case DISABLE_REASON_SUBSCRIPTION_REQUIRED: + return context.getString(R.string.media_output_status_require_premium); + } + return ""; + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java index 7bc0c0cc614ba..5b137e91f9e7b 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java @@ -748,6 +748,10 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, return mFeatureFlags.isEnabled(Flags.OUTPUT_SWITCHER_ROUTES_PROCESSING); } + public boolean isSubStatusSupported() { + return mFeatureFlags.isEnabled(Flags.OUTPUT_SWITCHER_DEVICE_STATUS); + } + List getGroupMediaDevices() { final List selectedDevices = getSelectedMediaDevice(); final List selectableDevices = getSelectableMediaDevice(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java index 7c3c9d2a1bb18..77daa3f1c2072 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java @@ -16,6 +16,8 @@ package com.android.systemui.media.dialog; +import static android.media.RouteListingPreference.Item.DISABLE_REASON_SUBSCRIPTION_REQUIRED; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.mock; @@ -57,6 +59,7 @@ public class MediaOutputAdapterTest extends SysuiTestCase { private static final String TEST_DEVICE_ID_1 = "test_device_id_1"; private static final String TEST_DEVICE_ID_2 = "test_device_id_2"; private static final String TEST_SESSION_NAME = "test_session_name"; + private static final int TEST_MAX_VOLUME = 20; private static final int TEST_CURRENT_VOLUME = 10; @@ -78,6 +81,7 @@ public class MediaOutputAdapterTest extends SysuiTestCase { @Before public void setUp() { when(mMediaOutputController.isAdvancedLayoutSupported()).thenReturn(false); + when(mMediaOutputController.isSubStatusSupported()).thenReturn(false); when(mMediaOutputController.getMediaItemList()).thenReturn(mMediaItems); when(mMediaOutputController.getMediaDevices()).thenReturn(mMediaDevices); when(mMediaOutputController.hasAdjustVolumeUserRestriction()).thenReturn(false); @@ -403,6 +407,25 @@ public class MediaOutputAdapterTest extends SysuiTestCase { assertThat(mViewHolder.mTwoLineTitleText.getText()).isEqualTo(TEST_DEVICE_NAME_2); } + @Test + public void subStatusSupported_onBindViewHolder_bindFailedStateDevice_verifyView() { + String deviceStatus = (String) mContext.getText( + R.string.media_output_status_require_premium); + when(mMediaOutputController.isSubStatusSupported()).thenReturn(true); + when(mMediaDevice2.hasDisabledReason()).thenReturn(true); + when(mMediaDevice2.getDisableReason()).thenReturn(DISABLE_REASON_SUBSCRIPTION_REQUIRED); + mMediaOutputAdapter.onBindViewHolder(mViewHolder, 1); + + assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE); + assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.GONE); + assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE); + assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE); + assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(mViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(mViewHolder.mSubTitleText.getText()).isEqualTo(deviceStatus); + assertThat(mViewHolder.mTwoLineTitleText.getText()).isEqualTo(TEST_DEVICE_NAME_2); + } + @Test public void onBindViewHolder_inTransferring_bindTransferringDevice_verifyView() { when(mMediaOutputController.isAnyDeviceTransferring()).thenReturn(true);