Freezing legacy feature flags

Legacy feature flags will be locked to their current values in code.
All new feature development should use aconfig flags

Bug: 332588958
Flag: None
Test: Presubmit
Change-Id: Ie72dd8276b7135620de279835d6721a34f82ede4
This commit is contained in:
Sunny Goyal
2024-04-09 10:38:38 -07:00
parent 3b00e7909a
commit 8049369af8
12 changed files with 40 additions and 597 deletions

View File

@@ -1,59 +0,0 @@
/*
* Copyright (C) 2023 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.flags;
import static com.android.launcher3.uioverrides.flags.FlagsFactory.TEAMFOOD_FLAG;
import androidx.annotation.NonNull;
import com.android.launcher3.config.FeatureFlags.BooleanFlag;
import com.android.launcher3.config.FeatureFlags.FlagState;
class DebugFlag extends BooleanFlag {
public final String key;
public final String description;
@NonNull
public final FlagState defaultValue;
DebugFlag(String key, String description, FlagState defaultValue, boolean currentValue) {
super(currentValue);
this.key = key;
this.defaultValue = defaultValue;
this.description = description;
}
/**
* Returns {@code true} if this flag's value has been modified from its default.
* <p>
* This helps to identify which flags have been toggled in log dumps and bug reports to
* further help triaging and debugging.
*/
boolean currentValueModified() {
switch (defaultValue) {
case ENABLED: return !get();
case TEAMFOOD: return TEAMFOOD_FLAG.get() != get();
case DISABLED: return get();
default: return true;
}
}
@Override
public String toString() {
return key + ": defaultValue=" + defaultValue + ", mCurrentValue=" + get();
}
}

View File

@@ -75,7 +75,6 @@ public class DeveloperOptionsUI {
private static final String ACTION_PLUGIN_SETTINGS =
"com.android.systemui.action.PLUGIN_SETTINGS";
private static final String TAG = "DeveloperOptionsUI";
private static final String PLUGIN_PERMISSION = "com.android.systemui.permission.PLUGIN";
private final PreferenceFragmentCompat mFragment;
@@ -86,6 +85,7 @@ public class DeveloperOptionsUI {
public DeveloperOptionsUI(PreferenceFragmentCompat fragment, PreferenceCategory flags) {
mFragment = fragment;
mPreferenceScreen = fragment.getPreferenceScreen();
flags.getParent().removePreference(flags);
// Add search bar
View listView = mFragment.getListView();
@@ -95,8 +95,6 @@ public class DeveloperOptionsUI {
parent.addView(topBar, parent.indexOfChild(listView));
initSearch(topBar.findViewById(R.id.filter_box));
new FlagTogglerPrefUi(mFragment.requireActivity(), topBar.findViewById(R.id.flag_apply_btn))
.applyTo(flags);
DevOptionsUiHelper uiHelper = new DevOptionsUiHelper();
uiHelper.inflateServerFlags(newCategory("Server flags"));

View File

@@ -1,40 +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.flags;
import com.android.launcher3.config.FeatureFlags.FlagState;
class DeviceFlag extends DebugFlag {
private final boolean mDefaultValueInCode;
DeviceFlag(String key, String description, FlagState defaultValue,
boolean currentValue, boolean defaultValueInCode) {
super(key, description, defaultValue, currentValue);
mDefaultValueInCode = defaultValueInCode;
}
@Override
boolean currentValueModified() {
return super.currentValueModified() || mDefaultValueInCode != get();
}
@Override
public String toString() {
return super.toString() + ", mDefaultValueInCode=" + mDefaultValueInCode;
}
}

View File

@@ -1,172 +0,0 @@
/*
* Copyright (C) 2018 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.flags;
import static com.android.launcher3.config.FeatureFlags.FlagState.TEAMFOOD;
import static com.android.launcher3.uioverrides.flags.FlagsFactory.TEAMFOOD_FLAG;
import android.app.Activity;
import android.content.Context;
import android.os.Handler;
import android.os.Process;
import android.text.Html;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import androidx.preference.PreferenceDataStore;
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceViewHolder;
import androidx.preference.SwitchPreference;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.ActivityLifecycleCallbacksAdapter;
import java.util.List;
import java.util.Set;
/**
* Dev-build only UI allowing developers to toggle flag settings. See {@link FeatureFlags}.
*/
public final class FlagTogglerPrefUi implements ActivityLifecycleCallbacksAdapter {
private static final String TAG = "FlagTogglerPrefFrag";
private final View mFlagsApplyButton;
private final Context mContext;
private final PreferenceDataStore mDataStore = new PreferenceDataStore() {
@Override
public void putBoolean(String key, boolean value) {
FlagsFactory.getSharedPreferences().edit().putBoolean(key, value).apply();
updateMenu();
}
@Override
public boolean getBoolean(String key, boolean defaultValue) {
return FlagsFactory.getSharedPreferences().getBoolean(key, defaultValue);
}
};
public FlagTogglerPrefUi(Activity activity, View flagsApplyButton) {
mFlagsApplyButton = flagsApplyButton;
mContext = mFlagsApplyButton.getContext();
activity.registerActivityLifecycleCallbacks(this);
mFlagsApplyButton.setOnClickListener(v -> {
FlagsFactory.getSharedPreferences().edit().commit();
Log.e(TAG,
"Killing launcher process " + Process.myPid() + " to apply new flag values");
System.exit(0);
});
}
public void applyTo(PreferenceGroup parent) {
Set<String> modifiedPrefs = FlagsFactory.getSharedPreferences().getAll().keySet();
List<DebugFlag> flags = FlagsFactory.getDebugFlags();
flags.sort((f1, f2) -> {
// Sort first by any prefs that the user has changed, then alphabetically.
int changeComparison = Boolean.compare(
modifiedPrefs.contains(f2.key), modifiedPrefs.contains(f1.key));
return changeComparison != 0
? changeComparison
: f1.key.compareToIgnoreCase(f2.key);
});
// Ensure that teamfood flag comes on the top
if (flags.remove(TEAMFOOD_FLAG)) {
flags.add(0, (DebugFlag) TEAMFOOD_FLAG);
}
// For flag overrides we only want to store when the engineer chose to override the
// 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 (DebugFlag flag : flags) {
SwitchPreference switchPreference = new SwitchPreference(mContext) {
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
holder.itemView.setOnLongClickListener(v -> {
FlagsFactory.getSharedPreferences().edit().remove(flag.key).apply();
setChecked(getFlagStateFromSharedPrefs(flag));
updateSummary(this, flag);
updateMenu();
return true;
});
}
};
switchPreference.setKey(flag.key);
switchPreference.setDefaultValue(FlagsFactory.getEnabledValue(flag.defaultValue));
switchPreference.setChecked(getFlagStateFromSharedPrefs(flag));
switchPreference.setTitle(flag.key);
updateSummary(switchPreference, flag);
switchPreference.setPreferenceDataStore(mDataStore);
switchPreference.setOnPreferenceChangeListener((p, v) -> {
new Handler().post(() -> updateSummary(switchPreference, flag));
return true;
});
parent.addPreference(switchPreference);
}
updateMenu();
}
/**
* Updates the summary to show the description and whether the flag overrides the default value.
*/
private void updateSummary(SwitchPreference switchPreference, DebugFlag flag) {
String summary = flag.defaultValue == TEAMFOOD
? "<font color='blue'><b>[TEAMFOOD]</b> </font>" : "";
if (FlagsFactory.getSharedPreferences().contains(flag.key)) {
summary += "<font color='red'><b>[OVERRIDDEN]</b> </font>";
}
if (!TextUtils.isEmpty(summary)) {
summary += "<br>";
}
switchPreference.setSummary(Html.fromHtml(summary + flag.description));
}
public void updateMenu() {
mFlagsApplyButton.setVisibility(anyChanged() ? View.VISIBLE : View.INVISIBLE);
}
@Override
public void onActivityStopped(Activity activity) {
if (anyChanged()) {
Toast.makeText(mContext, "Flag won't be applied until you restart launcher",
Toast.LENGTH_LONG).show();
}
}
private boolean getFlagStateFromSharedPrefs(DebugFlag flag) {
boolean defaultValue = FlagsFactory.getEnabledValue(flag.defaultValue);
return mDataStore.getBoolean(flag.key, defaultValue);
}
private boolean anyChanged() {
for (DebugFlag flag : FlagsFactory.getDebugFlags()) {
if (getFlagStateFromSharedPrefs(flag) != flag.get()) {
return true;
}
}
return false;
}
}

View File

@@ -1,198 +0,0 @@
/*
* Copyright (C) 2023 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.flags;
import static android.app.ActivityThread.currentApplication;
import static com.android.launcher3.BuildConfig.IS_DEBUG_DEVICE;
import static com.android.launcher3.config.FeatureFlags.FlagState.DISABLED;
import static com.android.launcher3.config.FeatureFlags.FlagState.ENABLED;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import android.content.Context;
import android.content.SharedPreferences;
import android.provider.DeviceConfig;
import android.provider.DeviceConfig.Properties;
import android.util.Log;
import androidx.annotation.NonNull;
import com.android.launcher3.config.FeatureFlags.BooleanFlag;
import com.android.launcher3.config.FeatureFlags.FlagState;
import com.android.launcher3.util.ScreenOnTracker;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* Helper class to create various flags for system build
*/
public class FlagsFactory {
private static final String TAG = "FlagsFactory";
private static final FlagsFactory INSTANCE = new FlagsFactory();
private static final boolean FLAG_AUTO_APPLY_ENABLED = true;
private static final String FLAGS_PREF_NAME = "featureFlags";
public static final String NAMESPACE_LAUNCHER = "launcher";
private static final List<DebugFlag> sDebugFlags = new ArrayList<>();
private static SharedPreferences sSharedPreferences;
static final BooleanFlag TEAMFOOD_FLAG = getReleaseFlag(
0, "LAUNCHER_TEAMFOOD", DISABLED, "Enable this flag to opt-in all team food flags");
private final Set<String> mKeySet = new HashSet<>();
private boolean mRestartRequested = false;
private FlagsFactory() {
if (!FLAG_AUTO_APPLY_ENABLED) {
return;
}
DeviceConfig.addOnPropertiesChangedListener(
NAMESPACE_LAUNCHER, UI_HELPER_EXECUTOR, this::onPropertiesChanged);
}
static boolean getEnabledValue(FlagState flagState) {
if (IS_DEBUG_DEVICE) {
switch (flagState) {
case ENABLED:
return true;
case TEAMFOOD:
return TEAMFOOD_FLAG.get();
default:
return false;
}
} else {
return flagState == ENABLED;
}
}
/**
* Creates a new debug flag. Debug flags always take their default value in release builds. On
* dogfood builds, they can be manually turned on using the flag toggle UI.
*/
public static BooleanFlag getDebugFlag(
int bugId, String key, FlagState flagState, String description) {
if (IS_DEBUG_DEVICE) {
boolean defaultValue = getEnabledValue(flagState);
boolean currentValue = getSharedPreferences().getBoolean(key, defaultValue);
DebugFlag flag = new DebugFlag(key, description, flagState, currentValue);
sDebugFlags.add(flag);
return flag;
} else {
return new BooleanFlag(getEnabledValue(flagState));
}
}
/**
* Creates a new release flag. Release flags can be rolled out using server configurations and
* also allow manual overrides on debug builds.
*/
public static BooleanFlag getReleaseFlag(
int bugId, String key, FlagState flagState, String description) {
INSTANCE.mKeySet.add(key);
boolean defaultValueInCode = getEnabledValue(flagState);
boolean defaultValue = DeviceConfig.getBoolean(NAMESPACE_LAUNCHER, key, defaultValueInCode);
if (IS_DEBUG_DEVICE) {
boolean currentValue = getSharedPreferences().getBoolean(key, defaultValue);
DebugFlag flag = new DeviceFlag(key, description,
(defaultValue == defaultValueInCode) ? flagState
: defaultValue ? ENABLED : DISABLED, currentValue, defaultValueInCode);
sDebugFlags.add(flag);
return flag;
} else {
return new BooleanFlag(defaultValue);
}
}
static List<DebugFlag> getDebugFlags() {
if (!IS_DEBUG_DEVICE) {
return Collections.emptyList();
}
synchronized (sDebugFlags) {
return new ArrayList<>(sDebugFlags);
}
}
/** Returns the SharedPreferences instance backing Debug FeatureFlags. */
@NonNull
static SharedPreferences getSharedPreferences() {
if (sSharedPreferences == null) {
sSharedPreferences = currentApplication()
.createDeviceProtectedStorageContext()
.getSharedPreferences(FLAGS_PREF_NAME, Context.MODE_PRIVATE);
}
return sSharedPreferences;
}
/**
* Dumps the current flags state to the print writer
*/
public static void dump(PrintWriter pw) {
if (!IS_DEBUG_DEVICE) {
return;
}
pw.println("DeviceFlags:");
pw.println(" BooleanFlags:");
synchronized (sDebugFlags) {
for (DebugFlag flag : sDebugFlags) {
if (flag instanceof DeviceFlag) {
pw.println((flag.currentValueModified() ? " ->" : " ") + flag);
}
}
}
pw.println(" DebugFlags:");
synchronized (sDebugFlags) {
for (DebugFlag flag : sDebugFlags) {
if (!(flag instanceof DeviceFlag)) {
pw.println((flag.currentValueModified() ? " ->" : " ") + flag);
}
}
}
}
private void onPropertiesChanged(Properties properties) {
if (!Collections.disjoint(properties.getKeyset(), mKeySet)) {
// Schedule a restart
if (mRestartRequested) {
return;
}
Log.e(TAG, "Flag changed, scheduling restart");
mRestartRequested = true;
ScreenOnTracker sot = ScreenOnTracker.INSTANCE.get(currentApplication());
if (sot.isScreenOn()) {
sot.addListener(this::onScreenOnChanged);
} else {
onScreenOnChanged(false);
}
}
}
private void onScreenOnChanged(boolean isOn) {
if (mRestartRequested && !isOn) {
Log.e(TAG, "Restart requested, killing process");
System.exit(0);
}
}
}

View File

@@ -95,7 +95,6 @@ import com.android.launcher3.taskbar.TaskbarManager;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.ResourceUtils;
import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.uioverrides.flags.FlagsFactory;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.LockedUserState;
@@ -1421,7 +1420,6 @@ public class TouchInteractionService extends Service {
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] rawArgs) {
// Dump everything
FlagsFactory.dump(pw);
if (LockedUserState.get(this).isUserUnlocked()) {
PluginManagerWrapper.INSTANCE.get(getBaseContext()).dump(pw);
}

View File

@@ -19,13 +19,12 @@ package com.android.quickstep.util
import android.app.ActivityThread
import android.content.Context
import android.content.SharedPreferences
import android.content.SharedPreferences.*
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
import android.provider.DeviceConfig
import android.provider.DeviceConfig.OnPropertiesChangedListener
import android.provider.DeviceConfig.Properties
import androidx.annotation.WorkerThread
import com.android.launcher3.BuildConfig
import com.android.launcher3.uioverrides.flags.FlagsFactory
import com.android.launcher3.util.Executors
/** Utility class to manage a set of device configurations */
@@ -79,10 +78,7 @@ class DeviceConfigHelper<ConfigType>(private val factory: (PropReader) -> Config
private fun recreateConfig() {
val myProps =
DeviceConfig.getProperties(
FlagsFactory.NAMESPACE_LAUNCHER,
*allKeys.toTypedArray<String>()
)
DeviceConfig.getProperties(NAMESPACE_LAUNCHER, *allKeys.toTypedArray<String>())
config =
factory(
PropReader(

View File

@@ -18,8 +18,9 @@
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0"
android:autoMirrored="true">
android:autoMirrored="true"
android:tint="?attr/widgetPickerSearchTextColor">
<path
android:fillColor="?attr/widgetPickerSearchTextColor"
android:fillColor="#FFFFFF"
android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z" />
</vector>

View File

@@ -11,16 +11,17 @@
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/developer_options_filter_margins"
android:background="@drawable/rounded_action_button"
android:layout_marginTop="4dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:padding="12dp"
android:drawableStart="@drawable/ic_allapps_search"
android:drawableTint="?android:attr/textColorSecondary"
android:drawablePadding="8dp"
android:hint="@string/developer_options_filter_hint"
android:inputType="text"
android:maxLines="1"
android:imeOptions="actionDone"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:text="Apply"
android:visibility="invisible"
android:id="@+id/flag_apply_btn" />
</LinearLayout>

View File

@@ -17,11 +17,8 @@
package com.android.launcher3.config;
import static com.android.launcher3.BuildConfig.WIDGET_ON_FIRST_SCREEN;
import static com.android.launcher3.config.FeatureFlags.FlagState.DISABLED;
import static com.android.launcher3.config.FeatureFlags.FlagState.ENABLED;
import static com.android.launcher3.config.FeatureFlags.FlagState.TEAMFOOD;
import static com.android.launcher3.uioverrides.flags.FlagsFactory.getDebugFlag;
import static com.android.launcher3.uioverrides.flags.FlagsFactory.getReleaseFlag;
import static com.android.launcher3.config.FeatureFlags.BooleanFlag.DISABLED;
import static com.android.launcher3.config.FeatureFlags.BooleanFlag.ENABLED;
import static com.android.wm.shell.Flags.enableTaskbarNavbarUnification;
import android.content.res.Resources;
@@ -31,8 +28,6 @@ import androidx.annotation.VisibleForTesting;
import com.android.launcher3.BuildConfig;
import com.android.launcher3.Flags;
import java.util.function.Predicate;
/**
* Defines a set of flags used to control various launcher behaviors.
* <p>
@@ -40,9 +35,6 @@ import java.util.function.Predicate;
*/
public final class FeatureFlags {
@VisibleForTesting
public static Predicate<BooleanFlag> sBooleanReader = f -> f.mCurrentValue;
private FeatureFlags() { }
/**
@@ -181,7 +173,7 @@ public final class FeatureFlags {
// TODO(Block 14): Cleanup flags
public static final BooleanFlag NOTIFY_CRASHES = getDebugFlag(270393108, "NOTIFY_CRASHES",
TEAMFOOD, "Sends a notification whenever launcher encounters an uncaught exception.");
DISABLED, "Sends a notification whenever launcher encounters an uncaught exception.");
public static final boolean ENABLE_TASKBAR_NAVBAR_UNIFICATION =
enableTaskbarNavbarUnification() && !isPhone();
@@ -251,7 +243,7 @@ public final class FeatureFlags {
// TODO(Block 17): Clean up flags
// Aconfig migration complete for ENABLE_TASKBAR_PINNING.
private static final BooleanFlag ENABLE_TASKBAR_PINNING = getDebugFlag(296231746,
"ENABLE_TASKBAR_PINNING", TEAMFOOD,
"ENABLE_TASKBAR_PINNING", DISABLED,
"Enables taskbar pinning to allow user to switch between transient and persistent "
+ "taskbar flavors");
@@ -291,7 +283,7 @@ public final class FeatureFlags {
// Aconfig migration complete for ENABLE_HOME_TRANSITION_LISTENER.
public static final BooleanFlag ENABLE_HOME_TRANSITION_LISTENER = getDebugFlag(306053414,
"ENABLE_HOME_TRANSITION_LISTENER", TEAMFOOD,
"ENABLE_HOME_TRANSITION_LISTENER", DISABLED,
"Enables launcher to listen to all transitions that include home activity.");
public static boolean enableHomeTransitionListener() {
@@ -386,7 +378,7 @@ public final class FeatureFlags {
// Aconfig migration complete for ENABLE_RESPONSIVE_WORKSPACE.
@VisibleForTesting
public static final BooleanFlag ENABLE_RESPONSIVE_WORKSPACE = getDebugFlag(241386436,
"ENABLE_RESPONSIVE_WORKSPACE", TEAMFOOD,
"ENABLE_RESPONSIVE_WORKSPACE", DISABLED,
"Enables new workspace grid calculations method.");
public static boolean enableResponsiveWorkspace() {
return ENABLE_RESPONSIVE_WORKSPACE.get() || Flags.enableResponsiveWorkspace();
@@ -400,35 +392,31 @@ public final class FeatureFlags {
"ALL_APPS_GONE_VISIBILITY", ENABLED,
"Set all apps container view's hidden visibility to GONE instead of INVISIBLE.");
// TODO(Block 34): Empty block
// Please only add flags to your assigned block. If you do not have a block:
// 1. Assign yourself this block
// 2. Add your flag to this block
// 3. Add a new empty block below this one
// 4. Move this comment to that new empty block
// This is all to prevent merge conflicts in the future and help keep track of who owns which
// flags.
// List of assigned blocks can be found: http://go/gnl-flags-block-directory
public static BooleanFlag getDebugFlag(
int bugId, String key, BooleanFlag flagState, String description) {
return flagState;
}
public static class BooleanFlag {
private final boolean mCurrentValue;
public BooleanFlag(boolean currentValue) {
mCurrentValue = currentValue;
}
public boolean get() {
return sBooleanReader.test(this);
}
public static BooleanFlag getReleaseFlag(
int bugId, String key, BooleanFlag flagState, String description) {
return flagState;
}
/**
* Enabled state for a flag
*/
public enum FlagState {
ENABLED,
DISABLED,
TEAMFOOD // Enabled in team food
public enum BooleanFlag {
ENABLED(true),
DISABLED(false);
private final boolean mValue;
BooleanFlag(boolean value) {
mValue = value;
}
public boolean get() {
return mValue;
}
}
}

View File

@@ -1,52 +0,0 @@
/*
* Copyright (C) 2023 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.flags;
import static com.android.launcher3.config.FeatureFlags.FlagState.ENABLED;
import com.android.launcher3.config.FeatureFlags.BooleanFlag;
import com.android.launcher3.config.FeatureFlags.FlagState;
import java.io.PrintWriter;
/**
* Helper class to create various flags for launcher build. The base implementation does
* not provide any flagging system, and simply replies with the default value.
*/
public class FlagsFactory {
/**
* Creates a new debug flag
*/
public static BooleanFlag getDebugFlag(
int bugId, String key, FlagState flagState, String description) {
return new BooleanFlag(flagState == ENABLED);
}
/**
* Creates a new debug flag
*/
public static BooleanFlag getReleaseFlag(
int bugId, String key, FlagState flagState, String description) {
return new BooleanFlag(flagState == ENABLED);
}
/**
* Dumps the current flags state to the print writer
*/
public static void dump(PrintWriter pw) { }
}

View File

@@ -46,8 +46,6 @@ import android.util.Log;
import androidx.test.uiautomator.UiDevice;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.config.FeatureFlags.BooleanFlag;
import com.android.launcher3.tapl.LauncherInstrumentation;
import com.android.launcher3.tapl.Workspace;
@@ -64,7 +62,6 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Predicate;
public class TestUtil {
private static final String TAG = "TestUtil";
@@ -144,21 +141,6 @@ public class TestUtil {
};
}
/**
* Utility class to override a boolean flag during test. Note that the returned SafeCloseable
* must be closed to restore the original state
*/
public static SafeCloseable overrideFlag(BooleanFlag flag, boolean value) {
Predicate<BooleanFlag> originalProxy = FeatureFlags.sBooleanReader;
Predicate<BooleanFlag> testProxy = f -> f == flag ? value : originalProxy.test(f);
FeatureFlags.sBooleanReader = testProxy;
return () -> {
if (FeatureFlags.sBooleanReader == testProxy) {
FeatureFlags.sBooleanReader = originalProxy;
}
};
}
public static void uninstallDummyApp() throws IOException {
UiDevice.getInstance(getInstrumentation()).executeShellCommand(
"pm uninstall " + DUMMY_PACKAGE);