From db1112a22168e2edec56c92a00ada6718bd19898 Mon Sep 17 00:00:00 2001 From: Fan Zhang Date: Tue, 18 Oct 2016 12:58:31 -0700 Subject: [PATCH] Add progressive disclsoure - 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 --- res/layout/expand_preference.xml | 32 ++++ .../settings/core/PreferenceController.java | 14 +- .../lifecycle/ObservablePreferenceFragment.java | 2 +- .../settings/dashboard/DashboardFragment.java | 54 ++++++- .../settings/dashboard/ExpandPreference.java | 53 +++++++ .../dashboard/ProgressiveDisclosureMixin.java | 168 +++++++++++++++++++++ ...AdditionalSystemUpdatePreferenceController.java | 2 +- .../ManageStoragePreferenceController.java | 2 +- .../SystemUpdatePreferenceController.java | 2 +- .../AutoBrightnessPreferenceController.java | 12 +- .../display/AutoRotatePreferenceController.java | 9 +- .../display/CameraGesturePreferenceController.java | 15 +- .../settings/display/DozePreferenceController.java | 13 +- .../display/FontSizePreferenceController.java | 9 +- .../display/LiftToWakePreferenceController.java | 14 +- .../display/NightDisplayPreferenceController.java | 2 +- .../display/NightModePreferenceController.java | 2 +- .../display/ScreenSaverPreferenceController.java | 11 +- .../display/TapToWakePreferenceController.java | 15 +- .../display/TimeoutPreferenceController.java | 17 +-- .../display/VrDisplayPreferenceController.java | 12 +- .../display/WallpaperPreferenceController.java | 11 +- .../network/AirplaneModePreferenceController.java | 2 +- .../network/MobileNetworkPreferenceController.java | 2 +- .../network/MobilePlanPreferenceController.java | 2 +- .../network/NetworkResetPreferenceController.java | 2 +- .../network/ProxyPreferenceController.java | 2 +- .../network/TetherPreferenceController.java | 2 +- .../settings/network/VpnPreferenceController.java | 2 +- .../network/WifiCallingPreferenceController.java | 2 +- .../settings/nfc/NfcPreferenceController.java | 2 +- .../settings/core/PreferenceControllerTest.java | 2 +- .../settings/dashboard/DashboardFragmentTest.java | 4 +- .../dashboard/ProgressiveDisclosureTest.java | 156 +++++++++++++++++++ 34 files changed, 524 insertions(+), 127 deletions(-) create mode 100644 res/layout/expand_preference.xml create mode 100644 src/com/android/settings/dashboard/ExpandPreference.java create mode 100644 src/com/android/settings/dashboard/ProgressiveDisclosureMixin.java create mode 100644 tests/robotests/src/com/android/settings/dashboard/ProgressiveDisclosureTest.java diff --git a/res/layout/expand_preference.xml b/res/layout/expand_preference.xml new file mode 100644 index 0000000000..640cda7291 --- /dev/null +++ b/res/layout/expand_preference.xml @@ -0,0 +1,32 @@ + + + + + + \ No newline at end of file diff --git a/src/com/android/settings/core/PreferenceController.java b/src/com/android/settings/core/PreferenceController.java index 6eac2bd467..8a4a245391 100644 --- a/src/com/android/settings/core/PreferenceController.java +++ b/src/com/android/settings/core/PreferenceController.java @@ -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(); - } diff --git a/src/com/android/settings/core/lifecycle/ObservablePreferenceFragment.java b/src/com/android/settings/core/lifecycle/ObservablePreferenceFragment.java index e9822af1c0..dbce75558c 100644 --- a/src/com/android/settings/core/lifecycle/ObservablePreferenceFragment.java +++ b/src/com/android/settings/core/lifecycle/ObservablePreferenceFragment.java @@ -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 diff --git a/src/com/android/settings/dashboard/DashboardFragment.java b/src/com/android/settings/dashboard/DashboardFragment.java index 3d065784f1..a730939a2c 100644 --- a/src/com/android/settings/dashboard/DashboardFragment.java +++ b/src/com/android/settings/dashboard/DashboardFragment.java @@ -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 mPreferenceControllers = new ArrayMap<>(); private final Set 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 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 getPreferenceController(Class 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 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 index 0000000000..215bfc5006 --- /dev/null +++ b/src/com/android/settings/dashboard/ExpandPreference.java @@ -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 index 0000000000..28113ad276 --- /dev/null +++ b/src/com/android/settings/dashboard/ProgressiveDisclosureMixin.java @@ -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 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; + } + +} diff --git a/src/com/android/settings/deviceinfo/AdditionalSystemUpdatePreferenceController.java b/src/com/android/settings/deviceinfo/AdditionalSystemUpdatePreferenceController.java index 6dd6aba0e3..7290250dd7 100644 --- a/src/com/android/settings/deviceinfo/AdditionalSystemUpdatePreferenceController.java +++ b/src/com/android/settings/deviceinfo/AdditionalSystemUpdatePreferenceController.java @@ -40,7 +40,7 @@ public class AdditionalSystemUpdatePreferenceController extends PreferenceContro } @Override - protected String getPreferenceKey() { + public String getPreferenceKey() { return KEY_UPDATE_SETTING; } } diff --git a/src/com/android/settings/deviceinfo/ManageStoragePreferenceController.java b/src/com/android/settings/deviceinfo/ManageStoragePreferenceController.java index add4781e1d..d4d53d493d 100644 --- a/src/com/android/settings/deviceinfo/ManageStoragePreferenceController.java +++ b/src/com/android/settings/deviceinfo/ManageStoragePreferenceController.java @@ -33,7 +33,7 @@ public class ManageStoragePreferenceController extends PreferenceController { } @Override - protected String getPreferenceKey() { + public String getPreferenceKey() { return KEY_MANAGE_STORAGE; } diff --git a/src/com/android/settings/deviceinfo/SystemUpdatePreferenceController.java b/src/com/android/settings/deviceinfo/SystemUpdatePreferenceController.java index 449847a429..e086a56062 100644 --- a/src/com/android/settings/deviceinfo/SystemUpdatePreferenceController.java +++ b/src/com/android/settings/deviceinfo/SystemUpdatePreferenceController.java @@ -51,7 +51,7 @@ public class SystemUpdatePreferenceController extends PreferenceController { } @Override - protected String getPreferenceKey() { + public String getPreferenceKey() { return KEY_SYSTEM_UPDATE_SETTINGS; } diff --git a/src/com/android/settings/display/AutoBrightnessPreferenceController.java b/src/com/android/settings/display/AutoBrightnessPreferenceController.java index 934ccf2cf7..775e60c0bc 100644 --- a/src/com/android/settings/display/AutoBrightnessPreferenceController.java +++ b/src/com/android/settings/display/AutoBrightnessPreferenceController.java @@ -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 diff --git a/src/com/android/settings/display/AutoRotatePreferenceController.java b/src/com/android/settings/display/AutoRotatePreferenceController.java index f28e1d672d..44d2158390 100644 --- a/src/com/android/settings/display/AutoRotatePreferenceController.java +++ b/src/com/android/settings/display/AutoRotatePreferenceController.java @@ -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; diff --git a/src/com/android/settings/display/CameraGesturePreferenceController.java b/src/com/android/settings/display/CameraGesturePreferenceController.java index 98486c5f0e..3f5d0de513 100644 --- a/src/com/android/settings/display/CameraGesturePreferenceController.java +++ b/src/com/android/settings/display/CameraGesturePreferenceController.java @@ -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 diff --git a/src/com/android/settings/display/DozePreferenceController.java b/src/com/android/settings/display/DozePreferenceController.java index 9fcc8079f8..bf5d8f3fe5 100644 --- a/src/com/android/settings/display/DozePreferenceController.java +++ b/src/com/android/settings/display/DozePreferenceController.java @@ -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 diff --git a/src/com/android/settings/display/FontSizePreferenceController.java b/src/com/android/settings/display/FontSizePreferenceController.java index 9981fcd36a..fcd423d763 100644 --- a/src/com/android/settings/display/FontSizePreferenceController.java +++ b/src/com/android/settings/display/FontSizePreferenceController.java @@ -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(); diff --git a/src/com/android/settings/display/LiftToWakePreferenceController.java b/src/com/android/settings/display/LiftToWakePreferenceController.java index 0b573cf827..c518f6880b 100644 --- a/src/com/android/settings/display/LiftToWakePreferenceController.java +++ b/src/com/android/settings/display/LiftToWakePreferenceController.java @@ -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); } } diff --git a/src/com/android/settings/display/NightDisplayPreferenceController.java b/src/com/android/settings/display/NightDisplayPreferenceController.java index d7191d2035..c52df23bbb 100644 --- a/src/com/android/settings/display/NightDisplayPreferenceController.java +++ b/src/com/android/settings/display/NightDisplayPreferenceController.java @@ -38,7 +38,7 @@ public class NightDisplayPreferenceController extends PreferenceController { } @Override - protected String getPreferenceKey() { + public String getPreferenceKey() { return KEY_NIGHT_DISPLAY; } } diff --git a/src/com/android/settings/display/NightModePreferenceController.java b/src/com/android/settings/display/NightModePreferenceController.java index 7b3c584d5d..c0f0c17a40 100644 --- a/src/com/android/settings/display/NightModePreferenceController.java +++ b/src/com/android/settings/display/NightModePreferenceController.java @@ -40,7 +40,7 @@ public class NightModePreferenceController extends PreferenceController } @Override - protected String getPreferenceKey() { + public String getPreferenceKey() { return KEY_NIGHT_MODE; } diff --git a/src/com/android/settings/display/ScreenSaverPreferenceController.java b/src/com/android/settings/display/ScreenSaverPreferenceController.java index 6376fcfe65..64d9dec548 100644 --- a/src/com/android/settings/display/ScreenSaverPreferenceController.java +++ b/src/com/android/settings/display/ScreenSaverPreferenceController.java @@ -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)); } } diff --git a/src/com/android/settings/display/TapToWakePreferenceController.java b/src/com/android/settings/display/TapToWakePreferenceController.java index 6d1681f745..4c5aaa0177 100644 --- a/src/com/android/settings/display/TapToWakePreferenceController.java +++ b/src/com/android/settings/display/TapToWakePreferenceController.java @@ -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 diff --git a/src/com/android/settings/display/TimeoutPreferenceController.java b/src/com/android/settings/display/TimeoutPreferenceController.java index 1295a47503..8c73c31d0d 100644 --- a/src/com/android/settings/display/TimeoutPreferenceController.java +++ b/src/com/android/settings/display/TimeoutPreferenceController.java @@ -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 diff --git a/src/com/android/settings/display/VrDisplayPreferenceController.java b/src/com/android/settings/display/VrDisplayPreferenceController.java index c340759cfc..84d7462017 100644 --- a/src/com/android/settings/display/VrDisplayPreferenceController.java +++ b/src/com/android/settings/display/VrDisplayPreferenceController.java @@ -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), diff --git a/src/com/android/settings/display/WallpaperPreferenceController.java b/src/com/android/settings/display/WallpaperPreferenceController.java index 32e9abcea0..29415e9a3f 100644 --- a/src/com/android/settings/display/WallpaperPreferenceController.java +++ b/src/com/android/settings/display/WallpaperPreferenceController.java @@ -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); diff --git a/src/com/android/settings/network/AirplaneModePreferenceController.java b/src/com/android/settings/network/AirplaneModePreferenceController.java index c99cd4d647..bd1918f537 100644 --- a/src/com/android/settings/network/AirplaneModePreferenceController.java +++ b/src/com/android/settings/network/AirplaneModePreferenceController.java @@ -92,7 +92,7 @@ public class AirplaneModePreferenceController extends PreferenceController } @Override - protected String getPreferenceKey() { + public String getPreferenceKey() { return KEY_TOGGLE_AIRPLANE; } diff --git a/src/com/android/settings/network/MobileNetworkPreferenceController.java b/src/com/android/settings/network/MobileNetworkPreferenceController.java index 509c7711bf..14dcf9eba9 100644 --- a/src/com/android/settings/network/MobileNetworkPreferenceController.java +++ b/src/com/android/settings/network/MobileNetworkPreferenceController.java @@ -52,7 +52,7 @@ public class MobileNetworkPreferenceController extends PreferenceController { } @Override - protected String getPreferenceKey() { + public String getPreferenceKey() { return KEY_MOBILE_NETWORK_SETTINGS; } } diff --git a/src/com/android/settings/network/MobilePlanPreferenceController.java b/src/com/android/settings/network/MobilePlanPreferenceController.java index e62686fa11..8dfff150b7 100644 --- a/src/com/android/settings/network/MobilePlanPreferenceController.java +++ b/src/com/android/settings/network/MobilePlanPreferenceController.java @@ -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; } diff --git a/src/com/android/settings/network/NetworkResetPreferenceController.java b/src/com/android/settings/network/NetworkResetPreferenceController.java index 2fe2038afe..b313cc01f2 100644 --- a/src/com/android/settings/network/NetworkResetPreferenceController.java +++ b/src/com/android/settings/network/NetworkResetPreferenceController.java @@ -43,7 +43,7 @@ public class NetworkResetPreferenceController extends PreferenceController { } @Override - protected String getPreferenceKey() { + public String getPreferenceKey() { return KEY_NETWORK_RESET; } } diff --git a/src/com/android/settings/network/ProxyPreferenceController.java b/src/com/android/settings/network/ProxyPreferenceController.java index 075b1f0555..5feb5d07b2 100644 --- a/src/com/android/settings/network/ProxyPreferenceController.java +++ b/src/com/android/settings/network/ProxyPreferenceController.java @@ -54,7 +54,7 @@ public class ProxyPreferenceController extends PreferenceController { } @Override - protected String getPreferenceKey() { + public String getPreferenceKey() { return KEY_PROXY_SETTINGS; } } diff --git a/src/com/android/settings/network/TetherPreferenceController.java b/src/com/android/settings/network/TetherPreferenceController.java index b3d55fac8f..96f037b783 100644 --- a/src/com/android/settings/network/TetherPreferenceController.java +++ b/src/com/android/settings/network/TetherPreferenceController.java @@ -83,7 +83,7 @@ public class TetherPreferenceController extends PreferenceController { } @Override - protected String getPreferenceKey() { + public String getPreferenceKey() { return KEY_TETHER_SETTINGS; } } diff --git a/src/com/android/settings/network/VpnPreferenceController.java b/src/com/android/settings/network/VpnPreferenceController.java index 6e838268b8..0703ed36e1 100644 --- a/src/com/android/settings/network/VpnPreferenceController.java +++ b/src/com/android/settings/network/VpnPreferenceController.java @@ -65,7 +65,7 @@ public class VpnPreferenceController extends PreferenceController { } @Override - protected String getPreferenceKey() { + public String getPreferenceKey() { return KEY_VPN_SETTINGS; } } diff --git a/src/com/android/settings/network/WifiCallingPreferenceController.java b/src/com/android/settings/network/WifiCallingPreferenceController.java index e733b670a7..61ab92e2b7 100644 --- a/src/com/android/settings/network/WifiCallingPreferenceController.java +++ b/src/com/android/settings/network/WifiCallingPreferenceController.java @@ -56,7 +56,7 @@ public class WifiCallingPreferenceController extends PreferenceController { } @Override - protected String getPreferenceKey() { + public String getPreferenceKey() { return KEY_WFC_SETTINGS; } } diff --git a/src/com/android/settings/nfc/NfcPreferenceController.java b/src/com/android/settings/nfc/NfcPreferenceController.java index 0d31fe6f39..b7cd702668 100644 --- a/src/com/android/settings/nfc/NfcPreferenceController.java +++ b/src/com/android/settings/nfc/NfcPreferenceController.java @@ -106,7 +106,7 @@ public class NfcPreferenceController extends PreferenceController } @Override - protected String getPreferenceKey() { + public String getPreferenceKey() { return null; } diff --git a/tests/robotests/src/com/android/settings/core/PreferenceControllerTest.java b/tests/robotests/src/com/android/settings/core/PreferenceControllerTest.java index ef03d5babb..9a526b106d 100644 --- a/tests/robotests/src/com/android/settings/core/PreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/core/PreferenceControllerTest.java @@ -107,7 +107,7 @@ public class PreferenceControllerTest { } @Override - protected String getPreferenceKey() { + public String getPreferenceKey() { return KEY_PREF; } } diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java index 432be56b26..cc064df87e 100644 --- a/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java +++ b/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java @@ -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 index 0000000000..6964d7463c --- /dev/null +++ b/tests/robotests/src/com/android/settings/dashboard/ProgressiveDisclosureTest.java @@ -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)); + } + +} -- 2.11.0