mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-02-27 15:26:58 +00:00
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:
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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"));
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) { }
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user