OSDN Git Service

Move theme setting out of tuner to display
authorJason Monk <jmonk@google.com>
Wed, 25 Jan 2017 15:34:29 +0000 (10:34 -0500)
committerJason Monk <jmonk@google.com>
Wed, 25 Jan 2017 15:34:29 +0000 (10:34 -0500)
Test: runtest --path
packages/apps/Settings/tests/unit/src/com/android/settings/display/
Fixes: 34682466

Change-Id: Ifc21e390bf8441308871d487bd60d59826603ec2

res/values/strings.xml
res/xml/ia_display_settings.xml
src/com/android/settings/DisplaySettings.java
src/com/android/settings/display/ThemePreferenceController.java [new file with mode: 0644]
tests/unit/src/com/android/settings/display/ThemePreferenceControllerTest.java [new file with mode: 0644]

index 0e572a6..818ff9f 100644 (file)
         Make <xliff:g id="app_name">%1$s</xliff:g> your autofill app? <xliff:g id="app_name">%1$s</xliff:g> will be able to read your screen and fill fields in other apps.
     </string>
 
+    <!-- Name of setting for switching device theme [CHAR LIMIT=60] -->
+    <string name="device_theme">Device theme</string>
+    <!-- Name of default device theme [CHAR LIMIT=60] -->
+    <string name="default_theme">Default</string>
+    <!-- Temporary reboot string, will be removed -->
+    <string name="change_theme_reboot" translatable="false">Changing the theme requires a restart.</string>
+
 </resources>
index 946466b..ed026f1 100644 (file)
                 android:title="@string/tap_to_wake"
                 android:summary="@string/tap_to_wake_summary" />
 
+        <ListPreference
+                android:key="theme"
+                android:title="@string/device_theme"
+                android:summary="%s" />
+
         <Preference
                 android:key="wifi_display"
                 android:title="@string/wifi_display_settings_title"
index e7b44f6..320cb83 100644 (file)
@@ -35,6 +35,7 @@ import com.android.settings.display.NightDisplayPreferenceController;
 import com.android.settings.display.NightModePreferenceController;
 import com.android.settings.display.ScreenSaverPreferenceController;
 import com.android.settings.display.TapToWakePreferenceController;
+import com.android.settings.display.ThemePreferenceController;
 import com.android.settings.display.TimeoutPreferenceController;
 import com.android.settings.display.VrDisplayPreferenceController;
 import com.android.settings.display.WallpaperPreferenceController;
@@ -92,6 +93,7 @@ public class DisplaySettings extends DashboardFragment {
         controllers.add(new TimeoutPreferenceController(context));
         controllers.add(new VrDisplayPreferenceController(context));
         controllers.add(new WallpaperPreferenceController(context));
+        controllers.add(new ThemePreferenceController(context));
         return controllers;
     }
 
@@ -177,6 +179,7 @@ public class DisplaySettings extends DashboardFragment {
                     new TimeoutPreferenceController(context).updateNonIndexableKeys(result);
                     new VrDisplayPreferenceController(context).updateNonIndexableKeys(result);
                     new WallpaperPreferenceController(context).updateNonIndexableKeys(result);
+                    new ThemePreferenceController(context).updateNonIndexableKeys(result);
 
                     return result;
                 }
diff --git a/src/com/android/settings/display/ThemePreferenceController.java b/src/com/android/settings/display/ThemePreferenceController.java
new file mode 100644 (file)
index 0000000..da5b84a
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * 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.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_THEME;
+
+import android.app.AlertDialog;
+import android.app.UiModeManager;
+import android.content.Context;
+import android.content.DialogInterface.OnClickListener;
+import android.support.v7.preference.ListPreference;
+import android.support.v7.preference.Preference;
+
+import com.android.settings.R;
+import com.android.settings.core.PreferenceController;
+import com.android.settings.core.instrumentation.MetricsFeatureProvider;
+import com.android.settings.overlay.FeatureFactory;
+
+import libcore.util.Objects;
+
+public class ThemePreferenceController extends PreferenceController implements
+        Preference.OnPreferenceChangeListener {
+
+    private static final String KEY_THEME = "theme";
+
+    private final UiModeManager mUiModeManager;
+    private final MetricsFeatureProvider mMetricsFeatureProvider;
+
+    public ThemePreferenceController(Context context) {
+        super(context);
+        mUiModeManager = context.getSystemService(UiModeManager.class);
+        mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY_THEME;
+    }
+
+    @Override
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        if (KEY_THEME.equals(preference.getKey())) {
+            mMetricsFeatureProvider.action(mContext, ACTION_THEME);
+        }
+        return false;
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        ListPreference pref = (ListPreference) preference;
+        String[] options = mUiModeManager.getAvailableThemes();
+        for (int i = 0; i < options.length; i++) {
+            options[i] = nullToDefault(options[i]);
+        }
+        pref.setEntries(options);
+        pref.setEntryValues(options);
+        String theme = mUiModeManager.getTheme();
+        if (theme == null) {
+            theme = mContext.getString(R.string.default_theme);
+        }
+        pref.setValue(nullToDefault(theme));
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object newValue) {
+        if (Objects.equal(newValue, mUiModeManager.getTheme())) {
+            return true;
+        }
+        // TODO: STOPSHIP Don't require reboot and remove this prompt.
+        OnClickListener onConfirm = (d, i) -> {
+            mUiModeManager.setTheme(defaultToNull((String) newValue));
+            ((ListPreference) preference).setValue((String) newValue);
+        };
+        new AlertDialog.Builder(mContext)
+                .setTitle(R.string.change_theme_reboot)
+                .setPositiveButton(com.android.internal.R.string.global_action_restart, onConfirm)
+                .setNegativeButton(android.R.string.cancel, null)
+                .show();
+        return false;
+    }
+
+    @Override
+    public boolean isAvailable() {
+        String[] themes = mUiModeManager.getAvailableThemes();
+        return themes != null && themes.length > 1;
+    }
+
+    private String nullToDefault(String input) {
+        if (input == null) {
+            return mContext.getString(R.string.default_theme);
+        }
+        return input;
+    }
+
+    private String defaultToNull(String input) {
+        if (mContext.getString(R.string.default_theme).equals(input)) {
+            return null;
+        }
+        return input;
+    }
+}
diff --git a/tests/unit/src/com/android/settings/display/ThemePreferenceControllerTest.java b/tests/unit/src/com/android/settings/display/ThemePreferenceControllerTest.java
new file mode 100644 (file)
index 0000000..231787e
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * 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.core;
+
+import static junit.framework.TestCase.assertNotNull;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.UiModeManager;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.v7.preference.ListPreference;
+
+import com.android.settings.R;
+import com.android.settings.display.ThemePreferenceController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ThemePreferenceControllerTest {
+
+    private UiModeManager mMockUiModeManager;
+    private ContextWrapper mContext;
+    private ThemePreferenceController mPreferenceController;
+
+    @Before
+    public void setup() {
+        mMockUiModeManager = mock(UiModeManager.class);
+        mContext = new ContextWrapper(InstrumentationRegistry.getTargetContext()) {
+            @Override
+            public Object getSystemService(String name) {
+                if (Context.UI_MODE_SERVICE.equals(name)) {
+                    return mMockUiModeManager;
+                }
+                return super.getSystemService(name);
+            }
+        };
+        mPreferenceController = new ThemePreferenceController(mContext);
+    }
+
+    @Test
+    public void testUpdateState() {
+        when(mMockUiModeManager.getAvailableThemes()).thenReturn(new String[] {
+                null,
+                "Theme1",
+                "Theme2",
+        });
+        when(mMockUiModeManager.getTheme()).thenReturn("Theme1");
+        ListPreference pref = mock(ListPreference.class);
+        mPreferenceController.updateState(pref);
+        ArgumentCaptor<String[]> arg = ArgumentCaptor.forClass(String[].class);
+        verify(pref).setEntries(arg.capture());
+
+        String[] entries = arg.getValue();
+        assertEquals(3, entries.length);
+        assertNotNull(entries[0]);
+        assertEquals("Theme1", entries[1]);
+        assertEquals("Theme2", entries[2]);
+
+        verify(pref).setEntryValues(arg.capture());
+        String[] entryValues = arg.getValue();
+        assertEquals(3, entryValues.length);
+        assertNotNull(entryValues[0]);
+        assertEquals("Theme1", entryValues[1]);
+        assertEquals("Theme2", entryValues[2]);
+
+        verify(pref).setValue(eq("Theme1"));
+    }
+
+    @Test
+    public void testAvailable_false() {
+        when(mMockUiModeManager.getAvailableThemes()).thenReturn(new String[1]);
+        assertFalse(mPreferenceController.isAvailable());
+    }
+
+    @Test
+    public void testAvailable_true() {
+        when(mMockUiModeManager.getAvailableThemes()).thenReturn(new String[2]);
+        assertTrue(mPreferenceController.isAvailable());
+    }
+}