Merge "[Settings] Remove unused string for erease eSIM" into rvc-dev
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 5379c96..da4583b 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -11002,6 +11002,7 @@
     <string-array name="graphics_driver_all_apps_preference_values">
         <item>@string/graphics_driver_app_preference_default</item>
         <item>@string/graphics_driver_app_preference_game_driver</item>
+        <item>@string/graphics_driver_app_preference_prerelease_driver</item>
     </string-array>
     <!-- All the values of graphics driver for app preference [CHAR LIMIT=50] -->
     <string-array name="graphics_driver_app_preference_values">
@@ -11620,6 +11621,8 @@
     <string name="media_output_panel_title">Switch output</string>
     <!-- Summary for represent which device is playing media [CHAR LIMIT=NONE] -->
     <string name="media_output_panel_summary_of_playing_device">Currently playing on <xliff:g id="device_name" example="Bose headphone">%1$s</xliff:g></string>
+    <!-- Summary for disconnected status [CHAR LIMIT=50] -->
+    <string name="media_output_disconnected_status"><xliff:g id="device_name" example="My device">%1$s</xliff:g> (disconnected)</string>
 
     <!-- Label for the title on wfc disclaimer fragment. [CHAR LIMIT=40] -->
     <string name="wfc_disclaimer_title_text">Important information</string>
diff --git a/res/xml/graphics_driver_settings.xml b/res/xml/graphics_driver_settings.xml
index c72c8fb..a1fa78c 100644
--- a/res/xml/graphics_driver_settings.xml
+++ b/res/xml/graphics_driver_settings.xml
@@ -24,8 +24,6 @@
         android:key="graphics_driver_all_apps_preference"
         android:title="@string/graphics_driver_all_apps_preference_title"
         android:dialogTitle="@string/graphics_driver_all_apps_preference_title"
-        android:entries="@array/graphics_driver_all_apps_preference_values"
-        android:entryValues="@array/graphics_driver_all_apps_preference_values"
         settings:controller="com.android.settings.development.graphicsdriver.GraphicsDriverEnableForAllAppsPreferenceController">
     </ListPreference>
 
diff --git a/src/com/android/settings/development/graphicsdriver/GraphicsDriverAppPreferenceController.java b/src/com/android/settings/development/graphicsdriver/GraphicsDriverAppPreferenceController.java
index 2013b45..b1a31fb 100644
--- a/src/com/android/settings/development/graphicsdriver/GraphicsDriverAppPreferenceController.java
+++ b/src/com/android/settings/development/graphicsdriver/GraphicsDriverAppPreferenceController.java
@@ -26,9 +26,7 @@
 import android.content.res.Resources;
 import android.os.Handler;
 import android.os.Looper;
-import android.os.SystemProperties;
 import android.provider.Settings;
-import android.text.TextUtils;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.ListPreference;
@@ -60,9 +58,6 @@
         GraphicsDriverContentObserver.OnGraphicsDriverContentChangedListener, LifecycleObserver,
         OnStart, OnStop {
 
-    private static final String PROPERTY_GFX_DRIVER_GAME = "ro.gfx.driver.0";
-    private static final String PROPERTY_GFX_DRIVER_PRERELEASE = "ro.gfx.driver.1";
-
     private final Context mContext;
     private final ContentResolver mContentResolver;
     private final String mPreferenceTitle;
@@ -98,7 +93,8 @@
         mPreferencePrereleaseDriver =
                 resources.getString(R.string.graphics_driver_app_preference_prerelease_driver);
         mPreferenceSystem = resources.getString(R.string.graphics_driver_app_preference_system);
-        mEntryList = constructEntryList();
+        mEntryList = GraphicsDriverEnableForAllAppsPreferenceController.constructEntryList(
+                mContext, true);
 
         // TODO: Move this task to background if there's potential ANR/Jank.
         // Update the UI when all the app infos are ready.
@@ -195,28 +191,6 @@
         updateState(mPreferenceGroup);
     }
 
-    /**
-     * Constructs and returns a list of graphics driver choices.
-     */
-    public CharSequence[] constructEntryList() {
-        final String prereleaseDriverPackageName =
-                SystemProperties.get(PROPERTY_GFX_DRIVER_PRERELEASE);
-        final String gameDriverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER_GAME);
-
-        List<CharSequence> entryList = new ArrayList<>();
-        entryList.add(mPreferenceDefault);
-        if (!TextUtils.isEmpty(prereleaseDriverPackageName)) {
-            entryList.add(mPreferencePrereleaseDriver);
-        }
-        if (!TextUtils.isEmpty(gameDriverPackageName)) {
-            entryList.add(mPreferenceGameDriver);
-        }
-        entryList.add(mPreferenceSystem);
-        CharSequence[] filteredEntryList = new CharSequence[entryList.size()];
-        filteredEntryList = entryList.toArray(filteredEntryList);
-        return filteredEntryList;
-    }
-
     // AppInfo class to achieve loading the application label only once
     class AppInfo {
         AppInfo(PackageManager packageManager, ApplicationInfo applicationInfo) {
diff --git a/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableForAllAppsPreferenceController.java b/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableForAllAppsPreferenceController.java
index 4baa993..29f1014 100644
--- a/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableForAllAppsPreferenceController.java
+++ b/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableForAllAppsPreferenceController.java
@@ -18,10 +18,15 @@
 
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
 import android.content.res.Resources;
+import android.os.Build;
 import android.os.Handler;
 import android.os.Looper;
+import android.os.SystemProperties;
 import android.provider.Settings;
+import android.text.TextUtils;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.ListPreference;
@@ -35,6 +40,11 @@
 import com.android.settingslib.core.lifecycle.events.OnStop;
 import com.android.settingslib.development.DevelopmentSettingsEnabler;
 
+import dalvik.system.VMRuntime;
+
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * Controller of global switch to enable Game Driver for all Apps.
  */
@@ -47,6 +57,8 @@
     public static final int GAME_DRIVER_ALL_APPS = 1;
     public static final int GAME_DRIVER_PRERELEASE_ALL_APPS = 2;
     public static final int GAME_DRIVER_OFF = 3;
+    public static final String PROPERTY_GFX_DRIVER_GAME = "ro.gfx.driver.0";
+    public static final String PROPERTY_GFX_DRIVER_PRERELEASE = "ro.gfx.driver.1";
 
     private final Context mContext;
     private final ContentResolver mContentResolver;
@@ -54,6 +66,8 @@
     private final String mPreferenceGameDriver;
     private final String mPreferencePrereleaseDriver;
     @VisibleForTesting
+    CharSequence[] mEntryList;
+    @VisibleForTesting
     GraphicsDriverContentObserver mGraphicsDriverContentObserver;
 
     private ListPreference mPreference;
@@ -69,6 +83,7 @@
                 resources.getString(R.string.graphics_driver_app_preference_game_driver);
         mPreferencePrereleaseDriver =
                 resources.getString(R.string.graphics_driver_app_preference_prerelease_driver);
+        mEntryList = constructEntryList(mContext, false);
         mGraphicsDriverContentObserver =
                 new GraphicsDriverContentObserver(new Handler(Looper.getMainLooper()), this);
     }
@@ -87,6 +102,8 @@
     public void displayPreference(PreferenceScreen screen) {
         super.displayPreference(screen);
         mPreference = screen.findPreference(getPreferenceKey());
+        mPreference.setEntries(mEntryList);
+        mPreference.setEntryValues(mEntryList);
         mPreference.setOnPreferenceChangeListener(this);
     }
 
@@ -147,4 +164,64 @@
     public void onGraphicsDriverContentChanged() {
         updateState(mPreference);
     }
+
+    /**
+     * Constructs and returns a list of graphics driver choices.
+     */
+    public static CharSequence[] constructEntryList(Context context, boolean withSystem) {
+        final Resources resources = context.getResources();
+        final String prereleaseDriverPackageName =
+                SystemProperties.get(PROPERTY_GFX_DRIVER_PRERELEASE);
+        final String gameDriverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER_GAME);
+
+        List<CharSequence> entryList = new ArrayList<>();
+        entryList.add(resources.getString(R.string.graphics_driver_app_preference_default));
+        final PackageManager pm = context.getPackageManager();
+        if (!TextUtils.isEmpty(prereleaseDriverPackageName)
+                && hasDriverPackage(pm, prereleaseDriverPackageName)) {
+            entryList.add(resources.getString(
+                    R.string.graphics_driver_app_preference_prerelease_driver));
+        }
+        if (!TextUtils.isEmpty(gameDriverPackageName)
+                && hasDriverPackage(pm, gameDriverPackageName)) {
+            entryList.add(resources.getString(R.string.graphics_driver_app_preference_game_driver));
+        }
+        if (withSystem) {
+            entryList.add(resources.getString(R.string.graphics_driver_app_preference_system));
+        }
+        CharSequence[] filteredEntryList = new CharSequence[entryList.size()];
+        filteredEntryList = entryList.toArray(filteredEntryList);
+        return filteredEntryList;
+    }
+
+    private static boolean hasDriverPackage(PackageManager pm, String driverPackageName) {
+        final ApplicationInfo driverAppInfo;
+        try {
+            driverAppInfo = pm.getApplicationInfo(driverPackageName,
+                    PackageManager.MATCH_SYSTEM_ONLY);
+        } catch (PackageManager.NameNotFoundException e) {
+            return false;
+        }
+        if (driverAppInfo.targetSdkVersion < Build.VERSION_CODES.O) {
+            return false;
+        }
+        final String abi = chooseAbi(driverAppInfo);
+        if (abi == null) {
+            return false;
+        }
+        return true;
+    }
+
+    private static String chooseAbi(ApplicationInfo ai) {
+        final String isa = VMRuntime.getCurrentInstructionSet();
+        if (ai.primaryCpuAbi != null
+                && isa.equals(VMRuntime.getInstructionSet(ai.primaryCpuAbi))) {
+            return ai.primaryCpuAbi;
+        }
+        if (ai.secondaryCpuAbi != null
+                && isa.equals(VMRuntime.getInstructionSet(ai.secondaryCpuAbi))) {
+            return ai.secondaryCpuAbi;
+        }
+        return null;
+    }
 }
diff --git a/src/com/android/settings/media/MediaOutputSlice.java b/src/com/android/settings/media/MediaOutputSlice.java
index 3c9999e..92fa843 100644
--- a/src/com/android/settings/media/MediaOutputSlice.java
+++ b/src/com/android/settings/media/MediaOutputSlice.java
@@ -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.MEDIA_OUTPUT_SLICE_URI;
 
@@ -24,9 +25,12 @@
 import android.bluetooth.BluetoothAdapter;
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.Color;
 import android.graphics.drawable.Drawable;
 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;
@@ -162,7 +166,7 @@
     }
 
     private ListBuilder.RowBuilder getMediaDeviceRow(MediaDevice device) {
-        final String title = device.getName();
+        final String deviceName = device.getName();
         final PendingIntent broadcastAction =
                 getBroadcastIntent(mContext, device.getId(), device.hashCode());
         final IconCompat deviceIcon = getDeviceIconCompat(device);
@@ -170,9 +174,22 @@
         final ListBuilder.RowBuilder rowBuilder = new ListBuilder.RowBuilder()
                 .setTitleItem(deviceIcon, ListBuilder.ICON_IMAGE)
                 .setPrimaryAction(SliceAction.create(broadcastAction, deviceIcon,
-                        ListBuilder.ICON_IMAGE, title))
-                .setTitle(title)
-                .setSubtitle(device.isConnected() ? null : device.getSummary());
+                        ListBuilder.ICON_IMAGE, deviceName));
+        // Append status to tile only for the disconnected Bluetooth device.
+        if (device.getDeviceType() == MediaDevice.MediaDeviceType.TYPE_BLUETOOTH_DEVICE
+                && !device.isConnected()) {
+            final SpannableString spannableTitle = new SpannableString(
+                    mContext.getString(R.string.media_output_disconnected_status, deviceName));
+            spannableTitle.setSpan(new ForegroundColorSpan(Color.GRAY), deviceName.length(),
+                    spannableTitle.length(), SPAN_EXCLUSIVE_EXCLUSIVE);
+            rowBuilder.setTitle(spannableTitle);
+            rowBuilder.setPrimaryAction(SliceAction.create(broadcastAction, deviceIcon,
+                    ListBuilder.ICON_IMAGE, spannableTitle));
+        } else {
+            rowBuilder.setTitle(deviceName);
+            rowBuilder.setPrimaryAction(SliceAction.create(broadcastAction, deviceIcon,
+                    ListBuilder.ICON_IMAGE, deviceName));
+        }
 
         return rowBuilder;
     }
diff --git a/src/com/android/settings/panel/VolumePanel.java b/src/com/android/settings/panel/VolumePanel.java
index 61dee15..dd9b53c 100644
--- a/src/com/android/settings/panel/VolumePanel.java
+++ b/src/com/android/settings/panel/VolumePanel.java
@@ -48,7 +48,7 @@
 
     @Override
     public CharSequence getTitle() {
-        return mContext.getText(R.string.volume_connectivity_panel_title);
+        return mContext.getText(R.string.sound_settings);
     }
 
     @Override
diff --git a/tests/robotests/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableForAllAppsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableForAllAppsPreferenceControllerTest.java
index 366a18d..920e9d1 100644
--- a/tests/robotests/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableForAllAppsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableForAllAppsPreferenceControllerTest.java
@@ -82,6 +82,8 @@
                 mResolver, Settings.Global.GAME_DRIVER_ALL_APPS, GAME_DRIVER_DEFAULT);
 
         mController = new GraphicsDriverEnableForAllAppsPreferenceController(mContext, "testKey");
+        mController.mEntryList = mContext.getResources().getStringArray(
+                R.array.graphics_driver_all_apps_preference_values);
         when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
         mController.displayPreference(mScreen);
     }
diff --git a/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java b/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java
index adbd14d..f71c090 100644
--- a/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java
+++ b/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java
@@ -44,6 +44,7 @@
 import androidx.slice.core.SliceQuery;
 import androidx.slice.widget.SliceLiveData;
 
+import com.android.settings.R;
 import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
 import com.android.settingslib.media.LocalMediaManager;
 import com.android.settingslib.media.MediaDevice;
@@ -156,6 +157,26 @@
     }
 
     @Test
+    public void getSlice_disconnectedBluetooth_verifyTitle() {
+        mDevices.clear();
+        final MediaDevice device = mock(MediaDevice.class);
+        when(device.getName()).thenReturn(TEST_DEVICE_1_NAME);
+        when(device.getIcon()).thenReturn(mTestDrawable);
+        when(device.getMaxVolume()).thenReturn(100);
+        when(device.isConnected()).thenReturn(false);
+
+        mDevices.add(device);
+        mMediaDeviceUpdateWorker.onDeviceListUpdate(mDevices);
+
+        final Slice mediaSlice = mMediaOutputSlice.getSlice();
+        final SliceMetadata metadata = SliceMetadata.from(mContext, mediaSlice);
+
+        final SliceAction primaryAction = metadata.getPrimaryAction();
+        assertThat(primaryAction.getTitle().toString()).isEqualTo(TEST_DEVICE_1_NAME + " ("
+                + mContext.getText(R.string.media_output_disconnected_status) + ")");
+    }
+
+    @Test
     public void onNotifyChange_foundMediaDevice_connect() {
         mDevices.clear();
         final MediaDevice device = mock(MediaDevice.class);