Merge "Updating feature flags subclassing" into ub-launcher3-master
diff --git a/proguard.flags b/proguard.flags
index 3e12283..01302cf 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 <init>(...);
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/DeviceFlag.java b/quickstep/src/com/android/launcher3/uioverrides/DeviceFlag.java
new file mode 100644
index 0000000..3c3f397
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/uioverrides/DeviceFlag.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2019 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.launcher3.uioverrides;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.os.Build;
+import android.provider.DeviceConfig;
+
+import com.android.launcher3.config.FeatureFlags.DebugFlag;
+
+@TargetApi(Build.VERSION_CODES.P)
+public class DeviceFlag extends DebugFlag {
+
+ public static final String NAMESPACE_LAUNCHER = "launcher";
+
+ private final boolean mDefaultValueInCode;
+
+ public DeviceFlag(String key, boolean defaultValue, String description) {
+ super(key, getDeviceValue(key, defaultValue), description);
+ mDefaultValueInCode = defaultValue;
+ }
+
+ @Override
+ protected StringBuilder appendProps(StringBuilder src) {
+ return super.appendProps(src).append(", mDefaultValueInCode=").append(mDefaultValueInCode);
+ }
+
+ @Override
+ public void addChangeListener(Context context, Runnable r) {
+ DeviceConfig.addOnPropertiesChangedListener(
+ NAMESPACE_LAUNCHER,
+ context.getMainExecutor(),
+ 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/quickstep/src/com/android/launcher3/uioverrides/TogglableFlag.java b/quickstep/src/com/android/launcher3/uioverrides/TogglableFlag.java
deleted file mode 100644
index 27d81ef..0000000
--- a/quickstep/src/com/android/launcher3/uioverrides/TogglableFlag.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2019 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.launcher3.uioverrides;
-
-import android.content.Context;
-import android.provider.DeviceConfig;
-
-import com.android.launcher3.config.FeatureFlags.BaseTogglableFlag;
-
-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);
- }
-
- @Override
- public boolean getOverridenDefaultValue(boolean value) {
- return DeviceConfig.getBoolean(NAMESPACE_LAUNCHER, getKey(), value);
- }
-
- @Override
- public void addChangeListener(Context context, Runnable r) {
- DeviceConfig.addOnPropertiesChangedListener(
- NAMESPACE_LAUNCHER,
- context.getMainExecutor(),
- (properties) -> {
- if (!NAMESPACE_LAUNCHER.equals(properties.getNamespace())) {
- return;
- }
- initialize(context);
- r.run();
- });
- }
-}
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 d33fecd..0000000
--- 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.
- *
- * <p>Usage:
- * <pre>
- * {@literal @}Rule public final FlagOverrideRule flags = new FlagOverrideRule();
- *
- * {@literal @}FlagOverride(flag = "FOO", value=true)
- * {@literal @}Test public void myTest() {
- * ...
- * }
- * </pre>
- */
-public final class FlagOverrideRule implements TestRule {
-
- private final HashMap<String, Boolean> mDefaultOverrides = new HashMap<>();
-
- /**
- * Container annotation for handling multiple {@link FlagOverride} annotations.
- * <p>
- * <p>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<String, BaseTogglableFlag> allFlags = FeatureFlags.getTogglableFlags().stream()
- .collect(Collectors.toMap(TogglableFlag::getKey, Function.identity()));
-
- HashMap<BaseTogglableFlag, Boolean> 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<String, Boolean> 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 2a359df..0000000
--- 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 3603dd8..344f532 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 @@
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 @@
/**
* 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 5c6b486..b8fff9c 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.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 @@
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 f10aca5..d63d2dd 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.
*
* <p>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<TogglableFlag> sFlags = new ArrayList<>();
+ private static final List<DebugFlag> 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 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 @@
* 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 @@
"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<TogglableFlag> 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<String, TogglableFlag> flagsByKey = new TreeMap<>();
- synchronized (sLock) {
- for (TogglableFlag flag : sFlags) {
- flagsByKey.put(flag.getKey(), flag);
- }
+ static List<DebugFlag> 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 a7e3732..6729f74 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.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 @@
@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 @@
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 @@
// 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 @@
/**
* 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() ? "" : "<b>OVERRIDDEN</b><br>";
- String offWarning = flag.getDefaultValue() ? "<b>OVERRIDDEN</b><br>" : "";
- 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 ? "" : "<b>OVERRIDDEN</b><br>";
+ String offWarning = flag.defaultValue ? "<b>OVERRIDDEN</b><br>" : "";
+ switchPreference.setSummaryOn(Html.fromHtml(onWarning + flag.description));
+ switchPreference.setSummaryOff(Html.fromHtml(offWarning + flag.description));
}
private void updateMenu() {
@@ -135,12 +139,12 @@
}
}
- 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 d76b73f..386de23 100644
--- a/src/com/android/launcher3/folder/FolderNameProvider.java
+++ b/src/com/android/launcher3/folder/FolderNameProvider.java
@@ -41,7 +41,7 @@
*/
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 d7bb293..5c1ac28 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) { }
}