Merge "Fix that the inconsistent accessibility content pages under Setup Wizard." into rvc-dev
diff --git a/res/xml/sound_settings.xml b/res/xml/sound_settings.xml
index 8973dec..92f8a3e 100644
--- a/res/xml/sound_settings.xml
+++ b/res/xml/sound_settings.xml
@@ -45,6 +45,7 @@
         android:title="@string/media_output_title"
         android:dialogTitle="@string/media_output_title"
         android:order="-175"
+        settings:searchable="false"
         settings:controller="com.android.settings.sound.MediaOutputPreferenceController"/>
 
     <!-- Call volume -->
diff --git a/src/com/android/settings/sound/MediaOutputPreferenceController.java b/src/com/android/settings/sound/MediaOutputPreferenceController.java
index c731bc3..da92b2b 100644
--- a/src/com/android/settings/sound/MediaOutputPreferenceController.java
+++ b/src/com/android/settings/sound/MediaOutputPreferenceController.java
@@ -20,8 +20,12 @@
 import android.content.Context;
 import android.content.Intent;
 import android.media.AudioManager;
+import android.media.session.MediaController;
+import android.media.session.MediaSessionManager;
+import android.media.session.PlaybackState;
 import android.text.TextUtils;
 
+import androidx.annotation.Nullable;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 
@@ -43,15 +47,18 @@
  */
 public class MediaOutputPreferenceController extends AudioSwitchPreferenceController {
 
+    private MediaController mMediaController;
+
     public MediaOutputPreferenceController(Context context, String key) {
         super(context, key);
+        mMediaController = getActiveLocalMediaController();
     }
 
     @Override
     public void displayPreference(PreferenceScreen screen) {
         super.displayPreference(screen);
 
-        if (!Utils.isAudioModeOngoingCall(mContext)) {
+        if (!Utils.isAudioModeOngoingCall(mContext) && mMediaController != null) {
             mPreference.setVisible(true);
         }
     }
@@ -63,6 +70,11 @@
             return;
         }
 
+        if (mMediaController == null) {
+            // No active local playback
+            return;
+        }
+
         if (Utils.isAudioModeOngoingCall(mContext)) {
             // Ongoing call status, switch entry for media will be disabled.
             mPreference.setVisible(false);
@@ -81,6 +93,9 @@
                 || (connectedHADevices != null && !connectedHADevices.isEmpty()))) {
             activeDevice = findActiveDevice();
         }
+        mPreference.setTitle(mContext.getString(R.string.media_output_label_title,
+                com.android.settings.Utils.getApplicationLabel(mContext,
+                        mMediaController.getPackageName())));
         mPreference.setSummary((activeDevice == null) ?
                 mContext.getText(R.string.media_output_default_summary) :
                 activeDevice.getAlias());
@@ -126,4 +141,26 @@
         }
         return false;
     }
+
+    @Nullable
+    MediaController getActiveLocalMediaController() {
+        final MediaSessionManager mMediaSessionManager = mContext.getSystemService(
+                MediaSessionManager.class);
+
+        for (MediaController controller : mMediaSessionManager.getActiveSessions(null)) {
+            final MediaController.PlaybackInfo pi = controller.getPlaybackInfo();
+            if (pi == null) {
+                return null;
+            }
+            final PlaybackState playbackState = controller.getPlaybackState();
+            if (playbackState == null) {
+                return null;
+            }
+            if (pi.getPlaybackType() == MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL
+                    && playbackState.getState() == PlaybackState.STATE_PLAYING) {
+                return controller;
+            }
+        }
+        return null;
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java
index f78d42f..49928db 100644
--- a/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java
@@ -22,6 +22,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
@@ -33,7 +34,15 @@
 import android.bluetooth.BluetoothManager;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageStats;
+import android.media.AudioAttributes;
 import android.media.AudioManager;
+import android.media.VolumeProvider;
+import android.media.session.MediaController;
+import android.media.session.MediaSessionManager;
+import android.media.session.PlaybackState;
 
 import androidx.preference.Preference;
 import androidx.preference.PreferenceManager;
@@ -60,8 +69,10 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
+import org.robolectric.Shadows;
 import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowBluetoothDevice;
+import org.robolectric.shadows.ShadowPackageManager;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -82,6 +93,8 @@
     private static final String TEST_DEVICE_ADDRESS_2 = "00:B2:B2:B2:B2:B2";
     private static final String TEST_DEVICE_ADDRESS_3 = "00:C3:C3:C3:C3:C3";
     private static final String TEST_DEVICE_ADDRESS_4 = "00:D4:D4:D4:D4:D4";
+    private static final String TEST_PACKAGE_NAME = "com.test.packagename";
+    private static final String TEST_APPLICATION_LABEL = "APP Test Label";
 
     @Mock
     private LocalBluetoothManager mLocalManager;
@@ -95,6 +108,10 @@
     private HearingAidProfile mHearingAidProfile;
     @Mock
     private AudioSwitchPreferenceController.AudioSwitchCallback mAudioSwitchPreferenceCallback;
+    @Mock
+    private MediaSessionManager mMediaSessionManager;
+    @Mock
+    private MediaController mMediaController;
 
     private Context mContext;
     private PreferenceScreen mScreen;
@@ -111,6 +128,13 @@
     private MediaOutputPreferenceController mController;
     private List<BluetoothDevice> mProfileConnectedDevices;
     private List<BluetoothDevice> mHearingAidActiveDevices;
+    private List<MediaController> mMediaControllers = new ArrayList<>();
+    private MediaController.PlaybackInfo mPlaybackInfo;
+    private PlaybackState mPlaybackState;
+    private ShadowPackageManager mShadowPackageManager;
+    private ApplicationInfo mAppInfo;
+    private PackageInfo mPackageInfo;
+    private PackageStats mPackageStats;
 
     @Before
     public void setUp() {
@@ -123,6 +147,23 @@
         ShadowBluetoothUtils.sLocalBluetoothManager = mLocalManager;
         mLocalBluetoothManager = Utils.getLocalBtManager(mContext);
 
+        when(mContext.getSystemService(MediaSessionManager.class)).thenReturn(mMediaSessionManager);
+        when(mMediaSessionManager.getActiveSessions(any())).thenReturn(mMediaControllers);
+        when(mMediaController.getPackageName()).thenReturn(TEST_PACKAGE_NAME);
+        mPlaybackInfo = new MediaController.PlaybackInfo(
+                MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL,
+                VolumeProvider.VOLUME_CONTROL_ABSOLUTE,
+                100,
+                10,
+                new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).build(),
+                null);
+        mPlaybackState = new PlaybackState.Builder()
+                .setState(PlaybackState.STATE_PLAYING, 0, 1)
+                .build();
+        when(mMediaController.getPlaybackInfo()).thenReturn(mPlaybackInfo);
+        when(mMediaController.getPlaybackState()).thenReturn(mPlaybackState);
+        mMediaControllers.add(mMediaController);
+
         when(mLocalBluetoothManager.getEventManager()).thenReturn(mBluetoothEventManager);
         when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager);
         when(mLocalBluetoothProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile);
@@ -227,6 +268,30 @@
     }
 
     @Test
+    public void updateState_noActiveLocalPlayback_noTitle() {
+        mPlaybackState = new PlaybackState.Builder()
+                .setState(PlaybackState.STATE_NONE, 0, 1)
+                .build();
+        when(mMediaController.getPlaybackState()).thenReturn(mPlaybackState);
+        mController = new MediaOutputPreferenceController(mContext, TEST_KEY);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.getTitle()).isNull();
+    }
+
+    @Test
+    public void updateState_withActiveLocalPlayback_checkTitle() {
+        initPackage();
+        mShadowPackageManager.addPackage(mPackageInfo, mPackageStats);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.getTitle()).isEqualTo(
+                mContext.getString(R.string.media_output_label_title, TEST_APPLICATION_LABEL));
+    }
+
+    @Test
     public void click_launch_outputSwitcherSlice() {
         final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
         mController.handlePreferenceTreeClick(mPreference);
@@ -282,4 +347,16 @@
 
         assertThat(mController.findActiveDevice()).isNull();
     }
+
+    private void initPackage() {
+        mShadowPackageManager = Shadows.shadowOf(mContext.getPackageManager());
+        mAppInfo = new ApplicationInfo();
+        mAppInfo.flags = ApplicationInfo.FLAG_INSTALLED;
+        mAppInfo.packageName = TEST_PACKAGE_NAME;
+        mAppInfo.name = TEST_APPLICATION_LABEL;
+        mPackageInfo = new PackageInfo();
+        mPackageInfo.packageName = TEST_PACKAGE_NAME;
+        mPackageInfo.applicationInfo = mAppInfo;
+        mPackageStats = new PackageStats(TEST_PACKAGE_NAME);
+    }
 }