Loading proguard.flags +0 −6 Original line number Diff line number Diff line Loading @@ -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>(...); } Loading quickstep/src/com/android/launcher3/uioverrides/TogglableFlag.java→quickstep/src/com/android/launcher3/uioverrides/DeviceFlag.java +19 −8 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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); } } robolectric_tests/src/com/android/launcher3/config/FlagOverrideRule.javadeleted 100644 → 0 +0 −117 Original line number Diff line number Diff line 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); } } } } robolectric_tests/src/com/android/launcher3/config/FlagOverrideSampleTest.javadeleted 100644 → 0 +0 −41 Original line number Diff line number Diff line 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()); } } robolectric_tests/src/com/android/launcher3/shadows/ShadowTogglableFlag.java→robolectric_tests/src/com/android/launcher3/shadows/ShadowDeviceFlag.java +8 −3 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; } } Loading
proguard.flags +0 −6 Original line number Diff line number Diff line Loading @@ -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>(...); } Loading
quickstep/src/com/android/launcher3/uioverrides/TogglableFlag.java→quickstep/src/com/android/launcher3/uioverrides/DeviceFlag.java +19 −8 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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); } }
robolectric_tests/src/com/android/launcher3/config/FlagOverrideRule.javadeleted 100644 → 0 +0 −117 Original line number Diff line number Diff line 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); } } } }
robolectric_tests/src/com/android/launcher3/config/FlagOverrideSampleTest.javadeleted 100644 → 0 +0 −41 Original line number Diff line number Diff line 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()); } }
robolectric_tests/src/com/android/launcher3/shadows/ShadowTogglableFlag.java→robolectric_tests/src/com/android/launcher3/shadows/ShadowDeviceFlag.java +8 −3 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; } }