diff --git a/proguard.flags b/proguard.flags index 3e12283d28..01302cfb54 100644 --- a/proguard.flags +++ b/proguard.flags @@ -2,12 +2,6 @@ *; } -# Proguard will strip new callbacks in LauncherApps.Callback from -# WrappedCallback if compiled against an older SDK. Don't let this happen. --keep class com.android.launcher3.compat.** { - *; -} - -keep class com.android.launcher3.graphics.ShadowDrawable { public (...); } diff --git a/quickstep/src/com/android/launcher3/uioverrides/TogglableFlag.java b/quickstep/src/com/android/launcher3/uioverrides/DeviceFlag.java similarity index 59% rename from quickstep/src/com/android/launcher3/uioverrides/TogglableFlag.java rename to quickstep/src/com/android/launcher3/uioverrides/DeviceFlag.java index 27d81eff06..3c3f397dff 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/TogglableFlag.java +++ b/quickstep/src/com/android/launcher3/uioverrides/DeviceFlag.java @@ -16,22 +16,28 @@ package com.android.launcher3.uioverrides; +import android.annotation.TargetApi; import android.content.Context; +import android.os.Build; import android.provider.DeviceConfig; -import com.android.launcher3.config.FeatureFlags.BaseTogglableFlag; +import com.android.launcher3.config.FeatureFlags.DebugFlag; + +@TargetApi(Build.VERSION_CODES.P) +public class DeviceFlag extends DebugFlag { -public class TogglableFlag extends BaseTogglableFlag { public static final String NAMESPACE_LAUNCHER = "launcher"; - public static final String TAG = "TogglableFlag"; - public TogglableFlag(String key, boolean defaultValue, String description) { - super(key, defaultValue, description); + private final boolean mDefaultValueInCode; + + public DeviceFlag(String key, boolean defaultValue, String description) { + super(key, getDeviceValue(key, defaultValue), description); + mDefaultValueInCode = defaultValue; } @Override - public boolean getOverridenDefaultValue(boolean value) { - return DeviceConfig.getBoolean(NAMESPACE_LAUNCHER, getKey(), value); + protected StringBuilder appendProps(StringBuilder src) { + return super.appendProps(src).append(", mDefaultValueInCode=").append(mDefaultValueInCode); } @Override @@ -39,12 +45,17 @@ public class TogglableFlag extends BaseTogglableFlag { DeviceConfig.addOnPropertiesChangedListener( NAMESPACE_LAUNCHER, context.getMainExecutor(), - (properties) -> { + properties -> { if (!NAMESPACE_LAUNCHER.equals(properties.getNamespace())) { return; } + defaultValue = getDeviceValue(key, mDefaultValueInCode); initialize(context); r.run(); }); } + + protected static boolean getDeviceValue(String key, boolean defaultValue) { + return DeviceConfig.getBoolean(NAMESPACE_LAUNCHER, key, defaultValue); + } } diff --git a/robolectric_tests/src/com/android/launcher3/config/FlagOverrideRule.java b/robolectric_tests/src/com/android/launcher3/config/FlagOverrideRule.java deleted file mode 100644 index d33fecd0cb..0000000000 --- a/robolectric_tests/src/com/android/launcher3/config/FlagOverrideRule.java +++ /dev/null @@ -1,117 +0,0 @@ -package com.android.launcher3.config; - - -import com.android.launcher3.config.FeatureFlags.BaseTogglableFlag; -import com.android.launcher3.uioverrides.TogglableFlag; - -import org.junit.rules.TestRule; -import org.junit.runner.Description; -import org.junit.runners.model.Statement; - -import java.lang.annotation.Annotation; -import java.lang.annotation.ElementType; -import java.lang.annotation.Repeatable; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; - -/** - * Test rule that makes overriding flags in Robolectric tests easier. This rule clears all flags - * before and after your test, avoiding one test method affecting subsequent methods. - * - *

Usage: - *

- * {@literal @}Rule public final FlagOverrideRule flags = new FlagOverrideRule();
- *
- * {@literal @}FlagOverride(flag = "FOO", value=true)
- * {@literal @}Test public void myTest() {
- *     ...
- * }
- * 
- */ -public final class FlagOverrideRule implements TestRule { - - private final HashMap mDefaultOverrides = new HashMap<>(); - - /** - * Container annotation for handling multiple {@link FlagOverride} annotations. - *

- *

Don't use this directly, use repeated {@link FlagOverride} annotations instead. - */ - @Retention(RetentionPolicy.RUNTIME) - @Target({ElementType.METHOD}) - public @interface FlagOverrides { - FlagOverride[] value(); - } - - @Retention(RetentionPolicy.RUNTIME) - @Target({ElementType.METHOD}) - @Repeatable(FlagOverrides.class) - public @interface FlagOverride { - String key(); - - boolean value(); - } - - @Override - public Statement apply(Statement base, Description description) { - return new MyStatement(base, description); - } - - /** - * Sets a default override to apply on all tests - */ - public FlagOverrideRule setOverride(BaseTogglableFlag flag, boolean value) { - mDefaultOverrides.put(flag.getKey(), value); - return this; - } - - private class MyStatement extends Statement { - - private final Statement mBase; - private final Description mDescription; - - - MyStatement(Statement base, Description description) { - mBase = base; - mDescription = description; - } - - @Override - public void evaluate() throws Throwable { - Map allFlags = FeatureFlags.getTogglableFlags().stream() - .collect(Collectors.toMap(TogglableFlag::getKey, Function.identity())); - - HashMap changedValues = new HashMap<>(); - FlagOverride[] overrides = new FlagOverride[0]; - try { - for (Annotation annotation : mDescription.getAnnotations()) { - if (annotation.annotationType() == FlagOverride.class) { - overrides = new FlagOverride[] { (FlagOverride) annotation }; - } else if (annotation.annotationType() == FlagOverrides.class) { - // Note: this branch is hit if the annotation is repeated - overrides = ((FlagOverrides) annotation).value(); - } - } - - HashMap allOverrides = new HashMap<>(mDefaultOverrides); - Arrays.stream(overrides).forEach(o -> allOverrides.put(o.key(), o.value())); - - allOverrides.forEach((key, val) -> { - BaseTogglableFlag flag = allFlags.get(key); - changedValues.put(flag, flag.get()); - flag.setForTests(val); - }); - mBase.evaluate(); - } finally { - // Clear the values - changedValues.forEach(BaseTogglableFlag::setForTests); - } - } - } -} diff --git a/robolectric_tests/src/com/android/launcher3/config/FlagOverrideSampleTest.java b/robolectric_tests/src/com/android/launcher3/config/FlagOverrideSampleTest.java deleted file mode 100644 index 2a359dfb32..0000000000 --- a/robolectric_tests/src/com/android/launcher3/config/FlagOverrideSampleTest.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.android.launcher3.config; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import com.android.launcher3.config.FlagOverrideRule.FlagOverride; -import com.android.launcher3.util.LauncherRoboTestRunner; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * Sample Robolectric test that demonstrates flag-overriding. - */ -@RunWith(LauncherRoboTestRunner.class) -public class FlagOverrideSampleTest { - - // Check out https://junit.org/junit4/javadoc/4.12/org/junit/Rule.html for more information - // on @Rules. - @Rule - public final FlagOverrideRule flags = new FlagOverrideRule(); - - /** - * Test if flag can be overriden to true via annoation. - */ - @FlagOverride(key = "FAKE_LANDSCAPE_UI", value = true) - @Test - public void withFlagOn() { - assertTrue(FeatureFlags.FAKE_LANDSCAPE_UI.get()); - } - - /** - * Test if flag can be overriden to false via annoation. - */ - @FlagOverride(key = "FAKE_LANDSCAPE_UI", value = false) - @Test - public void withFlagOff() { - assertFalse(FeatureFlags.FAKE_LANDSCAPE_UI.get()); - } -} diff --git a/robolectric_tests/src/com/android/launcher3/shadows/ShadowTogglableFlag.java b/robolectric_tests/src/com/android/launcher3/shadows/ShadowDeviceFlag.java similarity index 80% rename from robolectric_tests/src/com/android/launcher3/shadows/ShadowTogglableFlag.java rename to robolectric_tests/src/com/android/launcher3/shadows/ShadowDeviceFlag.java index 3603dd834d..344f53206f 100644 --- a/robolectric_tests/src/com/android/launcher3/shadows/ShadowTogglableFlag.java +++ b/robolectric_tests/src/com/android/launcher3/shadows/ShadowDeviceFlag.java @@ -18,7 +18,7 @@ package com.android.launcher3.shadows; import android.content.Context; -import com.android.launcher3.uioverrides.TogglableFlag; +import com.android.launcher3.uioverrides.DeviceFlag; import com.android.launcher3.util.LooperExecutor; import org.robolectric.annotation.Implementation; @@ -27,12 +27,17 @@ import org.robolectric.annotation.Implements; /** * Shadow for {@link LooperExecutor} to provide reset functionality for static executors. */ -@Implements(value = TogglableFlag.class, isInAndroidSdk = false) -public class ShadowTogglableFlag { +@Implements(value = DeviceFlag.class, isInAndroidSdk = false) +public class ShadowDeviceFlag { /** * Mock change listener as it uses internal system classes not available to robolectric */ @Implementation protected void addChangeListener(Context context, Runnable r) { } + + @Implementation + protected static boolean getDeviceValue(String key, boolean defaultValue) { + return defaultValue; + } } diff --git a/robolectric_tests/src/com/android/launcher3/util/LauncherRoboTestRunner.java b/robolectric_tests/src/com/android/launcher3/util/LauncherRoboTestRunner.java index 5c6b486ea5..b8fff9cc1d 100644 --- a/robolectric_tests/src/com/android/launcher3/util/LauncherRoboTestRunner.java +++ b/robolectric_tests/src/com/android/launcher3/util/LauncherRoboTestRunner.java @@ -23,7 +23,7 @@ import com.android.launcher3.shadows.LShadowLauncherApps; import com.android.launcher3.shadows.LShadowUserManager; import com.android.launcher3.shadows.ShadowLooperExecutor; import com.android.launcher3.shadows.ShadowMainThreadInitializedObject; -import com.android.launcher3.shadows.ShadowTogglableFlag; +import com.android.launcher3.shadows.ShadowDeviceFlag; import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper; import org.junit.runners.model.InitializationError; @@ -50,7 +50,7 @@ public class LauncherRoboTestRunner extends RobolectricTestRunner { ShadowLooperExecutor.class, ShadowMainThreadInitializedObject.class, - ShadowTogglableFlag.class, + ShadowDeviceFlag.class, }; public LauncherRoboTestRunner(Class testClass) throws InitializationError { diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java index f10aca509e..d63d2dde80 100644 --- a/src/com/android/launcher3/config/FeatureFlags.java +++ b/src/com/android/launcher3/config/FeatureFlags.java @@ -16,37 +16,25 @@ package com.android.launcher3.config; -import static androidx.core.util.Preconditions.checkNotNull; - import android.content.Context; -import android.content.SharedPreferences; - -import androidx.annotation.GuardedBy; -import androidx.annotation.Keep; -import androidx.annotation.VisibleForTesting; import com.android.launcher3.BuildConfig; import com.android.launcher3.Utilities; -import com.android.launcher3.uioverrides.TogglableFlag; +import com.android.launcher3.uioverrides.DeviceFlag; import java.util.ArrayList; import java.util.List; -import java.util.SortedMap; -import java.util.TreeMap; /** * Defines a set of flags used to control various launcher behaviors. * *

All the flags should be defined here with appropriate default values. */ -@Keep public final class FeatureFlags { - private static final Object sLock = new Object(); - @GuardedBy("sLock") - private static final List sFlags = new ArrayList<>(); + private static final List sDebugFlags = new ArrayList<>(); - static final String FLAGS_PREF_NAME = "featureFlags"; + public static final String FLAGS_PREF_NAME = "featureFlags"; private FeatureFlags() { } @@ -62,7 +50,6 @@ public final class FeatureFlags { */ public static final boolean QSB_ON_FIRST_SCREEN = true; - /** * Feature flag to handle define config changes dynamically instead of killing the process. * @@ -73,70 +60,66 @@ public final class FeatureFlags { * and set a default value for the flag. This will be the default value on Debug builds. */ // When enabled the promise icon is visible in all apps while installation an app. - public static final TogglableFlag PROMISE_APPS_IN_ALL_APPS = new TogglableFlag( + public static final BooleanFlag PROMISE_APPS_IN_ALL_APPS = getDebugFlag( "PROMISE_APPS_IN_ALL_APPS", false, "Add promise icon in all-apps"); // When enabled a promise icon is added to the home screen when install session is active. - public static final TogglableFlag PROMISE_APPS_NEW_INSTALLS = - new TogglableFlag("PROMISE_APPS_NEW_INSTALLS", true, - "Adds a promise icon to the home screen for new install sessions."); + public static final BooleanFlag PROMISE_APPS_NEW_INSTALLS = getDebugFlag( + "PROMISE_APPS_NEW_INSTALLS", true, + "Adds a promise icon to the home screen for new install sessions."); - public static final TogglableFlag APPLY_CONFIG_AT_RUNTIME = new TogglableFlag( + public static final BooleanFlag APPLY_CONFIG_AT_RUNTIME = getDebugFlag( "APPLY_CONFIG_AT_RUNTIME", true, "Apply display changes dynamically"); - public static final TogglableFlag QUICKSTEP_SPRINGS = new TogglableFlag("QUICKSTEP_SPRINGS", - true, "Enable springs for quickstep animations"); + public static final BooleanFlag QUICKSTEP_SPRINGS = getDebugFlag( + "QUICKSTEP_SPRINGS", true, "Enable springs for quickstep animations"); - public static final TogglableFlag UNSTABLE_SPRINGS = new TogglableFlag("UNSTABLE_SPRINGS", - false, "Enable unstable springs for quickstep animations"); + public static final BooleanFlag UNSTABLE_SPRINGS = getDebugFlag( + "UNSTABLE_SPRINGS", false, "Enable unstable springs for quickstep animations"); - public static final TogglableFlag ADAPTIVE_ICON_WINDOW_ANIM = new TogglableFlag( - "ADAPTIVE_ICON_WINDOW_ANIM", true, - "Use adaptive icons for window animations."); + public static final BooleanFlag ADAPTIVE_ICON_WINDOW_ANIM = getDebugFlag( + "ADAPTIVE_ICON_WINDOW_ANIM", true, "Use adaptive icons for window animations."); - public static final TogglableFlag ENABLE_QUICKSTEP_LIVE_TILE = new TogglableFlag( + public static final BooleanFlag ENABLE_QUICKSTEP_LIVE_TILE = getDebugFlag( "ENABLE_QUICKSTEP_LIVE_TILE", false, "Enable live tile in Quickstep overview"); - public static final TogglableFlag ENABLE_HINTS_IN_OVERVIEW = new TogglableFlag( - "ENABLE_HINTS_IN_OVERVIEW", false, - "Show chip hints and gleams on the overview screen"); + public static final BooleanFlag ENABLE_HINTS_IN_OVERVIEW = getDebugFlag( + "ENABLE_HINTS_IN_OVERVIEW", false, "Show chip hints and gleams on the overview screen"); - public static final TogglableFlag FAKE_LANDSCAPE_UI = new TogglableFlag( - "FAKE_LANDSCAPE_UI", false, - "Rotate launcher UI instead of using transposed layout"); + public static final BooleanFlag FAKE_LANDSCAPE_UI = getDebugFlag( + "FAKE_LANDSCAPE_UI", false, "Rotate launcher UI instead of using transposed layout"); - public static final TogglableFlag FOLDER_NAME_SUGGEST = new TogglableFlag( - "FOLDER_NAME_SUGGEST", true, - "Suggests folder names instead of blank text."); + public static final BooleanFlag FOLDER_NAME_SUGGEST = getDebugFlag( + "FOLDER_NAME_SUGGEST", true, "Suggests folder names instead of blank text."); - public static final TogglableFlag APP_SEARCH_IMPROVEMENTS = new TogglableFlag( + public static final BooleanFlag APP_SEARCH_IMPROVEMENTS = new DeviceFlag( "APP_SEARCH_IMPROVEMENTS", false, "Adds localized title and keyword search and ranking"); - public static final TogglableFlag ENABLE_PREDICTION_DISMISS = new TogglableFlag( + public static final BooleanFlag ENABLE_PREDICTION_DISMISS = getDebugFlag( "ENABLE_PREDICTION_DISMISS", false, "Allow option to dimiss apps from predicted list"); - public static final TogglableFlag ENABLE_QUICK_CAPTURE_GESTURE = new TogglableFlag( + public static final BooleanFlag ENABLE_QUICK_CAPTURE_GESTURE = getDebugFlag( "ENABLE_QUICK_CAPTURE_GESTURE", true, "Swipe from right to left to quick capture"); - public static final TogglableFlag ASSISTANT_GIVES_LAUNCHER_FOCUS = new TogglableFlag( + public static final BooleanFlag ASSISTANT_GIVES_LAUNCHER_FOCUS = getDebugFlag( "ASSISTANT_GIVES_LAUNCHER_FOCUS", false, "Allow Launcher to handle nav bar gestures while Assistant is running over it"); - public static final TogglableFlag ENABLE_HYBRID_HOTSEAT = new TogglableFlag( + public static final BooleanFlag ENABLE_HYBRID_HOTSEAT = getDebugFlag( "ENABLE_HYBRID_HOTSEAT", false, "Fill gaps in hotseat with predicted apps"); - public static final TogglableFlag ENABLE_DEEP_SHORTCUT_ICON_CACHE = new TogglableFlag( + public static final BooleanFlag ENABLE_DEEP_SHORTCUT_ICON_CACHE = getDebugFlag( "ENABLE_DEEP_SHORTCUT_ICON_CACHE", true, "R/W deep shortcut in IconCache"); - public static final TogglableFlag ENABLE_LAUNCHER_PREVIEW_IN_GRID_PICKER = new TogglableFlag( + public static final BooleanFlag ENABLE_LAUNCHER_PREVIEW_IN_GRID_PICKER = getDebugFlag( "ENABLE_LAUNCHER_PREVIEW_IN_GRID_PICKER", false, "Show launcher preview in grid picker"); - public static final TogglableFlag ENABLE_OVERVIEW_ACTIONS = new TogglableFlag( + public static final BooleanFlag ENABLE_OVERVIEW_ACTIONS = getDebugFlag( "ENABLE_OVERVIEW_ACTIONS", false, "Show app actions in Overview"); - public static final TogglableFlag ENABLE_DATABASE_RESTORE = new TogglableFlag( + public static final BooleanFlag ENABLE_DATABASE_RESTORE = getDebugFlag( "ENABLE_DATABASE_RESTORE", true, "Enable database restore when new restore session is created"); @@ -145,126 +128,81 @@ public final class FeatureFlags { "Replace Smartspace with a version rendered by System UI."); public static void initialize(Context context) { - // Avoid the disk read for user builds - if (Utilities.IS_DEBUG_DEVICE) { - synchronized (sLock) { - for (BaseTogglableFlag flag : sFlags) { - flag.initialize(context); - } + synchronized (sDebugFlags) { + for (DebugFlag flag : sDebugFlags) { + flag.initialize(context); } } } - static List getTogglableFlags() { - // By Java Language Spec 12.4.2 - // https://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4.2, the - // TogglableFlag instances on FeatureFlags will be created before those on the FeatureFlags - // subclass. This code handles flags that are redeclared in FeatureFlags, ensuring the - // FeatureFlags one takes priority. - SortedMap flagsByKey = new TreeMap<>(); - synchronized (sLock) { - for (TogglableFlag flag : sFlags) { - flagsByKey.put(flag.getKey(), flag); - } + static List getDebugFlags() { + synchronized (sDebugFlags) { + return new ArrayList<>(sDebugFlags); } - return new ArrayList<>(flagsByKey.values()); } - public static abstract class BaseTogglableFlag { - private final String key; - // should be value that is hardcoded in client side. - // Comparatively, getDefaultValue() can be overridden. - private final boolean defaultValue; - private final String description; - private boolean currentValue; + public static class BooleanFlag { - public BaseTogglableFlag( - String key, - boolean defaultValue, - String description) { - this.key = checkNotNull(key); - this.currentValue = this.defaultValue = defaultValue; - this.description = checkNotNull(description); + public final String key; + public boolean defaultValue; - synchronized (sLock) { - sFlags.add((TogglableFlag)this); - } + public BooleanFlag(String key, boolean defaultValue) { + this.key = key; + this.defaultValue = defaultValue; } - /** Set the value of this flag. This should only be used in tests. */ - @VisibleForTesting - void setForTests(boolean value) { - currentValue = value; - } - - public String getKey() { - return key; - } - - protected void initialize(Context context) { - currentValue = getFromStorage(context, getDefaultValue()); - } - - protected abstract boolean getOverridenDefaultValue(boolean value); - - protected abstract void addChangeListener(Context context, Runnable r); - - public void updateStorage(Context context, boolean value) { - SharedPreferences.Editor editor = context.getSharedPreferences(FLAGS_PREF_NAME, - Context.MODE_PRIVATE).edit(); - if (value == getDefaultValue()) { - editor.remove(key).apply(); - } else { - editor.putBoolean(key, value).apply(); - } - } - - boolean getFromStorage(Context context, boolean defaultValue) { - return context.getSharedPreferences(FLAGS_PREF_NAME, Context.MODE_PRIVATE) - .getBoolean(key, getDefaultValue()); - } - - boolean getDefaultValue() { - return getOverridenDefaultValue(defaultValue); - } - - /** Returns the value of the flag at process start, including any overrides present. */ public boolean get() { - return currentValue; - } - - String getDescription() { - return description; + return defaultValue; } @Override public String toString() { - return "TogglableFlag{" - + "key=" + key + ", " - + "defaultValue=" + defaultValue + ", " - + "overriddenDefaultValue=" + getOverridenDefaultValue(defaultValue) + ", " - + "currentValue=" + currentValue + ", " - + "description=" + description - + "}"; + return appendProps(new StringBuilder() + .append(getClass().getSimpleName()).append('{')) + .append('}').toString(); + } + + protected StringBuilder appendProps(StringBuilder src) { + return src.append("key=").append(key).append(", defaultValue=").append(defaultValue); + } + + public void addChangeListener(Context context, Runnable r) { } + } + + public static class DebugFlag extends BooleanFlag { + + public final String description; + private boolean mCurrentValue; + + public DebugFlag(String key, boolean defaultValue, String description) { + super(key, defaultValue); + this.description = description; + mCurrentValue = this.defaultValue; + synchronized (sDebugFlags) { + sDebugFlags.add(this); + } } @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (o instanceof TogglableFlag) { - BaseTogglableFlag that = (BaseTogglableFlag) o; - return (this.key.equals(that.getKey())) - && (this.getDefaultValue() == that.getDefaultValue()) - && (this.description.equals(that.getDescription())); - } - return false; + public boolean get() { + return mCurrentValue; + } + + public void initialize(Context context) { + mCurrentValue = context.getSharedPreferences(FLAGS_PREF_NAME, Context.MODE_PRIVATE) + .getBoolean(key, defaultValue); } @Override - public int hashCode() { - return key.hashCode(); + protected StringBuilder appendProps(StringBuilder src) { + return super.appendProps(src).append(", mCurrentValue=").append(mCurrentValue) + .append(", description=").append(description); } } + + private static BooleanFlag getDebugFlag(String key, boolean defaultValue, String description) { + return Utilities.IS_DEBUG_DEVICE + ? new DebugFlag(key, defaultValue, description) + : new BooleanFlag(key, defaultValue); + } } diff --git a/src/com/android/launcher3/config/FlagTogglerPrefUi.java b/src/com/android/launcher3/config/FlagTogglerPrefUi.java index a7e3732397..6729f7434f 100644 --- a/src/com/android/launcher3/config/FlagTogglerPrefUi.java +++ b/src/com/android/launcher3/config/FlagTogglerPrefUi.java @@ -16,6 +16,8 @@ package com.android.launcher3.config; +import static com.android.launcher3.config.FeatureFlags.FLAGS_PREF_NAME; + import android.content.Context; import android.content.SharedPreferences; import android.os.Process; @@ -31,8 +33,7 @@ import androidx.preference.PreferenceGroup; import androidx.preference.SwitchPreference; import com.android.launcher3.R; -import com.android.launcher3.config.FeatureFlags.BaseTogglableFlag; -import com.android.launcher3.uioverrides.TogglableFlag; +import com.android.launcher3.config.FeatureFlags.DebugFlag; /** * Dev-build only UI allowing developers to toggle flag settings. See {@link FeatureFlags}. @@ -49,23 +50,26 @@ public final class FlagTogglerPrefUi { @Override public void putBoolean(String key, boolean value) { - for (TogglableFlag flag : FeatureFlags.getTogglableFlags()) { - if (flag.getKey().equals(key)) { - boolean prevValue = flag.get(); - flag.updateStorage(mContext, value); - updateMenu(); - if (flag.get() != prevValue) { - Toast.makeText(mContext, "Flag applied", Toast.LENGTH_SHORT).show(); + for (DebugFlag flag : FeatureFlags.getDebugFlags()) { + if (flag.key.equals(key)) { + SharedPreferences.Editor editor = mContext.getSharedPreferences( + FLAGS_PREF_NAME, Context.MODE_PRIVATE).edit(); + if (value == flag.defaultValue) { + editor.remove(key).apply(); + } else { + editor.putBoolean(key, value).apply(); } + updateMenu(); } } } @Override public boolean getBoolean(String key, boolean defaultValue) { - for (BaseTogglableFlag flag : FeatureFlags.getTogglableFlags()) { - if (flag.getKey().equals(key)) { - return flag.getFromStorage(mContext, defaultValue); + for (DebugFlag flag : FeatureFlags.getDebugFlags()) { + if (flag.key.equals(key)) { + return mContext.getSharedPreferences(FLAGS_PREF_NAME, Context.MODE_PRIVATE) + .getBoolean(key, flag.defaultValue); } } return defaultValue; @@ -76,7 +80,7 @@ public final class FlagTogglerPrefUi { mFragment = fragment; mContext = fragment.getActivity(); mSharedPreferences = mContext.getSharedPreferences( - FeatureFlags.FLAGS_PREF_NAME, Context.MODE_PRIVATE); + FLAGS_PREF_NAME, Context.MODE_PRIVATE); } public void applyTo(PreferenceGroup parent) { @@ -84,12 +88,12 @@ public final class FlagTogglerPrefUi { // flag with a different value than the default. That way, when we flip flags in // future, engineers will pick up the new value immediately. To accomplish this, we use a // custom preference data store. - for (BaseTogglableFlag flag : FeatureFlags.getTogglableFlags()) { + for (DebugFlag flag : FeatureFlags.getDebugFlags()) { SwitchPreference switchPreference = new SwitchPreference(mContext); - switchPreference.setKey(flag.getKey()); - switchPreference.setDefaultValue(flag.getDefaultValue()); + switchPreference.setKey(flag.key); + switchPreference.setDefaultValue(flag.defaultValue); switchPreference.setChecked(getFlagStateFromSharedPrefs(flag)); - switchPreference.setTitle(flag.getKey()); + switchPreference.setTitle(flag.key); updateSummary(switchPreference, flag); switchPreference.setPreferenceDataStore(mDataStore); parent.addPreference(switchPreference); @@ -100,11 +104,11 @@ public final class FlagTogglerPrefUi { /** * Updates the summary to show the description and whether the flag overrides the default value. */ - private void updateSummary(SwitchPreference switchPreference, BaseTogglableFlag flag) { - String onWarning = flag.getDefaultValue() ? "" : "OVERRIDDEN
"; - String offWarning = flag.getDefaultValue() ? "OVERRIDDEN
" : ""; - switchPreference.setSummaryOn(Html.fromHtml(onWarning + flag.getDescription())); - switchPreference.setSummaryOff(Html.fromHtml(offWarning + flag.getDescription())); + private void updateSummary(SwitchPreference switchPreference, DebugFlag flag) { + String onWarning = flag.defaultValue ? "" : "OVERRIDDEN
"; + String offWarning = flag.defaultValue ? "OVERRIDDEN
" : ""; + switchPreference.setSummaryOn(Html.fromHtml(onWarning + flag.description)); + switchPreference.setSummaryOff(Html.fromHtml(offWarning + flag.description)); } private void updateMenu() { @@ -135,12 +139,12 @@ public final class FlagTogglerPrefUi { } } - private boolean getFlagStateFromSharedPrefs(BaseTogglableFlag flag) { - return mDataStore.getBoolean(flag.getKey(), flag.getDefaultValue()); + private boolean getFlagStateFromSharedPrefs(DebugFlag flag) { + return mDataStore.getBoolean(flag.key, flag.defaultValue); } private boolean anyChanged() { - for (TogglableFlag flag : FeatureFlags.getTogglableFlags()) { + for (DebugFlag flag : FeatureFlags.getDebugFlags()) { if (getFlagStateFromSharedPrefs(flag) != flag.get()) { return true; } diff --git a/src/com/android/launcher3/folder/FolderNameProvider.java b/src/com/android/launcher3/folder/FolderNameProvider.java index d76b73f7ee..386de23b45 100644 --- a/src/com/android/launcher3/folder/FolderNameProvider.java +++ b/src/com/android/launcher3/folder/FolderNameProvider.java @@ -41,7 +41,7 @@ import java.util.stream.Collectors; */ public class FolderNameProvider { - private static final String TAG = FeatureFlags.FOLDER_NAME_SUGGEST.getKey(); + private static final String TAG = "FolderNameProvider"; private static final boolean DEBUG = FeatureFlags.FOLDER_NAME_SUGGEST.get(); /** diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/TogglableFlag.java b/src_ui_overrides/com/android/launcher3/uioverrides/DeviceFlag.java similarity index 63% rename from src_ui_overrides/com/android/launcher3/uioverrides/TogglableFlag.java rename to src_ui_overrides/com/android/launcher3/uioverrides/DeviceFlag.java index d7bb2939e2..5c1ac2856f 100644 --- a/src_ui_overrides/com/android/launcher3/uioverrides/TogglableFlag.java +++ b/src_ui_overrides/com/android/launcher3/uioverrides/DeviceFlag.java @@ -16,21 +16,11 @@ package com.android.launcher3.uioverrides; -import android.content.Context; +import com.android.launcher3.config.FeatureFlags.DebugFlag; -import com.android.launcher3.config.FeatureFlags.BaseTogglableFlag; +public class DeviceFlag extends DebugFlag { -public class TogglableFlag extends BaseTogglableFlag { - - public TogglableFlag(String key, boolean defaultValue, String description) { + public DeviceFlag(String key, boolean defaultValue, String description) { super(key, defaultValue, description); } - - @Override - public boolean getOverridenDefaultValue(boolean value) { - return value; - } - - @Override - public void addChangeListener(Context context, Runnable r) { } }