OSDN Git Service

Add progressive disclsoure
authorFan Zhang <zhfan@google.com>
Tue, 18 Oct 2016 19:58:31 +0000 (12:58 -0700)
committerFan Zhang <zhfan@google.com>
Tue, 18 Oct 2016 23:57:11 +0000 (16:57 -0700)
- Add a ProgressiveDisclosureMixin that contains all logic for collapse
  preference list when it's too long
- Refactored PreferenceController's updateState to take a preference
  instead of PreferenceScreen, because with progressive disclosure the
  preference can either be in screen or the mixin. DashboardFragment is
  responsible finding the preference before passing it to controller.

Bug: 32255863
Test: RunSettingsRoboTests

Change-Id: I6713abd61c954ce12732902e5b3ca4d4c0b1563e

34 files changed:
res/layout/expand_preference.xml [new file with mode: 0644]
src/com/android/settings/core/PreferenceController.java
src/com/android/settings/core/lifecycle/ObservablePreferenceFragment.java
src/com/android/settings/dashboard/DashboardFragment.java
src/com/android/settings/dashboard/ExpandPreference.java [new file with mode: 0644]
src/com/android/settings/dashboard/ProgressiveDisclosureMixin.java [new file with mode: 0644]
src/com/android/settings/deviceinfo/AdditionalSystemUpdatePreferenceController.java
src/com/android/settings/deviceinfo/ManageStoragePreferenceController.java
src/com/android/settings/deviceinfo/SystemUpdatePreferenceController.java
src/com/android/settings/display/AutoBrightnessPreferenceController.java
src/com/android/settings/display/AutoRotatePreferenceController.java
src/com/android/settings/display/CameraGesturePreferenceController.java
src/com/android/settings/display/DozePreferenceController.java
src/com/android/settings/display/FontSizePreferenceController.java
src/com/android/settings/display/LiftToWakePreferenceController.java
src/com/android/settings/display/NightDisplayPreferenceController.java
src/com/android/settings/display/NightModePreferenceController.java
src/com/android/settings/display/ScreenSaverPreferenceController.java
src/com/android/settings/display/TapToWakePreferenceController.java
src/com/android/settings/display/TimeoutPreferenceController.java
src/com/android/settings/display/VrDisplayPreferenceController.java
src/com/android/settings/display/WallpaperPreferenceController.java
src/com/android/settings/network/AirplaneModePreferenceController.java
src/com/android/settings/network/MobileNetworkPreferenceController.java
src/com/android/settings/network/MobilePlanPreferenceController.java
src/com/android/settings/network/NetworkResetPreferenceController.java
src/com/android/settings/network/ProxyPreferenceController.java
src/com/android/settings/network/TetherPreferenceController.java
src/com/android/settings/network/VpnPreferenceController.java
src/com/android/settings/network/WifiCallingPreferenceController.java
src/com/android/settings/nfc/NfcPreferenceController.java
tests/robotests/src/com/android/settings/core/PreferenceControllerTest.java
tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java
tests/robotests/src/com/android/settings/dashboard/ProgressiveDisclosureTest.java [new file with mode: 0644]

diff --git a/res/layout/expand_preference.xml b/res/layout/expand_preference.xml
new file mode 100644 (file)
index 0000000..640cda7
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2016 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.
+  -->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:background="@drawable/selectable_card_grey"
+    android:gravity="center_vertical"
+    android:minHeight="?android:attr/listPreferredItemHeight"
+    android:orientation="vertical"
+    android:paddingEnd="?android:attr/scrollbarSize">
+    <TextView
+        android:id="@android:id/title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"/>
+</LinearLayout>
\ No newline at end of file
index 6eac2bd..8a4a245 100644 (file)
@@ -50,7 +50,8 @@ public abstract class PreferenceController {
     /**
      * Updates the current status of preference (summary, switch state, etc)
      */
-    public void updateState(PreferenceScreen screen) {
+    public void updateState(Preference preference) {
+
     }
 
     /**
@@ -73,6 +74,11 @@ public abstract class PreferenceController {
     public abstract boolean handlePreferenceTreeClick(Preference preference);
 
     /**
+     * Returns the key for this preference.
+     */
+    public abstract String getPreferenceKey();
+
+    /**
      * Removes preference from screen.
      */
     protected final void removePreference(PreferenceScreen screen, String key) {
@@ -86,10 +92,4 @@ public abstract class PreferenceController {
      * Returns true if preference is available (should be displayed)
      */
     protected abstract boolean isAvailable();
-
-    /**
-     * Returns the key for this preference.
-     */
-    protected abstract String getPreferenceKey();
-
 }
index e9822af..dbce755 100644 (file)
@@ -42,8 +42,8 @@ public abstract class ObservablePreferenceFragment extends PreferenceFragment {
     @CallSuper
     @Override
     public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
         mLifecycle.onCreate(savedInstanceState);
+        super.onCreate(savedInstanceState);
     }
 
     @CallSuper
index 3d06578..a730939 100644 (file)
@@ -52,12 +52,14 @@ import java.util.Set;
 public abstract class DashboardFragment extends SettingsPreferenceFragment
         implements SettingsDrawerActivity.CategoryListener, Indexable,
         SummaryLoader.SummaryConsumer {
+    private static final String TAG = "DashboardFragment";
 
     private final Map<Class, PreferenceController> mPreferenceControllers =
             new ArrayMap<>();
     private final Set<String> mDashboardTilePrefKeys = new ArraySet<>();
     private DashboardDividerDecoration mDividerDecoration;
 
+    protected ProgressiveDisclosureMixin mProgressiveDisclosureMixin;
     protected DashboardFeatureProvider mDashboardFeatureProvider;
     private boolean mListeningToCategoryChange;
     private SummaryLoader mSummaryLoader;
@@ -67,6 +69,8 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
         super.onAttach(context);
         mDashboardFeatureProvider =
                 FeatureFactory.getFactory(context).getDashboardFeatureProvider(context);
+        mProgressiveDisclosureMixin = new ProgressiveDisclosureMixin(context, this);
+        getLifecycle().addObserver(mProgressiveDisclosureMixin);
 
         final List<PreferenceController> controllers = getPreferenceControllers(context);
         if (controllers == null) {
@@ -160,6 +164,18 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
         }
     }
 
+    @Override
+    public Preference findPreference(CharSequence key) {
+        Preference preference = super.findPreference(key);
+        if (preference == null && mProgressiveDisclosureMixin != null) {
+            preference = mProgressiveDisclosureMixin.findPreference(key);
+        }
+        if (preference == null) {
+            Log.d(TAG, "Cannot find preference with key " + key);
+        }
+        return preference;
+    }
+
     protected <T extends PreferenceController> T getPreferenceController(Class<T> clazz) {
         PreferenceController controller = mPreferenceControllers.get(clazz);
         return (T) controller;
@@ -259,7 +275,19 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
             // (larger value has higher priority). However pref order defines smaller value has
             // higher priority.
             pref.setOrder(-tile.priority);
-            screen.addPreference(pref);
+
+            // Either add to screen, or to collapsed list.
+            if (mProgressiveDisclosureMixin.isCollapsed()) {
+                // Already collapsed, add to collapsed list.
+                mProgressiveDisclosureMixin.addToCollapsedList(pref);
+            } else if (mProgressiveDisclosureMixin.shouldCollapse(screen)) {
+                // About to have too many tiles on scree, collapse and add pref to collapsed list.
+                mProgressiveDisclosureMixin.collapse(screen);
+                mProgressiveDisclosureMixin.addToCollapsedList(pref);
+            } else {
+                // No need to collapse, add to screen directly.
+                screen.addPreference(pref);
+            }
         }
     }
 
@@ -278,9 +306,15 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
      */
     private void updatePreferenceStates() {
         Collection<PreferenceController> controllers = mPreferenceControllers.values();
-        final PreferenceScreen screen = getPreferenceScreen();
         for (PreferenceController controller : controllers) {
-            controller.updateState(screen);
+            final String key = controller.getPreferenceKey();
+
+            final Preference preference = findPreference(key);
+            if (preference == null) {
+                Log.d(TAG, "Cannot find preference with key " + key);
+                continue;
+            }
+            controller.updateState(preference);
         }
     }
 
@@ -302,15 +336,20 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
      */
     private void refreshAllPreferences(final String TAG) {
         // First remove old preferences.
-        final PreferenceScreen screen = getPreferenceScreen();
-        if (screen != null) {
-            screen.removeAll();
+        if (getPreferenceScreen() != null) {
+            // Intentionally do not cache PreferenceScreen because it will be recreated later.
+            getPreferenceScreen().removeAll();
         }
 
         // Add resource based tiles.
         displayResourceTiles();
 
         refreshDashboardTiles(TAG);
+
+        if (!mProgressiveDisclosureMixin.isCollapsed()
+                && mProgressiveDisclosureMixin.shouldCollapse(getPreferenceScreen())) {
+            mProgressiveDisclosureMixin.collapse(getPreferenceScreen());
+        }
     }
 
     /**
@@ -319,10 +358,13 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
     private void refreshDashboardTiles(final String TAG) {
         final PreferenceScreen screen = getPreferenceScreen();
         for (String key : mDashboardTilePrefKeys) {
+            // Remove tiles from screen
             final Preference pref = screen.findPreference(key);
             if (pref != null) {
                 screen.removePreference(pref);
             }
+            // Also remove tile from collapsed set
+            mProgressiveDisclosureMixin.removePreference(screen, key);
         }
         mDashboardTilePrefKeys.clear();
         displayDashboardTiles(TAG, getPreferenceScreen());
diff --git a/src/com/android/settings/dashboard/ExpandPreference.java b/src/com/android/settings/dashboard/ExpandPreference.java
new file mode 100644 (file)
index 0000000..215bfc5
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2016 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.dashboard;
+
+import android.content.Context;
+import android.support.v7.preference.Preference;
+import android.util.AttributeSet;
+
+import com.android.settings.R;
+
+public class ExpandPreference extends Preference {
+
+    public ExpandPreference(Context context, AttributeSet attrs,
+            int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        init();
+    }
+
+    public ExpandPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        init();
+    }
+
+    public ExpandPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init();
+    }
+
+    public ExpandPreference(Context context) {
+        super(context);
+        init();
+    }
+
+    private void init() {
+        setLayoutResource(R.layout.expand_preference);
+        setTitle(R.string.wifi_more);
+        setOrder(999);
+    }
+}
diff --git a/src/com/android/settings/dashboard/ProgressiveDisclosureMixin.java b/src/com/android/settings/dashboard/ProgressiveDisclosureMixin.java
new file mode 100644 (file)
index 0000000..28113ad
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2016 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.dashboard;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.support.v14.preference.PreferenceFragment;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.settings.core.lifecycle.LifecycleObserver;
+import com.android.settings.core.lifecycle.events.OnCreate;
+import com.android.settings.core.lifecycle.events.OnSaveInstanceState;
+import com.android.settings.overlay.FeatureFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ProgressiveDisclosureMixin implements Preference.OnPreferenceClickListener,
+        LifecycleObserver, OnCreate, OnSaveInstanceState {
+
+    private static final String TAG = "ProgressiveDisclosure";
+    private static final String STATE_USER_EXPANDED = "state_user_expanded";
+    private static final int DEFAULT_TILE_LIMIT = 3;
+
+    private int mTileLimit = DEFAULT_TILE_LIMIT;
+
+    private final DashboardFeatureProvider mDashboardFeatureProvider;
+    private final List<Preference> collapsedPrefs = new ArrayList<>();
+    private final ExpandPreference mExpandButton;
+    private final PreferenceFragment mFragment;
+
+    private boolean mUserExpanded;
+
+    public ProgressiveDisclosureMixin(Context context, PreferenceFragment fragment) {
+        mFragment = fragment;
+        mExpandButton = new ExpandPreference(context);
+        mExpandButton.setOnPreferenceClickListener(this);
+        mDashboardFeatureProvider = FeatureFactory.getFactory(context)
+                .getDashboardFeatureProvider(context);
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        if (savedInstanceState != null) {
+            mUserExpanded = savedInstanceState.getBoolean(STATE_USER_EXPANDED, false);
+        }
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        outState.putBoolean(STATE_USER_EXPANDED, mUserExpanded);
+    }
+
+    @Override
+    public boolean onPreferenceClick(Preference preference) {
+        if (preference instanceof ExpandPreference) {
+            final PreferenceScreen screen = mFragment.getPreferenceScreen();
+            if (screen != null) {
+                screen.removePreference(preference);
+                for (Preference pref : collapsedPrefs) {
+                    screen.addPreference(pref);
+                }
+                mUserExpanded = true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Sets the threshold to start collapsing preferences when there are too many.
+     */
+    public void setTileLimit(int limit) {
+        mTileLimit = limit;
+    }
+
+    /**
+     * Whether the controller is in collapsed state.
+     */
+    public boolean isCollapsed() {
+        return !collapsedPrefs.isEmpty();
+    }
+
+    /**
+     * Whether the screen should be collapsed.
+     */
+    public boolean shouldCollapse(PreferenceScreen screen) {
+        return mDashboardFeatureProvider.isEnabled() && screen.getPreferenceCount() >= mTileLimit
+                && !mUserExpanded;
+    }
+
+    /**
+     * Collapse extra preferences and show a "More" button
+     */
+    public void collapse(PreferenceScreen screen) {
+        final int itemCount = screen.getPreferenceCount();
+        if (!shouldCollapse(screen)) {
+            return;
+        }
+        if (!collapsedPrefs.isEmpty()) {
+            Log.w(TAG, "collapsed list should ALWAYS BE EMPTY before collapsing!");
+        }
+
+        for (int i = itemCount - 1; i >= mTileLimit; i--) {
+            final Preference preference = screen.getPreference(i);
+            addToCollapsedList(preference);
+            screen.removePreference(preference);
+        }
+        screen.addPreference(mExpandButton);
+    }
+
+    /**
+     * Add preference to collapsed list.
+     */
+    public void addToCollapsedList(Preference preference) {
+        collapsedPrefs.add(preference);
+    }
+
+    /**
+     * Remove preference from collapsed list. If the preference is not in list, do nothing.
+     */
+    public void removePreference(PreferenceScreen screen, String key) {
+        if (!isCollapsed()) {
+            return;
+        }
+        for (int i = 0; i < collapsedPrefs.size(); i++) {
+            final Preference pref = collapsedPrefs.get(i);
+            if (TextUtils.equals(key, pref.getKey())) {
+                collapsedPrefs.remove(pref);
+                if (collapsedPrefs.isEmpty()) {
+                    // Removed last element, remove expand button too.
+                    screen.removePreference(mExpandButton);
+                }
+                return;
+            }
+        }
+    }
+
+    /**
+     * Find whether a preference is in collapsed list.
+     */
+    public Preference findPreference(CharSequence key) {
+        for (int i = 0; i < collapsedPrefs.size(); i++) {
+            final Preference pref = collapsedPrefs.get(i);
+            if (TextUtils.equals(key, pref.getKey())) {
+                return pref;
+            }
+        }
+        return null;
+    }
+
+}
index 6dd6aba..7290250 100644 (file)
@@ -40,7 +40,7 @@ public class AdditionalSystemUpdatePreferenceController extends PreferenceContro
     }
 
     @Override
-    protected String getPreferenceKey() {
+    public String getPreferenceKey() {
         return KEY_UPDATE_SETTING;
     }
 }
index add4781..d4d53d4 100644 (file)
@@ -33,7 +33,7 @@ public class ManageStoragePreferenceController extends PreferenceController {
     }
 
     @Override
-    protected String getPreferenceKey() {
+    public String getPreferenceKey() {
         return KEY_MANAGE_STORAGE;
     }
 
index 449847a..e086a56 100644 (file)
@@ -51,7 +51,7 @@ public class SystemUpdatePreferenceController extends PreferenceController {
     }
 
     @Override
-    protected String getPreferenceKey() {
+    public String getPreferenceKey() {
         return KEY_SYSTEM_UPDATE_SETTINGS;
     }
 
index 934ccf2..775e60c 100644 (file)
@@ -17,7 +17,6 @@ import android.content.Context;
 import android.provider.Settings;
 import android.support.v14.preference.SwitchPreference;
 import android.support.v7.preference.Preference;
-import android.support.v7.preference.PreferenceScreen;
 
 import com.android.settings.core.PreferenceController;
 
@@ -42,7 +41,7 @@ public class AutoBrightnessPreferenceController extends PreferenceController imp
     }
 
     @Override
-    protected String getPreferenceKey() {
+    public String getPreferenceKey() {
         return KEY_AUTO_BRIGHTNESS;
     }
 
@@ -52,15 +51,10 @@ public class AutoBrightnessPreferenceController extends PreferenceController imp
     }
 
     @Override
-    public void updateState(PreferenceScreen screen) {
-        final SwitchPreference preference =
-                (SwitchPreference) screen.findPreference(KEY_AUTO_BRIGHTNESS);
-        if (preference == null) {
-            return;
-        }
+    public void updateState(Preference preference) {
         int brightnessMode = Settings.System.getInt(mContext.getContentResolver(),
                 SCREEN_BRIGHTNESS_MODE, SCREEN_BRIGHTNESS_MODE_MANUAL);
-        preference.setChecked(brightnessMode != SCREEN_BRIGHTNESS_MODE_MANUAL);
+        ((SwitchPreference) preference).setChecked(brightnessMode != SCREEN_BRIGHTNESS_MODE_MANUAL);
     }
 
     @Override
index f28e1d6..44d2158 100644 (file)
@@ -17,7 +17,6 @@ import android.content.Context;
 import android.content.res.Configuration;
 import android.support.v7.preference.DropDownPreference;
 import android.support.v7.preference.Preference;
-import android.support.v7.preference.PreferenceScreen;
 
 import com.android.internal.logging.MetricsProto;
 import com.android.internal.view.RotationPolicy;
@@ -38,14 +37,13 @@ public class AutoRotatePreferenceController extends PreferenceController impleme
     }
 
     @Override
-    protected String getPreferenceKey() {
+    public String getPreferenceKey() {
         return KEY_AUTO_ROTATE;
     }
 
     @Override
-    public void updateState(PreferenceScreen screen) {
-        final DropDownPreference rotatePreference =
-                (DropDownPreference) screen.findPreference(KEY_AUTO_ROTATE);
+    public void updateState(Preference preference) {
+        final DropDownPreference rotatePreference = (DropDownPreference) preference;
         final int rotateLockedResourceId;
         // The following block sets the string used when rotation is locked.
         // If the device locks specifically to portrait or landscape (rather than current
@@ -69,7 +67,6 @@ public class AutoRotatePreferenceController extends PreferenceController impleme
                 1 : 0);
     }
 
-
     @Override
     public boolean handlePreferenceTreeClick(Preference preference) {
         return false;
index 98486c5..3f5d0de 100644 (file)
@@ -18,7 +18,6 @@ import android.os.SystemProperties;
 import android.provider.Settings;
 import android.support.v14.preference.SwitchPreference;
 import android.support.v7.preference.Preference;
-import android.support.v7.preference.PreferenceScreen;
 
 import com.android.settings.core.PreferenceController;
 
@@ -34,7 +33,7 @@ public class CameraGesturePreferenceController extends PreferenceController impl
     }
 
     @Override
-    protected String getPreferenceKey() {
+    public String getPreferenceKey() {
         return KEY_CAMERA_GESTURE;
     }
 
@@ -44,14 +43,10 @@ public class CameraGesturePreferenceController extends PreferenceController impl
     }
 
     @Override
-    public void updateState(PreferenceScreen screen) {
-        final SwitchPreference preference =
-                (SwitchPreference) screen.findPreference(KEY_CAMERA_GESTURE);
-        if (preference != null) {
-            int value = Settings.Secure.getInt(mContext.getContentResolver(),
-                    CAMERA_GESTURE_DISABLED, 0);
-            preference.setChecked(value == 0);
-        }
+    public void updateState(Preference preference) {
+        int value = Settings.Secure.getInt(mContext.getContentResolver(),
+                CAMERA_GESTURE_DISABLED, 0);
+        ((SwitchPreference) preference).setChecked(value == 0);
     }
 
     @Override
index 9fcc807..bf5d8f3 100644 (file)
@@ -19,7 +19,6 @@ import android.os.SystemProperties;
 import android.provider.Settings;
 import android.support.v14.preference.SwitchPreference;
 import android.support.v7.preference.Preference;
-import android.support.v7.preference.PreferenceScreen;
 import android.text.TextUtils;
 
 import com.android.settings.core.PreferenceController;
@@ -42,7 +41,7 @@ public class DozePreferenceController extends PreferenceController implements
     }
 
     @Override
-    protected String getPreferenceKey() {
+    public String getPreferenceKey() {
         return KEY_DOZE;
     }
 
@@ -55,13 +54,9 @@ public class DozePreferenceController extends PreferenceController implements
     }
 
     @Override
-    public void updateState(PreferenceScreen screen) {
-        final SwitchPreference preference = (SwitchPreference) screen.findPreference(KEY_DOZE);
-        // Update doze if it is available.
-        if (preference != null) {
-            int value = Settings.Secure.getInt(mContext.getContentResolver(), DOZE_ENABLED, 1);
-            preference.setChecked(value != 0);
-        }
+    public void updateState(Preference preference) {
+        int value = Settings.Secure.getInt(mContext.getContentResolver(), DOZE_ENABLED, 1);
+        ((SwitchPreference) preference).setChecked(value != 0);
     }
 
     @Override
index 9981fcd..fcd423d 100644 (file)
@@ -17,7 +17,6 @@ import android.content.Context;
 import android.content.res.Resources;
 import android.provider.Settings;
 import android.support.v7.preference.Preference;
-import android.support.v7.preference.PreferenceScreen;
 
 import com.android.settings.R;
 import com.android.settings.accessibility.ToggleFontSizePreferenceFragment;
@@ -37,16 +36,12 @@ public class FontSizePreferenceController extends PreferenceController {
     }
 
     @Override
-    protected String getPreferenceKey() {
+    public String getPreferenceKey() {
         return KEY_FONT_SIZE;
     }
 
     @Override
-    public void updateState(PreferenceScreen screen) {
-        final Preference preference = screen.findPreference(KEY_FONT_SIZE);
-        if (preference == null) {
-            return;
-        }
+    public void updateState(Preference preference) {
         final float currentScale = Settings.System.getFloat(mContext.getContentResolver(),
                 Settings.System.FONT_SCALE, 1.0f);
         final Resources res = mContext.getResources();
index 0b573cf..c518f68 100644 (file)
@@ -19,7 +19,6 @@ import android.hardware.SensorManager;
 import android.provider.Settings;
 import android.support.v14.preference.SwitchPreference;
 import android.support.v7.preference.Preference;
-import android.support.v7.preference.PreferenceScreen;
 
 import com.android.settings.core.PreferenceController;
 
@@ -41,7 +40,7 @@ public class LiftToWakePreferenceController extends PreferenceController impleme
     }
 
     @Override
-    protected String getPreferenceKey() {
+    public String getPreferenceKey() {
         return KEY_LIFT_TO_WAKE;
     }
 
@@ -58,13 +57,8 @@ public class LiftToWakePreferenceController extends PreferenceController impleme
     }
 
     @Override
-    public void updateState(PreferenceScreen screen) {
-        final SwitchPreference pref = (SwitchPreference) screen.findPreference(KEY_LIFT_TO_WAKE);
-        // Update lift-to-wake if it is available.
-        if (pref != null) {
-            int value =
-                    Settings.Secure.getInt(mContext.getContentResolver(), WAKE_GESTURE_ENABLED, 0);
-            pref.setChecked(value != 0);
-        }
+    public void updateState(Preference preference) {
+        int value = Settings.Secure.getInt(mContext.getContentResolver(), WAKE_GESTURE_ENABLED, 0);
+        ((SwitchPreference) preference).setChecked(value != 0);
     }
 }
index d7191d2..c52df23 100644 (file)
@@ -38,7 +38,7 @@ public class NightDisplayPreferenceController extends PreferenceController {
     }
 
     @Override
-    protected String getPreferenceKey() {
+    public String getPreferenceKey() {
         return KEY_NIGHT_DISPLAY;
     }
 }
index 7b3c584..c0f0c17 100644 (file)
@@ -40,7 +40,7 @@ public class NightModePreferenceController extends PreferenceController
     }
 
     @Override
-    protected String getPreferenceKey() {
+    public String getPreferenceKey() {
         return KEY_NIGHT_MODE;
     }
 
index 6376fcf..64d9dec 100644 (file)
@@ -15,7 +15,6 @@ package com.android.settings.display;
 
 import android.content.Context;
 import android.support.v7.preference.Preference;
-import android.support.v7.preference.PreferenceScreen;
 
 import com.android.settings.DreamSettings;
 import com.android.settings.core.PreferenceController;
@@ -35,7 +34,7 @@ public class ScreenSaverPreferenceController extends PreferenceController {
     }
 
     @Override
-    protected String getPreferenceKey() {
+    public String getPreferenceKey() {
         return KEY_SCREEN_SAVER;
     }
 
@@ -45,11 +44,7 @@ public class ScreenSaverPreferenceController extends PreferenceController {
     }
 
     @Override
-    public void updateState(PreferenceScreen screen) {
-        final Preference preference = screen.findPreference(KEY_SCREEN_SAVER);
-        if (preference != null) {
-            preference.setSummary(
-                    DreamSettings.getSummaryTextWithDreamName(mContext));
-        }
+    public void updateState(Preference preference) {
+        preference.setSummary(DreamSettings.getSummaryTextWithDreamName(mContext));
     }
 }
index 6d1681f..4c5aaa0 100644 (file)
@@ -17,7 +17,6 @@ import android.content.Context;
 import android.provider.Settings;
 import android.support.v14.preference.SwitchPreference;
 import android.support.v7.preference.Preference;
-import android.support.v7.preference.PreferenceScreen;
 
 import com.android.settings.core.PreferenceController;
 
@@ -31,7 +30,7 @@ public class TapToWakePreferenceController extends PreferenceController implemen
     }
 
     @Override
-    protected String getPreferenceKey() {
+    public String getPreferenceKey() {
         return KEY_TAP_TO_WAKE;
     }
 
@@ -47,14 +46,10 @@ public class TapToWakePreferenceController extends PreferenceController implemen
     }
 
     @Override
-    public void updateState(PreferenceScreen screen) {
-        final SwitchPreference preference =
-                (SwitchPreference) screen.findPreference(KEY_TAP_TO_WAKE);
-        if (preference != null) {
-            int value = Settings.Secure.getInt(
-                    mContext.getContentResolver(), Settings.Secure.DOUBLE_TAP_TO_WAKE, 0);
-            preference.setChecked(value != 0);
-        }
+    public void updateState(Preference preference) {
+        int value = Settings.Secure.getInt(
+                mContext.getContentResolver(), Settings.Secure.DOUBLE_TAP_TO_WAKE, 0);
+        ((SwitchPreference) preference).setChecked(value != 0);
     }
 
     @Override
index 1295a47..8c73c31 100644 (file)
@@ -18,7 +18,6 @@ import android.content.Context;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.support.v7.preference.Preference;
-import android.support.v7.preference.PreferenceScreen;
 import android.util.Log;
 
 import com.android.settings.R;
@@ -48,7 +47,7 @@ public class TimeoutPreferenceController extends PreferenceController implements
     }
 
     @Override
-    protected String getPreferenceKey() {
+    public String getPreferenceKey() {
         return KEY_SCREEN_TIMEOUT;
     }
 
@@ -58,15 +57,11 @@ public class TimeoutPreferenceController extends PreferenceController implements
     }
 
     @Override
-    public void updateState(PreferenceScreen screen) {
-        final TimeoutListPreference preference =
-                (TimeoutListPreference) screen.findPreference(KEY_SCREEN_TIMEOUT);
-        if (preference == null) {
-            return;
-        }
+    public void updateState(Preference preference) {
+        final TimeoutListPreference timeoutListPreference = (TimeoutListPreference) preference;
         final long currentTimeout = Settings.System.getLong(mContext.getContentResolver(),
                 SCREEN_OFF_TIMEOUT, FALLBACK_SCREEN_TIMEOUT_VALUE);
-        preference.setValue(String.valueOf(currentTimeout));
+        timeoutListPreference.setValue(String.valueOf(currentTimeout));
         final DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
                 Context.DEVICE_POLICY_SERVICE);
         if (dpm != null) {
@@ -74,9 +69,9 @@ public class TimeoutPreferenceController extends PreferenceController implements
                     RestrictedLockUtils.checkIfMaximumTimeToLockIsSet(mContext);
             final long maxTimeout =
                     dpm.getMaximumTimeToLockForUserAndProfiles(UserHandle.myUserId());
-            preference.removeUnusableTimeouts(maxTimeout, admin);
+            timeoutListPreference.removeUnusableTimeouts(maxTimeout, admin);
         }
-        updateTimeoutPreferenceDescription(preference, currentTimeout);
+        updateTimeoutPreferenceDescription(timeoutListPreference, currentTimeout);
     }
 
     @Override
index c340759..84d7462 100644 (file)
@@ -19,7 +19,6 @@ import android.content.pm.PackageManager;
 import android.provider.Settings;
 import android.support.v7.preference.DropDownPreference;
 import android.support.v7.preference.Preference;
-import android.support.v7.preference.PreferenceScreen;
 import android.util.Log;
 
 import com.android.settings.R;
@@ -42,18 +41,13 @@ public class VrDisplayPreferenceController extends PreferenceController implemen
     }
 
     @Override
-    protected String getPreferenceKey() {
+    public String getPreferenceKey() {
         return KEY_VR_DISPLAY_PREF;
     }
 
     @Override
-    public void updateState(PreferenceScreen screen) {
-        final DropDownPreference pref =
-                (DropDownPreference) screen.findPreference(KEY_VR_DISPLAY_PREF);
-        if (pref == null) {
-            Log.d(TAG, "Could not find VR display preference.");
-            return;
-        }
+    public void updateState(Preference preference) {
+        final DropDownPreference pref = (DropDownPreference) preference;
         pref.setEntries(new CharSequence[]{
                 mContext.getString(R.string.display_vr_pref_low_persistence),
                 mContext.getString(R.string.display_vr_pref_off),
index 32e9abc..29415e9 100644 (file)
@@ -16,7 +16,6 @@ package com.android.settings.display;
 import android.content.Context;
 import android.os.UserHandle;
 import android.support.v7.preference.Preference;
-import android.support.v7.preference.PreferenceScreen;
 
 import com.android.settings.core.PreferenceController;
 import com.android.settingslib.RestrictedLockUtils;
@@ -38,13 +37,13 @@ public class WallpaperPreferenceController extends PreferenceController {
     }
 
     @Override
-    protected String getPreferenceKey() {
+    public String getPreferenceKey() {
         return KEY_WALLPAPER;
     }
 
     @Override
-    public void updateState(PreferenceScreen screen) {
-        disablePreferenceIfManaged(screen);
+    public void updateState(Preference preference) {
+        disablePreferenceIfManaged((RestrictedPreference) preference);
     }
 
     @Override
@@ -52,9 +51,7 @@ public class WallpaperPreferenceController extends PreferenceController {
         return false;
     }
 
-    private void disablePreferenceIfManaged(PreferenceScreen screen) {
-        final RestrictedPreference pref =
-                (RestrictedPreference) screen.findPreference(KEY_WALLPAPER);
+    private void disablePreferenceIfManaged(RestrictedPreference pref) {
         final String restriction = DISALLOW_SET_WALLPAPER;
         if (pref != null) {
             pref.setDisabledByAdmin(null);
index c99cd4d..bd1918f 100644 (file)
@@ -92,7 +92,7 @@ public class AirplaneModePreferenceController extends PreferenceController
     }
 
     @Override
-    protected String getPreferenceKey() {
+    public String getPreferenceKey() {
         return KEY_TOGGLE_AIRPLANE;
     }
 
index 509c771..14dcf9e 100644 (file)
@@ -52,7 +52,7 @@ public class MobileNetworkPreferenceController extends PreferenceController {
     }
 
     @Override
-    protected String getPreferenceKey() {
+    public String getPreferenceKey() {
         return KEY_MOBILE_NETWORK_SETTINGS;
     }
 }
index e62686f..8dfff15 100644 (file)
@@ -120,7 +120,7 @@ public class MobilePlanPreferenceController extends PreferenceController impleme
         return isPrefAllowedForUser && isPrefAllowedOnDevice;
     }
     @Override
-    protected String getPreferenceKey() {
+    public String getPreferenceKey() {
         return KEY_MANAGE_MOBILE_PLAN;
     }
 
index 2fe2038..b313cc0 100644 (file)
@@ -43,7 +43,7 @@ public class NetworkResetPreferenceController extends PreferenceController {
     }
 
     @Override
-    protected String getPreferenceKey() {
+    public String getPreferenceKey() {
         return KEY_NETWORK_RESET;
     }
 }
index 075b1f0..5feb5d0 100644 (file)
@@ -54,7 +54,7 @@ public class ProxyPreferenceController extends PreferenceController {
     }
 
     @Override
-    protected String getPreferenceKey() {
+    public String getPreferenceKey() {
         return KEY_PROXY_SETTINGS;
     }
 }
index b3d55fa..96f037b 100644 (file)
@@ -83,7 +83,7 @@ public class TetherPreferenceController extends PreferenceController {
     }
 
     @Override
-    protected String getPreferenceKey() {
+    public String getPreferenceKey() {
         return KEY_TETHER_SETTINGS;
     }
 }
index 6e83826..0703ed3 100644 (file)
@@ -65,7 +65,7 @@ public class VpnPreferenceController extends PreferenceController {
     }
 
     @Override
-    protected String getPreferenceKey() {
+    public String getPreferenceKey() {
         return KEY_VPN_SETTINGS;
     }
 }
index e733b67..61ab92e 100644 (file)
@@ -56,7 +56,7 @@ public class WifiCallingPreferenceController extends PreferenceController {
     }
 
     @Override
-    protected String getPreferenceKey() {
+    public String getPreferenceKey() {
         return KEY_WFC_SETTINGS;
     }
 }
index 0d31fe6..b7cd702 100644 (file)
@@ -106,7 +106,7 @@ public class NfcPreferenceController extends PreferenceController
     }
 
     @Override
-    protected String getPreferenceKey() {
+    public String getPreferenceKey() {
         return null;
     }
 
index ef03d5b..9a526b1 100644 (file)
@@ -107,7 +107,7 @@ public class PreferenceControllerTest {
         }
 
         @Override
-        protected String getPreferenceKey() {
+        public String getPreferenceKey() {
             return KEY_PREF;
         }
     }
index 432be56..cc064df 100644 (file)
@@ -69,7 +69,7 @@ public class DashboardFragmentTest {
         mDashboardCategory.tiles = new ArrayList<>();
         mDashboardCategory.tiles.add(new Tile());
         mTestFragment = new TestFragment(ShadowApplication.getInstance().getApplicationContext());
-        mTestFragment.onAttach(mContext);
+        mTestFragment.onAttach(ShadowApplication.getInstance().getApplicationContext());
         when(mFakeFeatureFactory.dashboardFeatureProvider.getTilesForCategory(anyString()))
                 .thenReturn(mDashboardCategory);
     }
@@ -126,7 +126,7 @@ public class DashboardFragmentTest {
         }
 
         @Override
-        protected String getPreferenceKey() {
+        public String getPreferenceKey() {
             return null;
         }
 
diff --git a/tests/robotests/src/com/android/settings/dashboard/ProgressiveDisclosureTest.java b/tests/robotests/src/com/android/settings/dashboard/ProgressiveDisclosureTest.java
new file mode 100644 (file)
index 0000000..6964d74
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2016 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.dashboard;
+
+import android.content.Context;
+import android.support.v14.preference.PreferenceFragment;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.TestConfig;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.testutils.FakeFeatureFactory;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowApplication;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class ProgressiveDisclosureTest {
+
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private Context mContext;
+    @Mock
+    private FakeFeatureFactory mFakeFeatureFactory;
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private PreferenceFragment mPreferenceFragment;
+    private Context mAppContext;
+    private Preference mPreference;
+
+    private ProgressiveDisclosureMixin mMixin;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        FakeFeatureFactory.setupForTest(mContext);
+        mAppContext = ShadowApplication.getInstance().getApplicationContext();
+        mFakeFeatureFactory = (FakeFeatureFactory) FeatureFactory.getFactory(mContext);
+        mMixin = new ProgressiveDisclosureMixin(mAppContext, mPreferenceFragment);
+        mPreference = new Preference(mAppContext);
+        mPreference.setKey("test");
+        when(mFakeFeatureFactory.dashboardFeatureProvider.isEnabled()).thenReturn(true);
+    }
+
+    @Test
+    public void shouldNotCollapse_lessPreferenceThanLimit() {
+        when(mPreferenceFragment.getPreferenceScreen().getPreferenceCount()).thenReturn(5);
+
+        mMixin.setTileLimit(10);
+
+        assertThat(mMixin.shouldCollapse(mPreferenceFragment.getPreferenceScreen())).isFalse();
+    }
+
+    @Test
+    public void shouldCollapse_morePreferenceThanLimit() {
+        when(mFakeFeatureFactory.dashboardFeatureProvider.isEnabled()).thenReturn(true);
+        when(mPreferenceFragment.getPreferenceScreen().getPreferenceCount()).thenReturn(5);
+
+        assertThat(mMixin.shouldCollapse(mPreferenceFragment.getPreferenceScreen())).isTrue();
+    }
+
+    @Test
+    public void findPreference_prefInCollapsedList_shouldFindIt() {
+        mMixin.addToCollapsedList(mPreference);
+
+        Preference pref = mMixin.findPreference(mPreference.getKey());
+
+        assertThat(pref).isNotNull();
+        assertThat(pref).isSameAs(mPreference);
+    }
+
+    @Test
+    public void findPreference_prefNotInCollapsedList_shouldNotFindIt() {
+        Preference pref = mMixin.findPreference(mPreference.getKey());
+
+        assertThat(pref).isNull();
+    }
+
+    @Test
+    public void findPreference_prefRemovedFromCollapsedList_shouldNotFindIt() {
+        mMixin.addToCollapsedList(mPreference);
+        mMixin.removePreference(mPreferenceFragment.getPreferenceScreen(), mPreference.getKey());
+        Preference pref = mMixin.findPreference(mPreference.getKey());
+
+        assertThat(pref).isNull();
+    }
+
+    @Test
+    public void removeLastPreference_shouldRemoveExpandButtonToo() {
+        mMixin.addToCollapsedList(mPreference);
+        // Collapsed
+        assertThat(mMixin.isCollapsed()).isTrue();
+
+        mMixin.removePreference(mPreferenceFragment.getPreferenceScreen(), mPreference.getKey());
+
+        // Removing expand button
+        verify(mPreferenceFragment.getPreferenceScreen()).removePreference(any(Preference.class));
+        // No longer collapsed
+        assertThat(mMixin.isCollapsed()).isFalse();
+    }
+
+    @Test
+    public void collapse_shouldDoNothingIfNotCollapsible() {
+        final PreferenceScreen screen = mPreferenceFragment.getPreferenceScreen();
+        when(screen.getPreferenceCount()).thenReturn(5);
+        mMixin.setTileLimit(15);
+
+        mMixin.collapse(screen);
+        assertThat(mMixin.isCollapsed()).isFalse();
+        verify(screen, never()).addPreference(any(Preference.class));
+        verify(screen, never()).removePreference(any(Preference.class));
+    }
+
+    @Test
+    public void collapse_shouldRemovePrefAndAddExpandButton() {
+        final PreferenceScreen screen = mPreferenceFragment.getPreferenceScreen();
+        when(screen.getPreferenceCount()).thenReturn(5);
+        when(screen.getPreference(anyInt())).thenReturn(mPreference);
+        mMixin.setTileLimit(2);
+
+        mMixin.collapse(screen);
+
+        assertThat(mMixin.isCollapsed()).isTrue();
+        verify(screen).addPreference(any(ExpandPreference.class));
+        verify(screen, times(3)).removePreference(any(Preference.class));
+    }
+
+}