Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d5d4880d authored by Sunny Goyal's avatar Sunny Goyal Committed by Android (Google) Code Review
Browse files

Merge "Adding a Teamfood flag option" into udc-dev

parents 7163918d ef6b0c07
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -15,16 +15,20 @@
 */
package com.android.launcher3.uioverrides.flags;

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;

    public final boolean defaultValue;
    @NonNull
    public final FlagState defaultValue;

    public DebugFlag(String key, String description, boolean defaultValue, boolean currentValue) {
    DebugFlag(String key, String description, FlagState defaultValue, boolean currentValue) {
        super(currentValue);
        this.key = key;
        this.defaultValue = defaultValue;
+9 −1
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.ArrayMap;
import android.util.Pair;
@@ -182,9 +183,16 @@ public class DeveloperOptionsFragment extends PreferenceFragmentCompat {
    }

    private PreferenceCategory newCategory(String title) {
        return newCategory(title, null);
    }

    private PreferenceCategory newCategory(String title, @Nullable String summary) {
        PreferenceCategory category = new PreferenceCategory(getContext());
        category.setOrder(Preference.DEFAULT_ORDER);
        category.setTitle(title);
        if (!TextUtils.isEmpty(summary)) {
            category.setSummary(summary);
        }
        mPreferenceScreen.addPreference(category);
        return category;
    }
@@ -195,7 +203,7 @@ public class DeveloperOptionsFragment extends PreferenceFragmentCompat {
        }

        mFlagTogglerPrefUi = new FlagTogglerPrefUi(this);
        mFlagTogglerPrefUi.applyTo(newCategory("Feature flags"));
        mFlagTogglerPrefUi.applyTo(newCategory("Feature flags", "Long press to reset"));
    }

    @Override
+3 −1
Original line number Diff line number Diff line
@@ -16,11 +16,13 @@

package com.android.launcher3.uioverrides.flags;

import com.android.launcher3.config.FeatureFlags.FlagState;

class DeviceFlag extends DebugFlag {

    private final boolean mDefaultValueInCode;

    public DeviceFlag(String key, String description, boolean defaultValue,
    DeviceFlag(String key, String description, FlagState defaultValue,
            boolean currentValue, boolean defaultValueInCode) {
        super(key, description, defaultValue, currentValue);
        mDefaultValueInCode = defaultValueInCode;
+42 −13
Original line number Diff line number Diff line
@@ -17,11 +17,15 @@
package com.android.launcher3.uioverrides.flags;

import static com.android.launcher3.config.FeatureFlags.FLAGS_PREF_NAME;
import static com.android.launcher3.config.FeatureFlags.FlagState.TEAMFOOD;
import static com.android.launcher3.uioverrides.flags.FlagsFactory.TEAMFOOD_FLAG;

import android.content.Context;
import android.content.SharedPreferences;
import android.os.Handler;
import android.os.Process;
import android.text.Html;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
@@ -30,6 +34,7 @@ import android.widget.Toast;
import androidx.preference.PreferenceDataStore;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceViewHolder;
import androidx.preference.SwitchPreference;

import com.android.launcher3.R;
@@ -59,12 +64,7 @@ public final class FlagTogglerPrefUi {

        @Override
        public boolean getBoolean(String key, boolean defaultValue) {
            for (DebugFlag flag : FlagsFactory.getDebugFlags()) {
                if (flag.key.equals(key)) {
                    return mSharedPreferences.getBoolean(key, flag.defaultValue);
                }
            }
            return defaultValue;
            return mSharedPreferences.getBoolean(key, defaultValue);
        }
    };

@@ -87,18 +87,41 @@ public final class FlagTogglerPrefUi {
                    : 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);
            SwitchPreference switchPreference = new SwitchPreference(mContext) {
                @Override
                public void onBindViewHolder(PreferenceViewHolder holder) {
                    super.onBindViewHolder(holder);
                    holder.itemView.setOnLongClickListener(v -> {
                        mSharedPreferences.edit().remove(flag.key).apply();
                        setChecked(getFlagStateFromSharedPrefs(flag));
                        updateSummary(this, flag);
                        updateMenu();
                        return true;
                    });
                }
            };
            switchPreference.setKey(flag.key);
            switchPreference.setDefaultValue(flag.defaultValue);
            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();
@@ -108,10 +131,15 @@ public final class FlagTogglerPrefUi {
     * Updates the summary to show the description and whether the flag overrides the default value.
     */
    private void updateSummary(SwitchPreference switchPreference, DebugFlag flag) {
        String onWarning = flag.defaultValue ? "" : "<b>OVERRIDDEN</b><br>";
        String offWarning = flag.defaultValue ? "<b>OVERRIDDEN</b><br>" : "";
        switchPreference.setSummaryOn(Html.fromHtml(onWarning + flag.description));
        switchPreference.setSummaryOff(Html.fromHtml(offWarning + flag.description));
        String summary = flag.defaultValue == TEAMFOOD
                ? "<font color='blue'><b>[TEAMFOOD]</b> </font>" : "";
        if (mSharedPreferences.contains(flag.key)) {
            summary += "<font color='red'><b>[OVERRIDDEN]</b> </font>";
        }
        if (!TextUtils.isEmpty(summary)) {
            summary += "<br>";
        }
        switchPreference.setSummary(Html.fromHtml(summary + flag.description));
    }

    private void updateMenu() {
@@ -143,7 +171,8 @@ public final class FlagTogglerPrefUi {
    }

    private boolean getFlagStateFromSharedPrefs(DebugFlag flag) {
        return mDataStore.getBoolean(flag.key, flag.defaultValue);
        boolean defaultValue = FlagsFactory.getEnabledValue(flag.defaultValue);
        return mDataStore.getBoolean(flag.key, defaultValue);
    }

    private boolean anyChanged() {
+38 −12
Original line number Diff line number Diff line
@@ -18,6 +18,10 @@ 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.config.FeatureFlags.FlagState.TEAMFOOD;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;

import android.content.Context;
@@ -26,8 +30,8 @@ import android.provider.DeviceConfig;
import android.provider.DeviceConfig.Properties;
import android.util.Log;

import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags.BooleanFlag;
import com.android.launcher3.config.FeatureFlags.FlagState;
import com.android.launcher3.config.FeatureFlags.IntFlag;
import com.android.launcher3.util.ScreenOnTracker;

@@ -53,6 +57,9 @@ public class FlagsFactory {

    private static final List<DebugFlag> sDebugFlags = new ArrayList<>();

    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;

@@ -64,35 +71,54 @@ public class FlagsFactory {
                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
     * 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, boolean defaultValue, String description) {
        if (Utilities.IS_DEBUG_DEVICE) {
            int bugId, String key, FlagState flagState, String description) {
        if (IS_DEBUG_DEVICE) {
            SharedPreferences prefs = currentApplication()
                    .getSharedPreferences(FLAGS_PREF_NAME, Context.MODE_PRIVATE);
            boolean defaultValue = getEnabledValue(flagState);
            boolean currentValue = prefs.getBoolean(key, defaultValue);
            DebugFlag flag = new DebugFlag(key, description, defaultValue, currentValue);
            DebugFlag flag = new DebugFlag(key, description, flagState, currentValue);
            sDebugFlags.add(flag);
            return flag;
        } else {
            return new BooleanFlag(defaultValue);
            return new BooleanFlag(getEnabledValue(flagState));
        }
    }

    /**
     * Creates a new release flag
     * 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, boolean defaultValueInCode, String description) {
            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 (Utilities.IS_DEBUG_DEVICE) {
        if (IS_DEBUG_DEVICE) {
            SharedPreferences prefs = currentApplication()
                    .getSharedPreferences(FLAGS_PREF_NAME, Context.MODE_PRIVATE);
            boolean currentValue = prefs.getBoolean(key, defaultValue);
            DebugFlag flag = new DeviceFlag(key, description, defaultValue, currentValue,
            DebugFlag flag = new DeviceFlag(key, description, flagState, currentValue,
                    defaultValueInCode);
            sDebugFlags.add(flag);
            return flag;
@@ -111,7 +137,7 @@ public class FlagsFactory {
    }

    static List<DebugFlag> getDebugFlags() {
        if (!Utilities.IS_DEBUG_DEVICE) {
        if (!IS_DEBUG_DEVICE) {
            return Collections.emptyList();
        }
        synchronized (sDebugFlags) {
@@ -123,7 +149,7 @@ public class FlagsFactory {
     * Dumps the current flags state to the print writer
     */
    public static void dump(PrintWriter pw) {
        if (!Utilities.IS_DEBUG_DEVICE) {
        if (!IS_DEBUG_DEVICE) {
            return;
        }
        pw.println("DeviceFlags:");
Loading