Use DeviceConfig property for default value of clipboard access notification setting.

This uses a new DeviceConfig property for the default value of the
setting that controls whether a notification is shown when an app
accesses clipboard.

Bug: 182349993
Test: manual, "adb shell device_config put clipboard
show_access_notifications false" and observe setting changes when
not set manually; also check notifications shown when expected.
Test: make RunSettingsRoboTests ROBOTEST_FILTER=
"com.android.settings.privacy.ShowClipAccessNotificationPreferenceControllerTest"

Change-Id: I452b1850ecc5fefb2ca9476d249866b32c885478
diff --git a/src/com/android/settings/privacy/ShowClipAccessNotificationPreferenceController.java b/src/com/android/settings/privacy/ShowClipAccessNotificationPreferenceController.java
index 4622431..cf05ff4 100644
--- a/src/com/android/settings/privacy/ShowClipAccessNotificationPreferenceController.java
+++ b/src/com/android/settings/privacy/ShowClipAccessNotificationPreferenceController.java
@@ -16,33 +16,47 @@
 
 package com.android.settings.privacy;
 
+import android.content.ClipboardManager;
 import android.content.Context;
+import android.provider.DeviceConfig;
 import android.provider.Settings;
 
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.OnLifecycleEvent;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
 import com.android.settings.core.TogglePreferenceController;
 
 /**
  * Controller for preference to toggle whether clipboard access notifications should be shown.
  */
-public class ShowClipAccessNotificationPreferenceController extends TogglePreferenceController {
+public class ShowClipAccessNotificationPreferenceController
+        extends TogglePreferenceController implements LifecycleObserver {
 
     private static final String KEY_SHOW_CLIP_ACCESS_NOTIFICATION = "show_clip_access_notification";
 
+    private final DeviceConfig.OnPropertiesChangedListener mDeviceConfigListener =
+            properties -> updateConfig();
+    private boolean mDefault;
+    private Preference mPreference;
+
     public ShowClipAccessNotificationPreferenceController(Context context) {
         super(context, KEY_SHOW_CLIP_ACCESS_NOTIFICATION);
+        updateConfig();
     }
 
     @Override
     public boolean isChecked() {
-        // TODO(b/182349993) Retrieve default value from DeviceConfig.
         return Settings.Secure.getInt(mContext.getContentResolver(),
-                Settings.Secure.CLIPBOARD_SHOW_ACCESS_NOTIFICATIONS, 1) != 0;
+                Settings.Secure.CLIPBOARD_SHOW_ACCESS_NOTIFICATIONS, (mDefault ? 1 : 0)) != 0;
     }
 
     @Override
     public boolean setChecked(boolean isChecked) {
         Settings.Secure.putInt(mContext.getContentResolver(),
-                Settings.Secure.CLIPBOARD_SHOW_ACCESS_NOTIFICATIONS, isChecked ? 1 : 0);
+                Settings.Secure.CLIPBOARD_SHOW_ACCESS_NOTIFICATIONS, (isChecked ? 1 : 0));
         return true;
     }
 
@@ -51,4 +65,35 @@
         return AVAILABLE;
     }
 
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+
+        mPreference = screen.findPreference(getPreferenceKey());
+    }
+
+    /**
+     * Registers a DeviceConfig listener on start.
+     */
+    @OnLifecycleEvent(Lifecycle.Event.ON_START)
+    public void onStart() {
+        DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_CLIPBOARD,
+                mContext.getMainExecutor(), mDeviceConfigListener);
+    }
+
+    /**
+     * Removes the DeviceConfig listener on stop.
+     */
+    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
+    public void onStop() {
+        DeviceConfig.removeOnPropertiesChangedListener(mDeviceConfigListener);
+    }
+
+    private void updateConfig() {
+        mDefault = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_CLIPBOARD,
+                ClipboardManager.DEVICE_CONFIG_SHOW_ACCESS_NOTIFICATIONS,
+                ClipboardManager.DEVICE_CONFIG_DEFAULT_SHOW_ACCESS_NOTIFICATIONS);
+        updateState(mPreference);
+    }
+
 }
diff --git a/tests/robotests/src/com/android/settings/privacy/ShowClipAccessNotificationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/privacy/ShowClipAccessNotificationPreferenceControllerTest.java
index c707cd6..fdf81e7 100644
--- a/tests/robotests/src/com/android/settings/privacy/ShowClipAccessNotificationPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/privacy/ShowClipAccessNotificationPreferenceControllerTest.java
@@ -18,8 +18,10 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import android.content.ClipboardManager;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.provider.DeviceConfig;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
 
@@ -27,14 +29,18 @@
 import androidx.preference.PreferenceScreen;
 import androidx.test.core.app.ApplicationProvider;
 
+import com.android.settings.testutils.shadow.ShadowDeviceConfig;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
 
 @RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowDeviceConfig.class})
 public class ShowClipAccessNotificationPreferenceControllerTest {
 
     @Mock
@@ -54,20 +60,48 @@
     }
 
     @Test
-    public void isChecked_settingIsOff_shouldReturnFalse() throws Exception {
+    public void isChecked_settingIsOff_shouldReturnFalse() {
         setProperty(0);
 
         assertThat(mController.isChecked()).isFalse();
     }
 
     @Test
-    public void isChecked_settingIsOn_shouldReturnTrue() throws Exception {
+    public void isChecked_settingIsOn_shouldReturnTrue() {
         setProperty(1);
 
         assertThat(mController.isChecked()).isTrue();
     }
 
     @Test
+    public void isChecked_settingIsUnset_deviceConfigProvidesDefaultOfTrue() {
+        clearProperty();
+
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_CLIPBOARD,
+                ClipboardManager.DEVICE_CONFIG_SHOW_ACCESS_NOTIFICATIONS,
+                "true", false);
+
+        ShowClipAccessNotificationPreferenceController controller =
+                new ShowClipAccessNotificationPreferenceController(mContext);
+
+        assertThat(controller.isChecked()).isTrue();
+    }
+
+    @Test
+    public void isChecked_settingIsUnset_deviceConfigProvidesDefaultOfFalse() {
+        clearProperty();
+
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_CLIPBOARD,
+                ClipboardManager.DEVICE_CONFIG_SHOW_ACCESS_NOTIFICATIONS,
+                "false", false);
+
+        ShowClipAccessNotificationPreferenceController controller =
+                new ShowClipAccessNotificationPreferenceController(mContext);
+
+        assertThat(controller.isChecked()).isFalse();
+    }
+
+    @Test
     public void onPreferenceChange_turnOn_shouldChangeSettingTo1() throws Exception {
         setProperty(0);
 
@@ -93,6 +127,12 @@
                 contentResolver, Settings.Secure.CLIPBOARD_SHOW_ACCESS_NOTIFICATIONS, newValue);
     }
 
+    private void clearProperty() {
+        final ContentResolver contentResolver = mContext.getContentResolver();
+        Settings.Secure.putString(
+                contentResolver, Settings.Secure.CLIPBOARD_SHOW_ACCESS_NOTIFICATIONS, null);
+    }
+
     private void assertProperty(int expectedValue) throws SettingNotFoundException {
         final ContentResolver contentResolver = mContext.getContentResolver();
         assertThat(Settings.Secure.getInt(