From d4204437de888756d2cf8ccb8e9244960bd6d423 Mon Sep 17 00:00:00 2001 From: Hyunyoung Song Date: Tue, 13 Aug 2019 15:57:15 -0700 Subject: [PATCH] Make TogglableFlag backed by DeviceConfig for e2e testing Bug: 138964490 TL;DR;; need this to be part of QQ1 or QD1 to verify if DeviceConfig can be supported for launcher toggleableFlags. Not handled in this CL: - When flag is locally modified, that will override the flag value How that scenario is handled should be discussed separately and is not within scope of this CL. Change-Id: I2e6694a40bee9202ed0b0d559e3b5607634071bf --- .../launcher3/uioverrides/TogglableFlag.java | 32 ++++++++ .../launcher3/config/FlagOverrideRule.java | 8 +- .../android/launcher3/config/BaseFlags.java | 74 ++++--------------- .../launcher3/config/FlagTogglerPrefUi.java | 11 +-- .../launcher3/uioverrides/TogglableFlag.java | 31 ++++++++ 5 files changed, 87 insertions(+), 69 deletions(-) create mode 100644 quickstep/src/com/android/launcher3/uioverrides/TogglableFlag.java create mode 100644 src_ui_overrides/com/android/launcher3/uioverrides/TogglableFlag.java diff --git a/quickstep/src/com/android/launcher3/uioverrides/TogglableFlag.java b/quickstep/src/com/android/launcher3/uioverrides/TogglableFlag.java new file mode 100644 index 0000000000..e425088147 --- /dev/null +++ b/quickstep/src/com/android/launcher3/uioverrides/TogglableFlag.java @@ -0,0 +1,32 @@ +/* + * 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.provider.DeviceConfig; +import com.android.launcher3.config.BaseFlags.BaseTogglableFlag; + +public class TogglableFlag extends BaseTogglableFlag { + + public TogglableFlag(String key, boolean defaultValue, String description) { + super(key, defaultValue, description); + } + + @Override + public boolean getInitialValue(boolean value) { + return DeviceConfig.getBoolean("launcher", getKey(), value); + } +} diff --git a/robolectric_tests/src/com/android/launcher3/config/FlagOverrideRule.java b/robolectric_tests/src/com/android/launcher3/config/FlagOverrideRule.java index 92bcc64348..a3d121676f 100644 --- a/robolectric_tests/src/com/android/launcher3/config/FlagOverrideRule.java +++ b/robolectric_tests/src/com/android/launcher3/config/FlagOverrideRule.java @@ -1,6 +1,8 @@ package com.android.launcher3.config; +import com.android.launcher3.config.BaseFlags.BaseTogglableFlag; +import com.android.launcher3.uioverrides.TogglableFlag; import org.junit.rules.TestRule; import org.junit.runner.Description; import org.junit.runners.model.Statement; @@ -70,7 +72,7 @@ public final class FlagOverrideRule implements TestRule { }; } - private void override(BaseFlags.TogglableFlag flag, boolean newValue) { + private void override(BaseTogglableFlag flag, boolean newValue) { if (!ruleInProgress) { throw new IllegalStateException( "Rule isn't in progress. Did you remember to mark it with @Rule?"); @@ -93,7 +95,7 @@ public final class FlagOverrideRule implements TestRule { private void applyAnnotation(FlagOverride flagOverride) { boolean found = false; - for (BaseFlags.TogglableFlag flag : FeatureFlags.getTogglableFlags()) { + for (TogglableFlag flag : FeatureFlags.getTogglableFlags()) { if (flag.getKey().equals(flagOverride.key())) { override(flag, flagOverride.value()); found = true; @@ -109,7 +111,7 @@ public final class FlagOverrideRule implements TestRule { * Resets all flags to their default values. */ private void clearOverrides() { - for (BaseFlags.TogglableFlag flag : FeatureFlags.getTogglableFlags()) { + for (BaseTogglableFlag flag : FeatureFlags.getTogglableFlags()) { flag.setForTests(flag.getDefaultValue()); } } diff --git a/src/com/android/launcher3/config/BaseFlags.java b/src/com/android/launcher3/config/BaseFlags.java index 54efcb7868..6436e4c1e3 100644 --- a/src/com/android/launcher3/config/BaseFlags.java +++ b/src/com/android/launcher3/config/BaseFlags.java @@ -18,20 +18,16 @@ package com.android.launcher3.config; import static androidx.core.util.Preconditions.checkNotNull; -import android.content.ContentResolver; import android.content.Context; import android.content.SharedPreferences; -import android.database.ContentObserver; -import android.os.Handler; -import android.os.Looper; -import android.provider.Settings; import androidx.annotation.GuardedBy; import androidx.annotation.Keep; -import androidx.annotation.VisibleForTesting; +import androidx.annotation.VisibleForTesting; import com.android.launcher3.Utilities; +import com.android.launcher3.uioverrides.TogglableFlag; import java.util.ArrayList; import java.util.List; import java.util.SortedMap; @@ -41,11 +37,9 @@ 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. - * - *

This class is kept package-private to prevent direct access. */ @Keep -abstract class BaseFlags { +public abstract class BaseFlags { private static final Object sLock = new Object(); @GuardedBy("sLock") @@ -116,7 +110,7 @@ abstract class BaseFlags { // Avoid the disk read for user builds if (Utilities.IS_DEBUG_DEVICE) { synchronized (sLock) { - for (TogglableFlag flag : sFlags) { + for (BaseTogglableFlag flag : sFlags) { flag.initialize(context); } } @@ -132,27 +126,27 @@ abstract class BaseFlags { SortedMap flagsByKey = new TreeMap<>(); synchronized (sLock) { for (TogglableFlag flag : sFlags) { - flagsByKey.put(flag.key, flag); + flagsByKey.put(((BaseTogglableFlag) flag).getKey(), flag); } } return new ArrayList<>(flagsByKey.values()); } - public static class TogglableFlag { + public static abstract class BaseTogglableFlag { private final String key; private final boolean defaultValue; private final String description; private boolean currentValue; - TogglableFlag( + public BaseTogglableFlag( String key, boolean defaultValue, String description) { this.key = checkNotNull(key); - this.currentValue = this.defaultValue = defaultValue; + this.currentValue = this.defaultValue = getInitialValue(defaultValue); this.description = checkNotNull(description); synchronized (sLock) { - sFlags.add(this); + sFlags.add((TogglableFlag)this); } } @@ -162,14 +156,16 @@ abstract class BaseFlags { currentValue = value; } - @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) public String getKey() { return key; } + void initialize(Context context) { currentValue = getFromStorage(context, defaultValue); } + protected abstract boolean getInitialValue(boolean value); + public void updateStorage(Context context, boolean value) { SharedPreferences.Editor editor = context.getSharedPreferences(FLAGS_PREF_NAME, Context.MODE_PRIVATE).edit(); @@ -213,7 +209,7 @@ abstract class BaseFlags { return true; } if (o instanceof TogglableFlag) { - TogglableFlag that = (TogglableFlag) o; + BaseTogglableFlag that = (BaseTogglableFlag) o; return (this.key.equals(that.getKey())) && (this.defaultValue == that.getDefaultValue()) && (this.description.equals(that.getDescription())); @@ -233,48 +229,4 @@ abstract class BaseFlags { return h$; } } - - /** - * Stores the FeatureFlag's value in Settings.Global instead of our SharedPrefs. - * This is useful if we want to be able to control this flag from another process. - */ - public static final class ToggleableGlobalSettingsFlag extends TogglableFlag { - private ContentResolver contentResolver; - - ToggleableGlobalSettingsFlag(String key, boolean defaultValue, String description) { - super(key, defaultValue, description); - } - - @Override - public void initialize(Context context) { - contentResolver = context.getContentResolver(); - contentResolver.registerContentObserver(Settings.Global.getUriFor(getKey()), true, - new ContentObserver(new Handler(Looper.getMainLooper())) { - @Override - public void onChange(boolean selfChange) { - superInitialize(context); - }}); - superInitialize(context); - } - - private void superInitialize(Context context) { - super.initialize(context); - } - - @Override - public void updateStorage(Context context, boolean value) { - if (contentResolver == null) { - return; - } - Settings.Global.putInt(contentResolver, getKey(), value ? 1 : 0); - } - - @Override - boolean getFromStorage(Context context, boolean defaultValue) { - if (contentResolver == null) { - return defaultValue; - } - return Settings.Global.getInt(contentResolver, getKey(), defaultValue ? 1 : 0) == 1; - } - } } diff --git a/src/com/android/launcher3/config/FlagTogglerPrefUi.java b/src/com/android/launcher3/config/FlagTogglerPrefUi.java index 5ecb186500..54e5322bd5 100644 --- a/src/com/android/launcher3/config/FlagTogglerPrefUi.java +++ b/src/com/android/launcher3/config/FlagTogglerPrefUi.java @@ -26,12 +26,13 @@ import android.view.MenuItem; import android.widget.Toast; import com.android.launcher3.R; -import com.android.launcher3.config.BaseFlags.TogglableFlag; import androidx.preference.PreferenceDataStore; import androidx.preference.PreferenceFragment; import androidx.preference.PreferenceGroup; import androidx.preference.SwitchPreference; +import com.android.launcher3.config.BaseFlags.BaseTogglableFlag; +import com.android.launcher3.uioverrides.TogglableFlag; /** * Dev-build only UI allowing developers to toggle flag settings. See {@link FeatureFlags}. @@ -62,7 +63,7 @@ public final class FlagTogglerPrefUi { @Override public boolean getBoolean(String key, boolean defaultValue) { - for (TogglableFlag flag : FeatureFlags.getTogglableFlags()) { + for (BaseTogglableFlag flag : FeatureFlags.getTogglableFlags()) { if (flag.getKey().equals(key)) { return flag.getFromStorage(mContext, defaultValue); } @@ -83,7 +84,7 @@ 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 (TogglableFlag flag : FeatureFlags.getTogglableFlags()) { + for (BaseTogglableFlag flag : FeatureFlags.getTogglableFlags()) { SwitchPreference switchPreference = new SwitchPreference(mContext); switchPreference.setKey(flag.getKey()); switchPreference.setDefaultValue(flag.getDefaultValue()); @@ -99,7 +100,7 @@ public final class FlagTogglerPrefUi { /** * Updates the summary to show the description and whether the flag overrides the default value. */ - private void updateSummary(SwitchPreference switchPreference, TogglableFlag flag) { + private void updateSummary(SwitchPreference switchPreference, BaseTogglableFlag flag) { String onWarning = flag.getDefaultValue() ? "" : "OVERRIDDEN
"; String offWarning = flag.getDefaultValue() ? "OVERRIDDEN
" : ""; switchPreference.setSummaryOn(Html.fromHtml(onWarning + flag.getDescription())); @@ -134,7 +135,7 @@ public final class FlagTogglerPrefUi { } } - private boolean getFlagStateFromSharedPrefs(TogglableFlag flag) { + private boolean getFlagStateFromSharedPrefs(BaseTogglableFlag flag) { return mDataStore.getBoolean(flag.getKey(), flag.getDefaultValue()); } diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/TogglableFlag.java b/src_ui_overrides/com/android/launcher3/uioverrides/TogglableFlag.java new file mode 100644 index 0000000000..e875a3c465 --- /dev/null +++ b/src_ui_overrides/com/android/launcher3/uioverrides/TogglableFlag.java @@ -0,0 +1,31 @@ +/* + * 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 com.android.launcher3.config.BaseFlags.BaseTogglableFlag; + +public class TogglableFlag extends BaseTogglableFlag { + + public TogglableFlag(String key, boolean defaultValue, String description) { + super(key, defaultValue, description); + } + + @Override + public boolean getInitialValue(boolean value) { + return value; + } +}