diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/DebugFlag.java b/quickstep/src/com/android/launcher3/uioverrides/flags/DebugFlag.java deleted file mode 100644 index 630ef39627..0000000000 --- a/quickstep/src/com/android/launcher3/uioverrides/flags/DebugFlag.java +++ /dev/null @@ -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. - *

- * 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(); - } -} diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/DeveloperOptionsUI.java b/quickstep/src/com/android/launcher3/uioverrides/flags/DeveloperOptionsUI.java index fd6bf4daf4..3f818acc4b 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/flags/DeveloperOptionsUI.java +++ b/quickstep/src/com/android/launcher3/uioverrides/flags/DeveloperOptionsUI.java @@ -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")); diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/DeviceFlag.java b/quickstep/src/com/android/launcher3/uioverrides/flags/DeviceFlag.java deleted file mode 100644 index 915f4aeaf7..0000000000 --- a/quickstep/src/com/android/launcher3/uioverrides/flags/DeviceFlag.java +++ /dev/null @@ -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; - } -} diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/FlagTogglerPrefUi.java b/quickstep/src/com/android/launcher3/uioverrides/flags/FlagTogglerPrefUi.java deleted file mode 100644 index fc39ce42a2..0000000000 --- a/quickstep/src/com/android/launcher3/uioverrides/flags/FlagTogglerPrefUi.java +++ /dev/null @@ -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 modifiedPrefs = FlagsFactory.getSharedPreferences().getAll().keySet(); - List 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 - ? "[TEAMFOOD] " : ""; - if (FlagsFactory.getSharedPreferences().contains(flag.key)) { - summary += "[OVERRIDDEN] "; - } - if (!TextUtils.isEmpty(summary)) { - summary += "
"; - } - 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; - } -} diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/FlagsFactory.java b/quickstep/src/com/android/launcher3/uioverrides/flags/FlagsFactory.java deleted file mode 100644 index 7fd63445bb..0000000000 --- a/quickstep/src/com/android/launcher3/uioverrides/flags/FlagsFactory.java +++ /dev/null @@ -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 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 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 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); - } - } -} diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index 5564b1873d..7035d6e5f0 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -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); } diff --git a/quickstep/src/com/android/quickstep/util/DeviceConfigHelper.kt b/quickstep/src/com/android/quickstep/util/DeviceConfigHelper.kt index f601fee954..544c64d3da 100644 --- a/quickstep/src/com/android/quickstep/util/DeviceConfigHelper.kt +++ b/quickstep/src/com/android/quickstep/util/DeviceConfigHelper.kt @@ -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(private val factory: (PropReader) -> Config private fun recreateConfig() { val myProps = - DeviceConfig.getProperties( - FlagsFactory.NAMESPACE_LAUNCHER, - *allKeys.toTypedArray() - ) + DeviceConfig.getProperties(NAMESPACE_LAUNCHER, *allKeys.toTypedArray()) config = factory( PropReader( diff --git a/res/drawable/ic_allapps_search.xml b/res/drawable/ic_allapps_search.xml index 0c3ab78575..53b4f91d22 100644 --- a/res/drawable/ic_allapps_search.xml +++ b/res/drawable/ic_allapps_search.xml @@ -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"> diff --git a/res/layout/developer_options_top_bar.xml b/res/layout/developer_options_top_bar.xml index 1b138ea926..ca46311828 100644 --- a/res/layout/developer_options_top_bar.xml +++ b/res/layout/developer_options_top_bar.xml @@ -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" /> -