Merge "Add recommendation setting and remove app settings" into sc-dev
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 5cfb665..e3302d1 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -9850,12 +9850,10 @@
         public static final String MEDIA_CONTROLS_RESUME = "qs_media_resumption";
 
         /**
-         * Controls which packages are blocked from persisting in media controls when resumption is
-         * enabled. The list of packages is set by the user in the Settings app.
-         * @see Settings.Secure#MEDIA_CONTROLS_RESUME
+         * Controls whether contextual suggestions can be shown in the media controls.
          * @hide
          */
-        public static final String MEDIA_CONTROLS_RESUME_BLOCKED = "qs_media_resumption_blocked";
+        public static final String MEDIA_CONTROLS_RECOMMENDATION = "qs_media_recommend";
 
         /**
          * Controls magnification mode when magnification is enabled via a system-wide triple tap
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index cf54083..ae6165b 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -169,7 +169,7 @@
         Settings.Secure.AWARE_TAP_PAUSE_TOUCH_COUNT,
         Settings.Secure.PEOPLE_STRIP,
         Settings.Secure.MEDIA_CONTROLS_RESUME,
-        Settings.Secure.MEDIA_CONTROLS_RESUME_BLOCKED,
+        Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION,
         Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE,
         Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
         Settings.Secure.ACCESSIBILITY_MAGNIFICATION_CAPABILITY,
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index 50fab4f..e09d420 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -251,8 +251,7 @@
         VALIDATORS.put(Secure.TAP_GESTURE, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.PEOPLE_STRIP, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.MEDIA_CONTROLS_RESUME, BOOLEAN_VALIDATOR);
-        VALIDATORS.put(Secure.MEDIA_CONTROLS_RESUME_BLOCKED,
-                COLON_SEPARATED_PACKAGE_LIST_VALIDATOR);
+        VALIDATORS.put(Secure.MEDIA_CONTROLS_RECOMMENDATION, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.ACCESSIBILITY_MAGNIFICATION_MODE,
                 new InclusiveIntegerRangeValidator(
                         Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN,
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
index ffcec29..c74f2fe 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
@@ -138,17 +138,6 @@
     private val mediaEntries: LinkedHashMap<String, MediaData> = LinkedHashMap()
     // There should ONLY be at most one Smartspace media recommendation.
     private var smartspaceMediaTarget: SmartspaceTarget? = null
-    internal var appsBlockedFromResume: MutableSet<String> = Utils.getBlockedMediaApps(context)
-        set(value) {
-            // Update list
-            appsBlockedFromResume.clear()
-            appsBlockedFromResume.addAll(value)
-
-            // Remove any existing resume players that are now blocked
-            appsBlockedFromResume.forEach {
-                removeAllForPackage(it)
-            }
-        }
     private var smartspaceSession: SmartspaceSession? = null
 
     @Inject
@@ -690,7 +679,9 @@
     }
 
     override fun onSmartspaceTargetsUpdated(targets: List<Parcelable>) {
-        Log.d(TAG, "My Smartspace media updates are here")
+        if (!Utils.allowMediaRecommendations(context)) {
+            return
+        }
         val mediaTargets = targets.filterIsInstance<SmartspaceTarget>()
         when (mediaTargets.size) {
             0 -> {
@@ -736,8 +727,7 @@
     fun onNotificationRemoved(key: String) {
         Assert.isMainThread()
         val removed = mediaEntries.remove(key)
-        if (useMediaResumption && removed?.resumeAction != null &&
-                !isBlockedFromResume(removed.packageName) && removed?.isLocalSession == true) {
+        if (useMediaResumption && removed?.resumeAction != null && removed?.isLocalSession) {
             Log.d(TAG, "Not removing $key because resumable")
             // Move to resume key (aka package name) if that key doesn't already exist.
             val resumeAction = getResumeMediaAction(removed.resumeAction!!)
@@ -765,13 +755,6 @@
         }
     }
 
-    private fun isBlockedFromResume(packageName: String?): Boolean {
-        if (packageName == null) {
-            return true
-        }
-        return appsBlockedFromResume.contains(packageName)
-    }
-
     fun setMediaResumptionEnabled(isEnabled: Boolean) {
         if (useMediaResumption == isEnabled) {
             return
@@ -844,7 +827,6 @@
             println("externalListeners: ${mediaDataFilter.listeners}")
             println("mediaEntries: $mediaEntries")
             println("useMediaResumption: $useMediaResumption")
-            println("appsBlockedFromResume: $appsBlockedFromResume")
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt b/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt
index 3bf7fb0..7fe408f 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt
@@ -58,7 +58,6 @@
 
     private var useMediaResumption: Boolean = Utils.useMediaResumption(context)
     private val resumeComponents: ConcurrentLinkedQueue<ComponentName> = ConcurrentLinkedQueue()
-    private var blockedApps: MutableSet<String> = Utils.getBlockedMediaApps(context)
 
     private lateinit var mediaDataManager: MediaDataManager
 
@@ -123,14 +122,6 @@
                 mediaDataManager.setMediaResumptionEnabled(useMediaResumption)
             }
         }, Settings.Secure.MEDIA_CONTROLS_RESUME)
-
-        // Listen to changes in which apps are allowed to persist
-        tunerService.addTunable(object : TunerService.Tunable {
-            override fun onTuningChanged(key: String?, newValue: String?) {
-                blockedApps = Utils.getBlockedMediaApps(context)
-                mediaDataManager.appsBlockedFromResume = blockedApps
-            }
-        }, Settings.Secure.MEDIA_CONTROLS_RESUME_BLOCKED)
     }
 
     private fun loadSavedComponents() {
@@ -159,10 +150,8 @@
         }
 
         resumeComponents.forEach {
-            if (!blockedApps.contains(it.packageName)) {
-                val browser = mediaBrowserFactory.create(mediaBrowserCallback, it)
-                browser.findRecentMedia()
-            }
+            val browser = mediaBrowserFactory.create(mediaBrowserCallback, it)
+            browser.findRecentMedia()
         }
     }
 
@@ -172,8 +161,7 @@
             mediaBrowser?.disconnect()
             mediaBrowser = null
             // If we don't have a resume action, check if we haven't already
-            if (data.resumeAction == null && !data.hasCheckedForResume &&
-                    !blockedApps.contains(data.packageName) && data.isLocalSession) {
+            if (data.resumeAction == null && !data.hasCheckedForResume && data.isLocalSession) {
                 // TODO also check for a media button receiver intended for restarting (b/154127084)
                 Log.d(TAG, "Checking for service component for " + data.packageName)
                 val pm = context.packageManager
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
index 7244ffe..26f4a2b 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
@@ -68,8 +68,7 @@
     private static final String[] RESET_EXCEPTION_LIST = new String[] {
             QSTileHost.TILES_SETTING,
             Settings.Secure.DOZE_ALWAYS_ON,
-            Settings.Secure.MEDIA_CONTROLS_RESUME,
-            Secure.MEDIA_CONTROLS_RESUME_BLOCKED
+            Settings.Secure.MEDIA_CONTROLS_RESUME
     };
 
     private final Observer mObserver = new Observer();
diff --git a/packages/SystemUI/src/com/android/systemui/util/Utils.java b/packages/SystemUI/src/com/android/systemui/util/Utils.java
index f3a95f7..bf00667 100644
--- a/packages/SystemUI/src/com/android/systemui/util/Utils.java
+++ b/packages/SystemUI/src/com/android/systemui/util/Utils.java
@@ -23,7 +23,6 @@
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.provider.Settings;
-import android.text.TextUtils;
 import android.view.ContextThemeWrapper;
 import android.view.View;
 
@@ -32,9 +31,7 @@
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.FeatureFlags;
 
-import java.util.HashSet;
 import java.util.List;
-import java.util.Set;
 import java.util.function.Consumer;
 
 public class Utils {
@@ -144,7 +141,7 @@
 
     /**
      * Allow media resumption controls. Requires {@link #useQsMediaPlayer(Context)} to be enabled.
-     * Off by default, but can be enabled by setting to 1
+     * On by default, but can be disabled by setting to 0
      */
     public static boolean useMediaResumption(Context context) {
         int flag = Settings.Secure.getInt(context.getContentResolver(),
@@ -153,20 +150,14 @@
     }
 
     /**
-     * Get the set of apps for which the user has manually disabled resumption.
+     * Allow recommendations from smartspace to show in media controls.
+     * Requires {@link #useQsMediaPlayer(Context)} to be enabled.
+     * On by default, but can be disabled by setting to 0
      */
-    public static Set<String> getBlockedMediaApps(Context context) {
-        String list = Settings.Secure.getString(context.getContentResolver(),
-                Settings.Secure.MEDIA_CONTROLS_RESUME_BLOCKED);
-        if (TextUtils.isEmpty(list)) {
-            return new HashSet<>();
-        }
-        String[] names = list.split(":");
-        Set<String> apps = new HashSet<>(names.length);
-        for (String s : names) {
-            apps.add(s);
-        }
-        return apps;
+    public static boolean allowMediaRecommendations(Context context) {
+        int flag = Settings.Secure.getInt(context.getContentResolver(),
+                Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION, 1);
+        return useQsMediaPlayer(context) && flag > 0;
     }
 
     /**
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
index 59527f6..dfb149d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
@@ -8,6 +8,7 @@
 import android.media.MediaMetadata
 import android.media.session.MediaController
 import android.media.session.MediaSession
+import android.provider.Settings
 import android.service.notification.StatusBarNotification
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper.RunWithLooper
@@ -83,11 +84,16 @@
     @Captor lateinit var mediaDataCaptor: ArgumentCaptor<MediaData>
     private val clock = FakeSystemClock()
 
+    private val originalSmartspaceSetting = Settings.Secure.getInt(context.contentResolver,
+            Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION, 1)
+
     @Before
     fun setup() {
         foregroundExecutor = FakeExecutor(clock)
         backgroundExecutor = FakeExecutor(clock)
         smartspaceMediaDataProvider = SmartspaceMediaDataProvider()
+        Settings.Secure.putInt(context.contentResolver,
+                Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION, 1)
         mediaDataManager = MediaDataManager(
             context = context,
             backgroundExecutor = backgroundExecutor,
@@ -139,6 +145,8 @@
     fun tearDown() {
         session.release()
         mediaDataManager.destroy()
+        Settings.Secure.putInt(context.contentResolver,
+                Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION, originalSmartspaceSetting)
     }
 
     @Test
@@ -257,55 +265,6 @@
     }
 
     @Test
-    fun testAppBlockedFromResumption() {
-        // GIVEN that the manager has a notification with a resume action
-        whenever(controller.metadata).thenReturn(metadataBuilder.build())
-        mediaDataManager.onNotificationAdded(KEY, mediaNotification)
-        assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
-        assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
-        verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor))
-        val data = mediaDataCaptor.value
-        assertThat(data.resumption).isFalse()
-        mediaDataManager.onMediaDataLoaded(KEY, null, data.copy(resumeAction = Runnable {}))
-
-        // and the manager should block the package from creating resume controls
-        val blocked = mutableSetOf(PACKAGE_NAME, "com.example.app")
-        mediaDataManager.appsBlockedFromResume = blocked
-
-        // WHEN the notification is removed
-        mediaDataManager.onNotificationRemoved(KEY)
-
-        // THEN the media data is removed
-        verify(listener).onMediaDataRemoved(eq(KEY))
-    }
-
-    @Test
-    fun testAppUnblockedFromResumption() {
-        // GIVEN that an app was blocked from resuming
-        val blocked = mutableSetOf(PACKAGE_NAME, "com.example.app")
-        mediaDataManager.appsBlockedFromResume = blocked
-
-        // and GIVEN that the manager has a notification from that app with a resume action
-        whenever(controller.metadata).thenReturn(metadataBuilder.build())
-        mediaDataManager.onNotificationAdded(KEY, mediaNotification)
-        assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
-        assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
-        verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor))
-        val data = mediaDataCaptor.value
-        assertThat(data.resumption).isFalse()
-        mediaDataManager.onMediaDataLoaded(KEY, null, data.copy(resumeAction = Runnable {}))
-
-        // WHEN the app is unblocked
-        mediaDataManager.appsBlockedFromResume = mutableSetOf("com.example.app")
-
-        // and the notification is removed
-        mediaDataManager.onNotificationRemoved(KEY)
-
-        // THEN the entry will stay as a resume control
-        verify(listener).onMediaDataLoaded(eq(PACKAGE_NAME), eq(KEY), capture(mediaDataCaptor))
-    }
-
-    @Test
     fun testAddResumptionControls() {
         // WHEN resumption controls are added
         val desc = MediaDescription.Builder().run {
@@ -382,6 +341,18 @@
     }
 
     @Test
+    fun testOnSmartspaceMediaDataLoaded_settingDisabled_doesNothing() {
+        // WHEN media recommendation setting is off
+        Settings.Secure.putInt(context.contentResolver,
+                Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION, 0)
+        smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
+
+        // THEN smartspace signal is ignored
+        verify(listener, never())
+                .onSmartspaceMediaDataLoaded(anyObject(), anyObject(), anyBoolean())
+    }
+
+    @Test
     fun testOnMediaDataChanged_updatesLastActiveTime() {
         val currentTime = clock.elapsedRealtime()
         mediaDataManager.onNotificationAdded(KEY, mediaNotification)