Merge "Add new color mode setting" into oc-mr1-dev
diff --git a/res/xml/display_settings.xml b/res/xml/display_settings.xml
index 27ef869..87d3e5e 100644
--- a/res/xml/display_settings.xml
+++ b/res/xml/display_settings.xml
@@ -64,9 +64,11 @@
         android:key="auto_rotate"
         android:title="@string/accelerometer_title" />
 
-    <SwitchPreference
+    <Preference
         android:key="color_mode"
-        android:title="@string/color_mode_title" />
+        android:title="@string/color_mode_title"
+        android:fragment="com.android.settings.display.ColorModePreferenceFragment"
+        settings:keywords="@string/keywords_color_mode" />
 
     <Preference
         android:key="font_size"
diff --git a/src/com/android/settings/display/ColorModePreferenceController.java b/src/com/android/settings/display/ColorModePreferenceController.java
index 2d669d0..2ab2ec9 100644
--- a/src/com/android/settings/display/ColorModePreferenceController.java
+++ b/src/com/android/settings/display/ColorModePreferenceController.java
@@ -18,36 +18,24 @@
 import android.os.Parcel;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.os.SystemProperties;
-import android.support.v7.preference.Preference;
-import android.support.v7.preference.TwoStatePreference;
 import android.util.Log;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.settings.core.PreferenceControllerMixin;
 import com.android.settingslib.core.AbstractPreferenceController;
 
 public class ColorModePreferenceController extends AbstractPreferenceController implements
-        PreferenceControllerMixin, Preference.OnPreferenceChangeListener {
+        PreferenceControllerMixin {
     private static final String TAG = "ColorModePreference";
-
     private static final String KEY_COLOR_MODE = "color_mode";
 
-    @VisibleForTesting
-    static final float COLOR_SATURATION_DEFAULT = 1.0f;
-    @VisibleForTesting
-    static final float COLOR_SATURATION_VIVID = 1.1f;
+    private static final int SURFACE_FLINGER_TRANSACTION_QUERY_WIDE_COLOR = 1024;
 
-    private static final int SURFACE_FLINGER_TRANSACTION_SATURATION = 1022;
-    @VisibleForTesting
-    static final String PERSISTENT_PROPERTY_SATURATION = "persist.sys.sf.color_saturation";
-
-    private final IBinder mSurfaceFlinger;
     private final ConfigurationWrapper mConfigWrapper;
 
     public ColorModePreferenceController(Context context) {
         super(context);
-        mSurfaceFlinger = ServiceManager.getService("SurfaceFlinger");
-        mConfigWrapper = new ConfigurationWrapper(context);
+        mConfigWrapper = new ConfigurationWrapper();
     }
 
     @Override
@@ -56,64 +44,35 @@
     }
 
     @Override
-    public void updateState(Preference preference) {
-        TwoStatePreference colorMode = (TwoStatePreference) preference;
-        colorMode.setChecked(getSaturationValue() > 1.0f);
-    }
-
-    @Override
     public boolean isAvailable() {
         return mConfigWrapper.isScreenWideColorGamut();
     }
 
-    @Override
-    public boolean onPreferenceChange(Preference preference, Object newValue) {
-        float saturation = (boolean) newValue
-                ? COLOR_SATURATION_VIVID : COLOR_SATURATION_DEFAULT;
-
-        SystemProperties.set(PERSISTENT_PROPERTY_SATURATION, Float.toString(saturation));
-        applySaturation(saturation);
-
-        return true;
-    }
-
-    /**
-     * Propagates the provided saturation to the SurfaceFlinger.
-     */
-    private void applySaturation(float saturation) {
-        if (mSurfaceFlinger != null) {
-            final Parcel data = Parcel.obtain();
-            data.writeInterfaceToken("android.ui.ISurfaceComposer");
-            data.writeFloat(saturation);
-            try {
-                mSurfaceFlinger.transact(SURFACE_FLINGER_TRANSACTION_SATURATION, data, null, 0);
-            } catch (RemoteException ex) {
-                Log.e(TAG, "Failed to set saturation", ex);
-            } finally {
-                data.recycle();
-            }
-        }
-    }
-
-    private static float getSaturationValue() {
-        try {
-            return Float.parseFloat(SystemProperties.get(
-                    PERSISTENT_PROPERTY_SATURATION, Float.toString(COLOR_SATURATION_DEFAULT)));
-        } catch (NumberFormatException e) {
-            return COLOR_SATURATION_DEFAULT;
-        }
-    }
-
     @VisibleForTesting
     static class ConfigurationWrapper {
-        private final Context mContext;
+        private final IBinder mSurfaceFlinger;
 
-        ConfigurationWrapper(Context context) {
-            mContext = context;
+        ConfigurationWrapper() {
+            mSurfaceFlinger = ServiceManager.getService("SurfaceFlinger");
         }
 
         boolean isScreenWideColorGamut() {
-            return mContext.getResources().getConfiguration().isScreenWideColorGamut();
+            if (mSurfaceFlinger != null) {
+                final Parcel data = Parcel.obtain();
+                final Parcel reply = Parcel.obtain();
+                data.writeInterfaceToken("android.ui.ISurfaceComposer");
+                try {
+                    mSurfaceFlinger.transact(SURFACE_FLINGER_TRANSACTION_QUERY_WIDE_COLOR,
+                            data, reply, 0);
+                    return reply.readBoolean();
+                } catch (RemoteException ex) {
+                    Log.e(TAG, "Failed to query wide color support", ex);
+                } finally {
+                    data.recycle();
+                    reply.recycle();
+                }
+            }
+            return false;
         }
     }
 }
diff --git a/src/com/android/settings/display/ColorModePreferenceFragment.java b/src/com/android/settings/display/ColorModePreferenceFragment.java
new file mode 100644
index 0000000..7c8b841
--- /dev/null
+++ b/src/com/android/settings/display/ColorModePreferenceFragment.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2017 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.settings.display;
+
+import android.app.ActivityManager;
+import android.app.IActivityManager;
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemProperties;
+import android.support.annotation.VisibleForTesting;
+import android.util.Log;
+
+import com.android.internal.logging.nano.MetricsProto;
+
+import com.android.settings.R;
+import com.android.settings.widget.RadioButtonPickerFragment;
+
+import java.util.Arrays;
+import java.util.List;
+
+@SuppressWarnings("WeakerAccess")
+public class ColorModePreferenceFragment extends RadioButtonPickerFragment {
+    private static final String TAG = "ColorModePreferenceFragment";
+
+    @VisibleForTesting
+    static final float COLOR_SATURATION_NATURAL = 1.0f;
+    @VisibleForTesting
+    static final float COLOR_SATURATION_BOOSTED = 1.1f;
+
+    private static final int SURFACE_FLINGER_TRANSACTION_SATURATION = 1022;
+    private static final int SURFACE_FLINGER_TRANSACTION_NATIVE_MODE = 1023;
+
+    @VisibleForTesting
+    static final String PERSISTENT_PROPERTY_SATURATION = "persist.sys.sf.color_saturation";
+    @VisibleForTesting
+    static final String PERSISTENT_PROPERTY_NATIVE_MODE = "persist.sys.sf.native_mode";
+
+    @VisibleForTesting
+    static final String KEY_COLOR_MODE_NATURAL = "color_mode_natural";
+    @VisibleForTesting
+    static final String KEY_COLOR_MODE_BOOSTED = "color_mode_boosted";
+    @VisibleForTesting
+    static final String KEY_COLOR_MODE_SATURATED = "color_mode_saturated";
+
+    private IBinder mSurfaceFlinger;
+    private IActivityManager mActivityManager;
+
+    @Override
+    public void onAttach(Context context) {
+        super.onAttach(context);
+        mSurfaceFlinger = ServiceManager.getService("SurfaceFlinger");
+        mActivityManager = ActivityManager.getService();
+    }
+
+    @Override
+    protected List<? extends CandidateInfo> getCandidates() {
+        Context c = getContext();
+        return Arrays.asList(
+            new ColorModeCandidateInfo(c.getString(R.string.color_mode_option_natural),
+                    KEY_COLOR_MODE_NATURAL),
+            new ColorModeCandidateInfo(c.getString(R.string.color_mode_option_boosted),
+                    KEY_COLOR_MODE_BOOSTED),
+            new ColorModeCandidateInfo(c.getString(R.string.color_mode_option_saturated),
+                    KEY_COLOR_MODE_SATURATED)
+        );
+    }
+
+    @Override
+    protected String getDefaultKey() {
+        if (isNativeModeEnabled()) {
+            return KEY_COLOR_MODE_SATURATED;
+        }
+        if (getSaturationValue() > COLOR_SATURATION_NATURAL) {
+            return KEY_COLOR_MODE_BOOSTED;
+        }
+        return KEY_COLOR_MODE_NATURAL;
+    }
+
+    @Override
+    protected boolean setDefaultKey(String key) {
+        switch (key) {
+            case KEY_COLOR_MODE_NATURAL:
+                applySaturation(COLOR_SATURATION_NATURAL);
+                setNativeMode(false);
+                break;
+            case KEY_COLOR_MODE_BOOSTED:
+                applySaturation(COLOR_SATURATION_BOOSTED);
+                setNativeMode(false);
+                break;
+            case KEY_COLOR_MODE_SATURATED:
+                applySaturation(COLOR_SATURATION_NATURAL);
+                setNativeMode(true);
+                break;
+        }
+
+        updateConfiguration();
+
+        return true;
+    }
+
+    @VisibleForTesting
+    void updateConfiguration() {
+        try {
+            mActivityManager.updateConfiguration(null);
+        } catch (RemoteException e) {
+            Log.d(TAG, "Could not update configuration", e);
+        }
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return MetricsProto.MetricsEvent.COLOR_MODE_SETTINGS;
+    }
+
+    /**
+     * Propagates the provided saturation to the SurfaceFlinger.
+     */
+    private void applySaturation(float saturation) {
+        SystemProperties.set(PERSISTENT_PROPERTY_SATURATION, Float.toString(saturation));
+        if (mSurfaceFlinger != null) {
+            final Parcel data = Parcel.obtain();
+            data.writeInterfaceToken("android.ui.ISurfaceComposer");
+            data.writeFloat(saturation);
+            try {
+                mSurfaceFlinger.transact(SURFACE_FLINGER_TRANSACTION_SATURATION, data, null, 0);
+            } catch (RemoteException ex) {
+                Log.e(TAG, "Failed to set saturation", ex);
+            } finally {
+                data.recycle();
+            }
+        }
+    }
+
+    private static float getSaturationValue() {
+        try {
+            return Float.parseFloat(SystemProperties.get(
+                    PERSISTENT_PROPERTY_SATURATION, Float.toString(COLOR_SATURATION_NATURAL)));
+        } catch (NumberFormatException e) {
+            return COLOR_SATURATION_NATURAL;
+        }
+    }
+
+    /**
+     * Toggles native mode on/off in SurfaceFlinger.
+     */
+    private void setNativeMode(boolean enabled) {
+        SystemProperties.set(PERSISTENT_PROPERTY_NATIVE_MODE, enabled ? "1" : "0");
+        if (mSurfaceFlinger != null) {
+            final Parcel data = Parcel.obtain();
+            data.writeInterfaceToken("android.ui.ISurfaceComposer");
+            data.writeInt(enabled ? 1 : 0);
+            try {
+                mSurfaceFlinger.transact(SURFACE_FLINGER_TRANSACTION_NATIVE_MODE, data, null, 0);
+            } catch (RemoteException ex) {
+                Log.e(TAG, "Failed to set native mode", ex);
+            } finally {
+                data.recycle();
+            }
+        }
+    }
+
+    private static boolean isNativeModeEnabled() {
+        return SystemProperties.getBoolean(PERSISTENT_PROPERTY_NATIVE_MODE, false);
+    }
+
+    @VisibleForTesting
+    static class ColorModeCandidateInfo extends CandidateInfo {
+        private final CharSequence mLabel;
+        private final String mKey;
+
+        ColorModeCandidateInfo(CharSequence label, String key) {
+            super(true);
+            mLabel = label;
+            mKey = key;
+        }
+
+        @Override
+        public CharSequence loadLabel() {
+            return mLabel;
+        }
+
+        @Override
+        public Drawable loadIcon() {
+            return null;
+        }
+
+        @Override
+        public String getKey() {
+            return mKey;
+        }
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/display/ColorModePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/ColorModePreferenceControllerTest.java
deleted file mode 100644
index 00d910e..0000000
--- a/tests/robotests/src/com/android/settings/display/ColorModePreferenceControllerTest.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2017 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.settings.display;
-
-import android.content.Context;
-import android.os.IBinder;
-import android.support.v14.preference.SwitchPreference;
-import android.support.v7.preference.PreferenceScreen;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settings.TestConfig;
-import com.android.settings.testutils.shadow.SettingsShadowSystemProperties;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
-import org.robolectric.util.ReflectionHelpers;
-
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
-public class ColorModePreferenceControllerTest {
-    @Mock
-    private ColorModePreferenceController.ConfigurationWrapper mConfigWrapper;
-    @Mock
-    private SwitchPreference mPreference;
-    @Mock
-    private PreferenceScreen mScreen;
-    @Mock
-    private Context mContext;
-    @Mock
-    private IBinder mSurfaceFlinger;
-
-    private ColorModePreferenceController mController;
-
-    @Before
-    public void setup() {
-        MockitoAnnotations.initMocks(this);
-        SettingsShadowSystemProperties.clear();
-
-        mController = new ColorModePreferenceController(mContext);
-        ReflectionHelpers.setField(mController, "mSurfaceFlinger", mSurfaceFlinger);
-        ReflectionHelpers.setField(mController, "mConfigWrapper", mConfigWrapper);
-
-        when(mConfigWrapper.isScreenWideColorGamut()).thenReturn(true);
-
-        when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
-        when(mPreference.getKey()).thenReturn(mController.getPreferenceKey());
-    }
-
-    @Config(shadows = {SettingsShadowSystemProperties.class})
-    @Test
-    public void shouldCheckPreference() {
-        SettingsShadowSystemProperties.set(
-                ColorModePreferenceController.PERSISTENT_PROPERTY_SATURATION,
-                Float.toString(ColorModePreferenceController.COLOR_SATURATION_VIVID));
-
-        mController.updateState(mPreference);
-
-        verify(mPreference).setChecked(true);
-    }
-
-    @Config(shadows = {SettingsShadowSystemProperties.class})
-    @Test
-    public void shouldUncheckPreference() {
-        SettingsShadowSystemProperties.set(
-                ColorModePreferenceController.PERSISTENT_PROPERTY_SATURATION,
-                Float.toString(ColorModePreferenceController.COLOR_SATURATION_DEFAULT));
-
-        mController.updateState(mPreference);
-
-        verify(mPreference).setChecked(false);
-    }
-
-    @Config(shadows = {SettingsShadowSystemProperties.class})
-    @Test
-    public void shouldBoostSaturationOnCheck() {
-        mController.onPreferenceChange(mPreference, true);
-
-        String saturation = SettingsShadowSystemProperties
-                .get(ColorModePreferenceController.PERSISTENT_PROPERTY_SATURATION);
-        assertThat(saturation)
-                .isEqualTo(Float.toString(ColorModePreferenceController.COLOR_SATURATION_VIVID));
-    }
-
-    @Config(shadows = {SettingsShadowSystemProperties.class})
-    @Test
-    public void shouldResetSaturationOnUncheck() {
-        mController.onPreferenceChange(mPreference, false);
-
-        String saturation = SettingsShadowSystemProperties
-                .get(ColorModePreferenceController.PERSISTENT_PROPERTY_SATURATION);
-        assertThat(saturation)
-                .isEqualTo(Float.toString(ColorModePreferenceController.COLOR_SATURATION_DEFAULT));
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/display/ColorModePreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/display/ColorModePreferenceFragmentTest.java
new file mode 100644
index 0000000..435f4f2
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/display/ColorModePreferenceFragmentTest.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2017 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.settings.display;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import android.app.IActivityManager;
+import android.content.res.Configuration;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+import com.android.internal.logging.nano.MetricsProto;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.SettingsShadowSystemProperties;
+import com.android.settings.widget.RadioButtonPickerFragment;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+import java.util.List;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class ColorModePreferenceFragmentTest {
+    @Mock
+    private IBinder mSurfaceFlinger;
+    @Mock
+    private IActivityManager mActivityManager;
+
+    private ColorModePreferenceFragment mFragment;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        SettingsShadowSystemProperties.clear();
+
+        mFragment = spy(new ColorModePreferenceFragment());
+        doReturn(RuntimeEnvironment.application).when(mFragment).getContext();
+        doNothing().when(mFragment).updateConfiguration();
+
+        ReflectionHelpers.setField(mFragment, "mSurfaceFlinger", mSurfaceFlinger);
+        ReflectionHelpers.setField(mFragment, "mActivityManager", mActivityManager);
+    }
+
+    @Test
+    public void verifyMetricsConstant() {
+        assertThat(mFragment.getMetricsCategory())
+                .isEqualTo(MetricsProto.MetricsEvent.COLOR_MODE_SETTINGS);
+    }
+
+    @Test
+    public void getCandidates() {
+        List<? extends RadioButtonPickerFragment.CandidateInfo> candidates =
+                mFragment.getCandidates();
+
+        assertThat(candidates.size()).isEqualTo(3);
+        assertThat(candidates.get(0).getKey())
+                .isEqualTo(ColorModePreferenceFragment.KEY_COLOR_MODE_NATURAL);
+        assertThat(candidates.get(1).getKey())
+                .isEqualTo(ColorModePreferenceFragment.KEY_COLOR_MODE_BOOSTED);
+        assertThat(candidates.get(2).getKey())
+                .isEqualTo(ColorModePreferenceFragment.KEY_COLOR_MODE_SATURATED);
+    }
+
+    @Config(shadows = {SettingsShadowSystemProperties.class})
+    @Test
+    public void getKey_natural() {
+        SettingsShadowSystemProperties.set(
+                ColorModePreferenceFragment.PERSISTENT_PROPERTY_SATURATION,
+                Float.toString(ColorModePreferenceFragment.COLOR_SATURATION_NATURAL));
+        SettingsShadowSystemProperties.set(
+                ColorModePreferenceFragment.PERSISTENT_PROPERTY_NATIVE_MODE, "0");
+
+        assertThat(mFragment.getDefaultKey())
+                .isEqualTo(ColorModePreferenceFragment.KEY_COLOR_MODE_NATURAL);
+    }
+
+    @Config(shadows = {SettingsShadowSystemProperties.class})
+    @Test
+    public void getKey_boosted() {
+        SettingsShadowSystemProperties.set(
+                ColorModePreferenceFragment.PERSISTENT_PROPERTY_SATURATION,
+                Float.toString(ColorModePreferenceFragment.COLOR_SATURATION_BOOSTED));
+        SettingsShadowSystemProperties.set(
+                ColorModePreferenceFragment.PERSISTENT_PROPERTY_NATIVE_MODE, "0");
+
+        assertThat(mFragment.getDefaultKey())
+                .isEqualTo(ColorModePreferenceFragment.KEY_COLOR_MODE_BOOSTED);
+    }
+
+    @Config(shadows = {SettingsShadowSystemProperties.class})
+    @Test
+    public void getKey_saturated() {
+        SettingsShadowSystemProperties.set(
+                ColorModePreferenceFragment.PERSISTENT_PROPERTY_NATIVE_MODE, "1");
+
+        assertThat(mFragment.getDefaultKey())
+                .isEqualTo(ColorModePreferenceFragment.KEY_COLOR_MODE_SATURATED);
+    }
+
+    @Config(shadows = {SettingsShadowSystemProperties.class})
+    @Test
+    public void setKey_natural() {
+        mFragment.setDefaultKey(ColorModePreferenceFragment.KEY_COLOR_MODE_NATURAL);
+
+        String saturation = SettingsShadowSystemProperties
+                .get(ColorModePreferenceFragment.PERSISTENT_PROPERTY_SATURATION);
+        assertThat(saturation)
+                .isEqualTo(Float.toString(ColorModePreferenceFragment.COLOR_SATURATION_NATURAL));
+
+        String nativeMode = SettingsShadowSystemProperties
+                .get(ColorModePreferenceFragment.PERSISTENT_PROPERTY_NATIVE_MODE);
+        assertThat(nativeMode).isEqualTo("0");
+    }
+
+    @Config(shadows = {SettingsShadowSystemProperties.class})
+    @Test
+    public void setKey_boosted() {
+        mFragment.setDefaultKey(ColorModePreferenceFragment.KEY_COLOR_MODE_BOOSTED);
+
+        String saturation = SettingsShadowSystemProperties
+                .get(ColorModePreferenceFragment.PERSISTENT_PROPERTY_SATURATION);
+        assertThat(saturation)
+                .isEqualTo(Float.toString(ColorModePreferenceFragment.COLOR_SATURATION_BOOSTED));
+
+        String nativeMode = SettingsShadowSystemProperties
+                .get(ColorModePreferenceFragment.PERSISTENT_PROPERTY_NATIVE_MODE);
+        assertThat(nativeMode).isEqualTo("0");
+    }
+
+    @Config(shadows = {SettingsShadowSystemProperties.class})
+    @Test
+    public void setKey_saturated() {
+        mFragment.setDefaultKey(ColorModePreferenceFragment.KEY_COLOR_MODE_SATURATED);
+
+        String saturation = SettingsShadowSystemProperties
+                .get(ColorModePreferenceFragment.PERSISTENT_PROPERTY_SATURATION);
+        assertThat(saturation)
+                .isEqualTo(Float.toString(ColorModePreferenceFragment.COLOR_SATURATION_NATURAL));
+
+        String nativeMode = SettingsShadowSystemProperties
+                .get(ColorModePreferenceFragment.PERSISTENT_PROPERTY_NATIVE_MODE);
+        assertThat(nativeMode).isEqualTo("1");
+    }
+}