Fix cloud provider todos for Android T

Added official support for app developers to set a cloud provider
with:

adb shell device_config put storage_native_boot
allowed_cloud_providers com.example.cloudmediaprovidersample.provider

The old method using set_cloud_provider still works just for CTS. This
will be removed in a subsequent cl

Test: Manual
Bug: 232457261
Change-Id: Id9c430324024a4c4b6bfb4d9ec122b4c73bf5dbf
diff --git a/src/com/android/providers/media/MediaProvider.java b/src/com/android/providers/media/MediaProvider.java
index f934478..3046888 100644
--- a/src/com/android/providers/media/MediaProvider.java
+++ b/src/com/android/providers/media/MediaProvider.java
@@ -1068,7 +1068,16 @@
                 MIGRATION_LISTENER, mIdGenerator);
         mExternalDbFacade = new ExternalDbFacade(getContext(), mExternalDatabase, mVolumeCache);
         mPickerDbFacade = new PickerDbFacade(context);
-        mPickerSyncController = new PickerSyncController(context, mPickerDbFacade, this);
+
+        final String localPickerProvider = PickerSyncController.LOCAL_PICKER_PROVIDER_AUTHORITY;
+        final String allowedCloudProviders =
+                getStringDeviceConfig(PickerSyncController.ALLOWED_CLOUD_PROVIDERS_KEY,
+                        /* default */ "");
+        final int pickerSyncDelayMs = getIntDeviceConfig(PickerSyncController.SYNC_DELAY_MS,
+                /* default */ 5000);
+
+        mPickerSyncController = new PickerSyncController(context, mPickerDbFacade,
+                localPickerProvider, allowedCloudProviders, pickerSyncDelayMs);
         mPickerDataLayer = new PickerDataLayer(context, mPickerDbFacade, mPickerSyncController);
         mPickerUriResolver = new PickerUriResolver(context, mPickerDbFacade);
 
@@ -6333,12 +6342,9 @@
             case MediaStore.SET_CLOUD_PROVIDER_CALL: {
                 // TODO(b/190713331): Remove after initial development
                 final String cloudProvider = extras.getString(MediaStore.EXTRA_CLOUD_PROVIDER);
-                Log.i(TAG, "Developer initiated cloud provider switch: " + cloudProvider);
-                if (mPickerSyncController.setCloudProvider(cloudProvider)
-                        && SdkLevel.isAtLeastT()) {
-                    mStorageManager.setCloudMediaProvider(cloudProvider);
-                }
-                // fall through
+                Log.i(TAG, "Test initiated cloud provider switch: " + cloudProvider);
+                mPickerSyncController.forceSetCloudProvider(cloudProvider);
+                // fall-through
             }
             case MediaStore.SYNC_PROVIDERS_CALL: {
                 syncAllMedia();
@@ -6384,8 +6390,7 @@
         // local_provider while running as MediaProvider
         final long t = Binder.clearCallingIdentity();
         try {
-            // TODO(b/190713331): Remove after initial development
-            Log.v(TAG, "Developer initiated provider sync");
+            Log.v(TAG, "Test initiated cloud provider sync");
             mPickerSyncController.syncAllMedia();
         } finally {
             Binder.restoreCallingIdentity(t);
diff --git a/src/com/android/providers/media/photopicker/PickerSyncController.java b/src/com/android/providers/media/photopicker/PickerSyncController.java
index 489950f..d0fb856 100644
--- a/src/com/android/providers/media/photopicker/PickerSyncController.java
+++ b/src/com/android/providers/media/photopicker/PickerSyncController.java
@@ -40,10 +40,9 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Process;
-import android.os.SystemProperties;
+import android.os.storage.StorageManager;
 import android.provider.CloudMediaProvider;
 import android.provider.CloudMediaProviderContract;
-import android.provider.DeviceConfig;
 import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.Log;
@@ -53,10 +52,9 @@
 import androidx.annotation.VisibleForTesting;
 
 import com.android.modules.utils.BackgroundThread;
-import com.android.providers.media.MediaProvider;
+import com.android.modules.utils.build.SdkLevel;
 import com.android.providers.media.R;
 import com.android.providers.media.photopicker.data.PickerDbFacade;
-import com.android.providers.media.util.DeviceConfigUtils;
 import com.android.providers.media.util.ForegroundThread;
 import com.android.providers.media.util.StringUtils;
 
@@ -75,11 +73,10 @@
 public class PickerSyncController {
     private static final String TAG = "PickerSyncController";
 
-    public static final String PROP_DEFAULT_SYNC_DELAY_MS = "pickerdb.default_sync_delay_ms";
+    public static final String SYNC_DELAY_MS = "default_sync_delay_ms";
+    public static final String ALLOWED_CLOUD_PROVIDERS_KEY = "allowed_cloud_providers";
 
     private static final String PREFS_KEY_CLOUD_PROVIDER_AUTHORITY = "cloud_provider_authority";
-    private static final String PREFS_KEY_CLOUD_PROVIDER_PKGNAME = "cloud_provider_pkg_name";
-    private static final String PREFS_KEY_CLOUD_PROVIDER_UID = "cloud_provider_uid";
     private static final String PREFS_KEY_CLOUD_PROVIDER_PENDING_NOTIFICATTION =
             "cloud_provider_pending_notification";
     private static final String PREFS_KEY_CLOUD_PREFIX = "cloud_provider:";
@@ -90,14 +87,6 @@
     public static final String LOCAL_PICKER_PROVIDER_AUTHORITY =
             "com.android.providers.media.photopicker";
 
-    public static final String PROP_USE_ALLOWED_CLOUD_PROVIDERS =
-            "persist.sys.photopicker.use_allowed_cloud_providers";
-    public static final String ALLOWED_CLOUD_PROVIDERS_KEY = "allowed_cloud_providers";
-
-    private static final String DEFAULT_CLOUD_PROVIDER_AUTHORITY = null;
-    private static final String DEFAULT_CLOUD_PROVIDER_PKGNAME = null;
-    private static final int DEFAULT_CLOUD_PROVIDER_UID = -1;
-
     private static final int SYNC_TYPE_NONE = 0;
     private static final int SYNC_TYPE_MEDIA_INCREMENTAL = 1;
     private static final int SYNC_TYPE_MEDIA_FULL = 2;
@@ -126,14 +115,7 @@
     private CloudProviderInfo mCloudProviderInfo;
 
     public PickerSyncController(Context context, PickerDbFacade dbFacade,
-            MediaProvider mediaProvider) {
-        this(context, dbFacade, LOCAL_PICKER_PROVIDER_AUTHORITY, mediaProvider.getIntDeviceConfig(
-                        DeviceConfig.NAMESPACE_STORAGE, PROP_DEFAULT_SYNC_DELAY_MS, 5000));
-    }
-
-    @VisibleForTesting
-    PickerSyncController(Context context, PickerDbFacade dbFacade,
-            String localProvider, long syncDelayMs) {
+            String localProvider, String allowedCloudProviders, long syncDelayMs) {
         mContext = context;
         mSyncPrefs = mContext.getSharedPreferences(PICKER_SYNC_PREFS_FILE_NAME,
                 Context.MODE_PRIVATE);
@@ -144,30 +126,23 @@
         mSyncDelayMs = syncDelayMs;
         mSyncAllMediaCallback = this::syncAllMedia;
 
-        final String cloudProviderAuthority = mUserPrefs.getString(
-                PREFS_KEY_CLOUD_PROVIDER_AUTHORITY,
-                DEFAULT_CLOUD_PROVIDER_AUTHORITY);
-        final String cloudProviderPackageName = mUserPrefs.getString(
-                PREFS_KEY_CLOUD_PROVIDER_PKGNAME,
-                DEFAULT_CLOUD_PROVIDER_PKGNAME);
-        final int cloudProviderUid = mUserPrefs.getInt(PREFS_KEY_CLOUD_PROVIDER_UID,
-                DEFAULT_CLOUD_PROVIDER_UID);
+        final String cachedAuthority = mUserPrefs.getString(
+                PREFS_KEY_CLOUD_PROVIDER_AUTHORITY, null);
 
-        if (SystemProperties.getBoolean(PROP_USE_ALLOWED_CLOUD_PROVIDERS, false)) {
-            mAllowedCloudProviders = getAllowedCloudProviders();
+        mAllowedCloudProviders = parseAllowedCloudProviders(allowedCloudProviders);
+
+        final CloudProviderInfo defaultInfo = getDefaultCloudProviderInfo(cachedAuthority);
+
+        if (Objects.equals(defaultInfo.authority, cachedAuthority)) {
+            // Just set it without persisting since it's not changing and persisting would
+            // notify the user that cloud media is now available
+            mCloudProviderInfo = defaultInfo;
         } else {
-            mAllowedCloudProviders = new ArraySet<>();
+            // Persist it so that we notify the user that cloud media is now available
+            persistCloudProviderInfo(defaultInfo);
         }
 
-        if (cloudProviderAuthority == null) {
-            // TODO: Only get default if it wasn't set by the user
-            final CloudProviderInfo defaultCloudProviderInfo = getDefaultCloudProviderInfo();
-            Log.i(TAG, "Cloud provider is set to Default " + defaultCloudProviderInfo.authority);
-            setCloudProviderInfo(defaultCloudProviderInfo);
-        } else {
-            mCloudProviderInfo = new CloudProviderInfo(cloudProviderAuthority,
-                cloudProviderPackageName, cloudProviderUid);
-        }
+        Log.d(TAG, "Initialized cloud provider to: " + mCloudProviderInfo.authority);
     }
 
     /**
@@ -221,7 +196,7 @@
      * Returns the supported cloud {@link CloudMediaProvider} infos.
      */
     public CloudProviderInfo getCloudProviderInfo(String authority) {
-        for (CloudProviderInfo info : getSupportedCloudProviders()) {
+        for (CloudProviderInfo info : getSupportedCloudProviders(/* ignoreAllowList */ false)) {
             if (info.authority.equals(authority)) {
                 return info;
             }
@@ -235,15 +210,12 @@
      */
     @VisibleForTesting
     List<CloudProviderInfo> getSupportedCloudProviders() {
+        return getSupportedCloudProviders(/* ignoreAllowList */ false);
+    }
+
+    private List<CloudProviderInfo> getSupportedCloudProviders(boolean ignoreAllowList) {
         final List<CloudProviderInfo> result = new ArrayList<>();
 
-        final boolean useAllowedCloudProviders =
-            SystemProperties.getBoolean(PROP_USE_ALLOWED_CLOUD_PROVIDERS, false);
-
-        if (useAllowedCloudProviders && mAllowedCloudProviders.isEmpty()) {
-            return result;
-        }
-
         final PackageManager pm = mContext.getPackageManager();
         final Intent intent = new Intent(CloudMediaProviderContract.PROVIDER_INTERFACE);
         final List<ResolveInfo> providers = pm.queryIntentContentProviders(intent, /* flags */ 0);
@@ -253,8 +225,8 @@
             if (providerInfo.authority != null
                     && CloudMediaProviderContract.MANAGE_CLOUD_MEDIA_PROVIDERS_PERMISSION.equals(
                             providerInfo.readPermission)
-                    && (!useAllowedCloudProviders
-                        || mAllowedCloudProviders.contains(providerInfo.authority))) {
+                    && (ignoreAllowList
+                            || mAllowedCloudProviders.contains(providerInfo.authority))) {
                 result.add(new CloudProviderInfo(providerInfo.authority,
                                 providerInfo.applicationInfo.packageName,
                                 providerInfo.applicationInfo.uid));
@@ -287,7 +259,7 @@
         if (authority == null || !newProviderInfo.isEmpty()) {
             synchronized (mLock) {
                 final String oldAuthority = mCloudProviderInfo.authority;
-                setCloudProviderInfo(newProviderInfo);
+                persistCloudProviderInfo(newProviderInfo);
                 resetCachedMediaCollectionInfo(newProviderInfo.authority);
 
                 // Disable cloud provider queries on the db until next sync
@@ -307,6 +279,20 @@
         return false;
     }
 
+    /**
+     * Set cloud provider and update allowed cloud providers
+     */
+    @VisibleForTesting
+    public void forceSetCloudProvider(String authority) {
+        if (authority == null) {
+            mAllowedCloudProviders.clear();
+        } else {
+            mAllowedCloudProviders.add(authority);
+        }
+
+        setCloudProvider(authority);
+    }
+
     public String getCloudProvider() {
         synchronized (mLock) {
             return mCloudProviderInfo.authority;
@@ -351,7 +337,11 @@
             return true;
         }
 
-        final List<CloudProviderInfo> infos = getSupportedCloudProviders();
+        // TODO(b/232738117): Enforce allow list here. This works around some CTS failure late in
+        // Android T. The current implementation is fine since cloud providers is only supported
+        // for app developers testing.
+        final List<CloudProviderInfo> infos = getSupportedCloudProviders(
+                /* ignoreAllowList */ true);
         for (CloudProviderInfo info : infos) {
             if (info.uid == uid && info.authority.equals(authority)) {
                 return true;
@@ -398,7 +388,7 @@
         final boolean hasPendingNotification = mUserPrefs.getBoolean(
                 PREFS_KEY_CLOUD_PROVIDER_PENDING_NOTIFICATTION, false);
 
-        if (!hasPendingNotification || (packageName == DEFAULT_CLOUD_PROVIDER_PKGNAME)) {
+        if (!hasPendingNotification || (packageName == null)) {
             Log.d(TAG, "No pending UI notification");
             return;
         }
@@ -563,26 +553,36 @@
         }
     }
 
-    private void setCloudProviderInfo(CloudProviderInfo info) {
+    private void persistCloudProviderInfo(CloudProviderInfo info) {
         synchronized (mLock) {
             mCloudProviderInfo = info;
         }
 
+        final String authority = info.authority;
         final SharedPreferences.Editor editor = mUserPrefs.edit();
 
         if (info.isEmpty()) {
             editor.remove(PREFS_KEY_CLOUD_PROVIDER_AUTHORITY);
-            editor.remove(PREFS_KEY_CLOUD_PROVIDER_PKGNAME);
-            editor.remove(PREFS_KEY_CLOUD_PROVIDER_UID);
             editor.putBoolean(PREFS_KEY_CLOUD_PROVIDER_PENDING_NOTIFICATTION, false);
         } else {
-            editor.putString(PREFS_KEY_CLOUD_PROVIDER_AUTHORITY, info.authority);
-            editor.putString(PREFS_KEY_CLOUD_PROVIDER_PKGNAME, info.packageName);
-            editor.putInt(PREFS_KEY_CLOUD_PROVIDER_UID, info.uid);
+            editor.putString(PREFS_KEY_CLOUD_PROVIDER_AUTHORITY, authority);
             editor.putBoolean(PREFS_KEY_CLOUD_PROVIDER_PENDING_NOTIFICATTION, true);
         }
 
         editor.apply();
+
+        if (SdkLevel.isAtLeastT()) {
+            try {
+                StorageManager sm = mContext.getSystemService(StorageManager.class);
+                sm.setCloudMediaProvider(authority);
+            } catch (SecurityException e) {
+                // When run as part of the unit tests, the notification fails because only the
+                // MediaProvider uid can notify
+                Log.w(TAG, "Failed to notify the system of cloud provider update to: " + authority);
+            }
+        }
+
+        Log.d(TAG, "Updated cloud provider to: " + authority);
     }
 
     private void cacheMediaCollectionInfo(String authority, Bundle bundle) {
@@ -724,8 +724,9 @@
                 + totalRowcount + ". Cursor count: " + cursorCount);
     }
 
-    private CloudProviderInfo getDefaultCloudProviderInfo() {
-        final List<CloudProviderInfo> infos = getSupportedCloudProviders();
+    private CloudProviderInfo getDefaultCloudProviderInfo(String cachedProvider) {
+        final List<CloudProviderInfo> infos =
+                getSupportedCloudProviders(/* ignoreAllowList */ false);
 
         if (infos.size() == 1) {
             Log.i(TAG, "Only 1 cloud provider found, hence "
@@ -734,7 +735,16 @@
         } else {
             final String defaultCloudProviderAuthority = StringUtils.getStringConfig(
                 mContext, R.string.config_default_cloud_provider_authority);
-            Log.i(TAG, "Default cloud provider to be used is " + defaultCloudProviderAuthority);
+            Log.i(TAG, "Found multiple cloud providers but OEM default is: "
+                    + defaultCloudProviderAuthority);
+
+            if (cachedProvider != null) {
+                for (CloudProviderInfo info : infos) {
+                    if (info.authority.equals(defaultCloudProviderAuthority)) {
+                        return info;
+                    }
+                }
+            }
 
             if (defaultCloudProviderAuthority != null) {
                 for (CloudProviderInfo info : infos) {
@@ -749,10 +759,9 @@
         return CloudProviderInfo.EMPTY;
     }
 
-    private Set<String> getAllowedCloudProviders() {
+    private Set<String> parseAllowedCloudProviders(String config) {
         Set<String> allowedProviders = new ArraySet<>();
-        final String[] allowedProvidersConfig = DeviceConfigUtils.getStringDeviceConfig(
-                ALLOWED_CLOUD_PROVIDERS_KEY, "").split(",");
+        final String[] allowedProvidersConfig = config.split(",");
 
         if (allowedProvidersConfig.length == 0 || allowedProvidersConfig[0].isEmpty()) {
             Log.i(TAG, "Empty allowed cloud providers");
@@ -812,9 +821,9 @@
         private final int uid;
 
         private CloudProviderInfo() {
-            this.authority = DEFAULT_CLOUD_PROVIDER_AUTHORITY;
-            this.packageName = DEFAULT_CLOUD_PROVIDER_PKGNAME;
-            this.uid = DEFAULT_CLOUD_PROVIDER_UID;
+            this.authority = null;
+            this.packageName = null;
+            this.uid = -1;
         }
 
         CloudProviderInfo(String authority, String packageName, int uid) {
diff --git a/src/com/android/providers/media/util/DeviceConfigUtils.java b/src/com/android/providers/media/util/DeviceConfigUtils.java
deleted file mode 100644
index 7740d1d..0000000
--- a/src/com/android/providers/media/util/DeviceConfigUtils.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.providers.media.util;
-
-import static com.android.providers.media.util.Logging.TAG;
-
-import android.os.Binder;
-import android.provider.DeviceConfig;
-import android.util.Log;
-import com.android.modules.utils.build.SdkLevel;
-
-public class DeviceConfigUtils {
-
-    public static String getStringDeviceConfig(String key, String defaultValue) {
-        if (!canReadDeviceConfig(key, defaultValue)) {
-            return defaultValue;
-        }
-
-        final long token = Binder.clearCallingIdentity();
-        try {
-            return DeviceConfig.getString(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT, key,
-                    defaultValue);
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-    }
-
-    private static <T> boolean canReadDeviceConfig(String key, T defaultValue) {
-        if (SdkLevel.isAtLeastS()) {
-            return true;
-        }
-
-        Log.w(TAG, "Cannot read device config before Android S. Returning defaultValue: "
-                + defaultValue + " for key: " + key);
-        return false;
-    }
-}
diff --git a/tests/src/com/android/providers/media/photopicker/PickerDataLayerTest.java b/tests/src/com/android/providers/media/photopicker/PickerDataLayerTest.java
index 47033cc..6931cd6 100644
--- a/tests/src/com/android/providers/media/photopicker/PickerDataLayerTest.java
+++ b/tests/src/com/android/providers/media/photopicker/PickerDataLayerTest.java
@@ -119,8 +119,10 @@
 
         mDbHelper = new PickerDatabaseHelper(mContext, DB_NAME, DB_VERSION_1);
         mFacade = new PickerDbFacade(mContext, LOCAL_PROVIDER_AUTHORITY, mDbHelper);
+        final String allowedCloudProviders = CLOUD_PRIMARY_PROVIDER_AUTHORITY + ","
+                + CLOUD_SECONDARY_PROVIDER_AUTHORITY;
         mController = new PickerSyncController(mContext, mFacade, LOCAL_PROVIDER_AUTHORITY,
-                /* syncDelay */ 0);
+                allowedCloudProviders, /* syncDelay */ 0);
         mDataLayer = new PickerDataLayer(mContext, mFacade, mController);
 
         // Set cloud provider to null to discard
diff --git a/tests/src/com/android/providers/media/photopicker/PickerSyncControllerTest.java b/tests/src/com/android/providers/media/photopicker/PickerSyncControllerTest.java
index 224e252..53d6837 100644
--- a/tests/src/com/android/providers/media/photopicker/PickerSyncControllerTest.java
+++ b/tests/src/com/android/providers/media/photopicker/PickerSyncControllerTest.java
@@ -18,22 +18,21 @@
 
 import static com.android.providers.media.PickerProviderMediaGenerator.MediaGenerator;
 import static com.android.providers.media.photopicker.PickerSyncController.CloudProviderInfo;
+
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
-import android.content.SharedPreferences;
 import android.content.res.Resources;
-import android.content.res.Resources.NotFoundException;
 import android.database.Cursor;
 import android.os.Bundle;
 import android.os.Process;
 import android.os.SystemClock;
-import android.os.SystemProperties;
-import android.provider.CloudMediaProviderContract;
+import android.os.storage.StorageManager;
 import android.provider.CloudMediaProviderContract.MediaColumns;
 import android.provider.MediaStore;
 import android.util.Pair;
@@ -41,24 +40,20 @@
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.dx.mockito.inline.extended.ExtendedMockito;
 import com.android.modules.utils.BackgroundThread;
 import com.android.providers.media.PickerProviderMediaGenerator;
+import com.android.providers.media.R;
 import com.android.providers.media.photopicker.data.PickerDatabaseHelper;
 import com.android.providers.media.photopicker.data.PickerDbFacade;
-import com.android.providers.media.R;
-import com.android.providers.media.util.DeviceConfigUtils;
-
-import java.io.File;
-import java.util.List;
-import java.util.Objects;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.MockitoSession;
+
+import java.io.File;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 @RunWith(AndroidJUnit4.class)
 public class PickerSyncControllerTest {
@@ -129,8 +124,11 @@
 
         mDbHelper = new PickerDatabaseHelper(mContext, DB_NAME, DB_VERSION_1);
         mFacade = new PickerDbFacade(mContext, LOCAL_PROVIDER_AUTHORITY, mDbHelper);
+
+        final String allowedCloudProviders = CLOUD_PRIMARY_PROVIDER_AUTHORITY + ","
+                + CLOUD_SECONDARY_PROVIDER_AUTHORITY;
         mController = new PickerSyncController(mContext, mFacade, LOCAL_PROVIDER_AUTHORITY,
-                /* syncDelay */ 0);
+                allowedCloudProviders, /* syncDelay */ 0);
 
         // Set cloud provider to null to avoid trying to sync it during other tests
         // that might be using an IsolatedContext
@@ -609,57 +607,34 @@
 
     @Test
     public void testGetSupportedCloudProviders_useAllowList() {
-        MockitoSession mockSession = ExtendedMockito.mockitoSession()
-                .mockStatic(DeviceConfigUtils.class)
-                .mockStatic(SystemProperties.class)
-                .startMocking();
+        CloudProviderInfo primaryInfo = new CloudProviderInfo(CLOUD_PRIMARY_PROVIDER_AUTHORITY,
+                PACKAGE_NAME,
+                Process.myUid());
+        CloudProviderInfo secondaryInfo = new CloudProviderInfo(
+                CLOUD_SECONDARY_PROVIDER_AUTHORITY,
+                PACKAGE_NAME,
+                Process.myUid());
 
-        try {
-            when(SystemProperties.getBoolean(
-                PickerSyncController.PROP_USE_ALLOWED_CLOUD_PROVIDERS, false))
-                .thenReturn(true);
+        // 1. Allow list is subset of existing providers list
+        PickerSyncController controller = new PickerSyncController(mContext, mFacade,
+                LOCAL_PROVIDER_AUTHORITY, CLOUD_PRIMARY_PROVIDER_AUTHORITY, SYNC_DELAY_MS);
+        List<CloudProviderInfo> providers = controller.getSupportedCloudProviders();
+        assertThat(providers).containsExactly(primaryInfo);
 
-            CloudProviderInfo primaryInfo = new CloudProviderInfo(CLOUD_PRIMARY_PROVIDER_AUTHORITY,
-                    PACKAGE_NAME,
-                    Process.myUid());
-            CloudProviderInfo secondaryInfo = new CloudProviderInfo(
-                    CLOUD_SECONDARY_PROVIDER_AUTHORITY,
-                    PACKAGE_NAME,
-                    Process.myUid());
+        String allowedCloudProviders = CLOUD_PRIMARY_PROVIDER_AUTHORITY + ","
+                + CLOUD_SECONDARY_PROVIDER_AUTHORITY;
+        controller = new PickerSyncController(mContext, mFacade,
+                LOCAL_PROVIDER_AUTHORITY, allowedCloudProviders, SYNC_DELAY_MS);
+        providers = controller.getSupportedCloudProviders();
+        assertThat(providers).containsExactly(primaryInfo, secondaryInfo);
 
-            // 1. Allow list is subset of existing providers list
-            when(DeviceConfigUtils.getStringDeviceConfig(
-                    PickerSyncController.ALLOWED_CLOUD_PROVIDERS_KEY, ""))
-                .thenReturn(CLOUD_PRIMARY_PROVIDER_AUTHORITY);
-            PickerSyncController controller = new PickerSyncController(mContext, mFacade,
-                    LOCAL_PROVIDER_AUTHORITY, SYNC_DELAY_MS);
-            List<CloudProviderInfo> providers = controller.getSupportedCloudProviders();
-            assertThat(providers).containsExactly(primaryInfo);
-
-            // 2. Allow list is exactly the same as existing providers list
-            when(DeviceConfigUtils.getStringDeviceConfig(
-                    PickerSyncController.ALLOWED_CLOUD_PROVIDERS_KEY, ""))
-                .thenReturn(CLOUD_PRIMARY_PROVIDER_AUTHORITY
-                            + "," + CLOUD_SECONDARY_PROVIDER_AUTHORITY);
-            controller = new PickerSyncController(mContext, mFacade,
-                    LOCAL_PROVIDER_AUTHORITY, SYNC_DELAY_MS);
-            providers = controller.getSupportedCloudProviders();
-            assertThat(providers).containsExactly(primaryInfo, secondaryInfo);
-
-            // 3. Allow list containing existing providers list + others
-            when(DeviceConfigUtils.getStringDeviceConfig(
-                    PickerSyncController.ALLOWED_CLOUD_PROVIDERS_KEY, ""))
-                .thenReturn(CLOUD_PRIMARY_PROVIDER_AUTHORITY
-                            + "," + CLOUD_SECONDARY_PROVIDER_AUTHORITY
-                            + "," + CLOUD_PRIMARY_PROVIDER_AUTHORITY + "invalid");
-            controller = new PickerSyncController(mContext, mFacade,
-                    LOCAL_PROVIDER_AUTHORITY, SYNC_DELAY_MS);
-            providers = controller.getSupportedCloudProviders();
-            assertThat(providers).containsExactly(primaryInfo, secondaryInfo);
-        }
-        finally {
-            mockSession.finishMocking();
-        }
+        allowedCloudProviders = CLOUD_PRIMARY_PROVIDER_AUTHORITY
+                + "," + CLOUD_SECONDARY_PROVIDER_AUTHORITY
+                + "," + CLOUD_PRIMARY_PROVIDER_AUTHORITY + "invalid";
+        controller = new PickerSyncController(mContext, mFacade,
+                LOCAL_PROVIDER_AUTHORITY, allowedCloudProviders, SYNC_DELAY_MS);
+        providers = controller.getSupportedCloudProviders();
+        assertThat(providers).containsExactly(primaryInfo, secondaryInfo);
     }
 
     @Test
@@ -712,7 +687,7 @@
     @Test
     public void testNotifyMediaEvent() {
         PickerSyncController controller = new PickerSyncController(mContext, mFacade,
-                LOCAL_PROVIDER_AUTHORITY, SYNC_DELAY_MS);
+                LOCAL_PROVIDER_AUTHORITY, "", SYNC_DELAY_MS);
 
         // 1. Add media and notify
         addMedia(mLocalMediaGenerator, LOCAL_ONLY_1);
@@ -737,7 +712,7 @@
         PickerDbFacade facade = new PickerDbFacade(mContext, LOCAL_PROVIDER_AUTHORITY,
                 dbHelper);
         PickerSyncController controller = new PickerSyncController(mContext, facade,
-                LOCAL_PROVIDER_AUTHORITY, /* syncDelay */ 0);
+                LOCAL_PROVIDER_AUTHORITY, "", /* syncDelay */ 0);
 
         addMedia(mLocalMediaGenerator, LOCAL_ONLY_1);
         controller.syncAllMedia();
@@ -756,7 +731,7 @@
 
         facade = new PickerDbFacade(mContext, LOCAL_PROVIDER_AUTHORITY, dbHelper);
         controller = new PickerSyncController(mContext, facade,
-                LOCAL_PROVIDER_AUTHORITY, /* syncDelay */ 0);
+                LOCAL_PROVIDER_AUTHORITY, "", /* syncDelay */ 0);
 
         // Initially empty db
         try (Cursor cr = queryMedia(facade)) {
@@ -779,7 +754,7 @@
         PickerDbFacade facade = new PickerDbFacade(mContext, LOCAL_PROVIDER_AUTHORITY,
                 dbHelperV1);
         PickerSyncController controller = new PickerSyncController(mContext, facade,
-                LOCAL_PROVIDER_AUTHORITY, SYNC_DELAY_MS);
+                LOCAL_PROVIDER_AUTHORITY, "", SYNC_DELAY_MS);
 
         addMedia(mLocalMediaGenerator, LOCAL_ONLY_1);
         controller.syncAllMedia();
@@ -795,7 +770,7 @@
         PickerDatabaseHelper dbHelperV2 = new PickerDatabaseHelper(mContext, DB_NAME, DB_VERSION_2);
         facade = new PickerDbFacade(mContext, LOCAL_PROVIDER_AUTHORITY, dbHelperV2);
         controller = new PickerSyncController(mContext, facade,
-                LOCAL_PROVIDER_AUTHORITY, SYNC_DELAY_MS);
+                LOCAL_PROVIDER_AUTHORITY, "", SYNC_DELAY_MS);
 
         // Initially empty db
         try (Cursor cr = queryMedia(facade)) {
@@ -818,7 +793,7 @@
         PickerDbFacade facade = new PickerDbFacade(mContext, LOCAL_PROVIDER_AUTHORITY,
                 dbHelperV2);
         PickerSyncController controller = new PickerSyncController(mContext, facade,
-                LOCAL_PROVIDER_AUTHORITY, SYNC_DELAY_MS);
+                LOCAL_PROVIDER_AUTHORITY, "", SYNC_DELAY_MS);
 
         addMedia(mLocalMediaGenerator, LOCAL_ONLY_1);
         controller.syncAllMedia();
@@ -835,7 +810,7 @@
         facade = new PickerDbFacade(mContext, LOCAL_PROVIDER_AUTHORITY,
                 dbHelperV1);
         controller = new PickerSyncController(mContext, facade,
-                LOCAL_PROVIDER_AUTHORITY, SYNC_DELAY_MS);
+                LOCAL_PROVIDER_AUTHORITY, "", SYNC_DELAY_MS);
 
         // Initially empty db
         try (Cursor cr = queryMedia(facade)) {
@@ -967,7 +942,7 @@
         PickerDbFacade facade = new PickerDbFacade(mContext, LOCAL_PROVIDER_AUTHORITY,
                 dbHelperV1);
         PickerSyncController controller = new PickerSyncController(mContext, facade,
-                LOCAL_PROVIDER_AUTHORITY, SYNC_DELAY_MS);
+                LOCAL_PROVIDER_AUTHORITY, CLOUD_PRIMARY_PROVIDER_AUTHORITY, SYNC_DELAY_MS);
 
         controller.setCloudProvider(CLOUD_PRIMARY_PROVIDER_AUTHORITY);
         assertThat(controller.getCloudProvider()).isEqualTo(CLOUD_PRIMARY_PROVIDER_AUTHORITY);
@@ -978,7 +953,7 @@
         facade = new PickerDbFacade(mContext, LOCAL_PROVIDER_AUTHORITY,
                 dbHelperV2);
         controller = new PickerSyncController(mContext, facade,
-                LOCAL_PROVIDER_AUTHORITY, SYNC_DELAY_MS);
+                LOCAL_PROVIDER_AUTHORITY, CLOUD_PRIMARY_PROVIDER_AUTHORITY, SYNC_DELAY_MS);
 
         assertThat(controller.getCloudProvider()).isEqualTo(CLOUD_PRIMARY_PROVIDER_AUTHORITY);
     }
@@ -1077,14 +1052,19 @@
 
         when(mockContext.getResources()).thenReturn(mockResources);
         when(mockContext.getPackageManager()).thenReturn(mContext.getPackageManager());
+        when(mockContext.getSystemService(StorageManager.class))
+                .thenReturn(mContext.getSystemService(StorageManager.class));
         when(mockContext.getSharedPreferences(anyString(), anyInt())).thenAnswer(i -> {
             return mContext.getSharedPreferences((String)i.getArgument(0), (int)i.getArgument(1));
         });
         when(mockResources.getString(R.string.config_default_cloud_provider_authority))
                 .thenReturn(defaultProvider);
 
+        final String allowedCloudProviders = CLOUD_PRIMARY_PROVIDER_AUTHORITY + ","
+                + CLOUD_SECONDARY_PROVIDER_AUTHORITY;
+
         return new PickerSyncController(mockContext, mFacade,
-                LOCAL_PROVIDER_AUTHORITY, SYNC_DELAY_MS);
+                LOCAL_PROVIDER_AUTHORITY, allowedCloudProviders, SYNC_DELAY_MS);
     }
 
     private static void assertCursor(Cursor cursor, String id, String expectedAuthority) {