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

Commit 45e2aafa authored by Dave Mankoff's avatar Dave Mankoff Committed by Android (Google) Code Review
Browse files

Merge "Use less SysUI specific code in Flags." into tm-qpr-dev

parents 4ccdca90 f1a5f74f
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.systemui.flags

import android.content.Context
import android.os.Handler
import com.android.internal.statusbar.IStatusBarService
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.flags.FeatureFlagsDebug.ALL_FLAGS
import com.android.systemui.util.settings.SettingsUtilModule
@@ -27,6 +28,7 @@ import dagger.Provides
import javax.inject.Named

@Module(includes = [
    FeatureFlagsDebugStartableModule::class,
    ServerFlagReaderModule::class,
    SettingsUtilModule::class,
])
@@ -46,5 +48,15 @@ abstract class FlagsModule {
        @Provides
        @Named(ALL_FLAGS)
        fun providesAllFlags(): Map<Int, Flag<*>> = Flags.collectFlags()

        @JvmStatic
        @Provides
        fun providesRestarter(barService: IStatusBarService): Restarter {
            return object: Restarter {
                override fun restart() {
                    barService.restart()
                }
            }
        }
    }
}
+19 −1
Original line number Diff line number Diff line
@@ -16,11 +16,29 @@

package com.android.systemui.flags

import com.android.internal.statusbar.IStatusBarService
import dagger.Binds
import dagger.Module
import dagger.Provides

@Module(includes = [ServerFlagReaderModule::class])
@Module(includes = [
    FeatureFlagsReleaseStartableModule::class,
    ServerFlagReaderModule::class
])
abstract class FlagsModule {
    @Binds
    abstract fun bindsFeatureFlagRelease(impl: FeatureFlagsRelease): FeatureFlags

    @Module
    companion object {
        @JvmStatic
        @Provides
        fun providesRestarter(barService: IStatusBarService): Restarter {
            return object: Restarter {
                override fun restart() {
                    barService.restart()
                }
            }
        }
    }
}
+3 −1
Original line number Diff line number Diff line
@@ -16,12 +16,14 @@

package com.android.systemui.flags

import android.util.Dumpable

/**
 * Class to manage simple DeviceConfig-based feature flags.
 *
 * See [Flags] for instructions on defining new flags.
 */
interface FeatureFlags : FlagListenable {
interface FeatureFlags : FlagListenable, Dumpable {
    /** Returns a boolean value for the given flag.  */
    fun isEnabled(flag: UnreleasedFlag): Boolean

+9 −175
Original line number Diff line number Diff line
@@ -30,29 +30,21 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.Dumpable;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.statusbar.commandline.Command;
import com.android.systemui.statusbar.commandline.CommandRegistry;
import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.settings.SecureSettings;

import org.jetbrains.annotations.NotNull;

import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;
@@ -75,10 +67,9 @@ import javax.inject.Named;
 * To restore a flag back to its default, leave the `--ez value <0|1>` off of the command.
 */
@SysUISingleton
public class FeatureFlagsDebug implements FeatureFlags, Dumpable {
    private static final String TAG = "SysUIFlags";
public class FeatureFlagsDebug implements FeatureFlags {
    static final String TAG = "SysUIFlags";
    static final String ALL_FLAGS = "all_flags";
    private static final String FLAG_COMMAND = "flag";

    private final FlagManager mFlagManager;
    private final SecureSettings mSecureSettings;
@@ -89,7 +80,7 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable {
    private final Map<Integer, Flag<?>> mAllFlags;
    private final Map<Integer, Boolean> mBooleanFlagCache = new TreeMap<>();
    private final Map<Integer, String> mStringFlagCache = new TreeMap<>();
    private final IStatusBarService mBarService;
    private final Restarter mRestarter;

    @Inject
    public FeatureFlagsDebug(
@@ -98,12 +89,10 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable {
            SecureSettings secureSettings,
            SystemPropertiesHelper systemProperties,
            @Main Resources resources,
            DumpManager dumpManager,
            DeviceConfigProxy deviceConfigProxy,
            ServerFlagReader serverFlagReader,
            @Named(ALL_FLAGS) Map<Integer, Flag<?>> allFlags,
            CommandRegistry commandRegistry,
            IStatusBarService barService) {
            Restarter barService) {
        mFlagManager = flagManager;
        mSecureSettings = secureSettings;
        mResources = resources;
@@ -111,7 +100,7 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable {
        mDeviceConfigProxy = deviceConfigProxy;
        mServerFlagReader = serverFlagReader;
        mAllFlags = allFlags;
        mBarService = barService;
        mRestarter = barService;

        IntentFilter filter = new IntentFilter();
        filter.addAction(ACTION_SET_FLAG);
@@ -120,8 +109,6 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable {
        flagManager.setClearCacheAction(this::removeFromCache);
        context.registerReceiver(mReceiver, filter, null, null,
                Context.RECEIVER_EXPORTED_UNAUDITED);
        dumpManager.registerDumpable(TAG, this);
        commandRegistry.registerCommand(FLAG_COMMAND, FlagCommand::new);
    }

    @Override
@@ -266,7 +253,7 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable {
        mFlagManager.dispatchListenersAndMaybeRestart(id, this::restartSystemUI);
    }

    private <T> void eraseFlag(Flag<T> flag) {
    <T> void eraseFlag(Flag<T> flag) {
        if (flag instanceof SysPropFlag) {
            mSystemProperties.erase(((SysPropFlag<T>) flag).getName());
            dispatchListenersAndMaybeRestart(flag.getId(), this::restartAndroid);
@@ -319,13 +306,10 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable {
            return;
        }
        Log.i(TAG, "Restarting Android");
        try {
            mBarService.restart();
        } catch (RemoteException e) {
        }
        mRestarter.restart();
    }

    private void setBooleanFlagInternal(Flag<?> flag, boolean value) {
    void setBooleanFlagInternal(Flag<?> flag, boolean value) {
        if (flag instanceof BooleanFlag) {
            setFlagValue(flag.getId(), value, BooleanFlagSerializer.INSTANCE);
        } else if (flag instanceof ResourceBooleanFlag) {
@@ -342,7 +326,7 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable {
        }
    }

    private void setStringFlagInternal(Flag<?> flag, String value) {
    void setStringFlagInternal(Flag<?> flag, String value) {
        if (flag instanceof StringFlag) {
            setFlagValue(flag.getId(), value, StringFlagSerializer.INSTANCE);
        } else if (flag instanceof ResourceStringFlag) {
@@ -476,154 +460,4 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable {
                + ": [length=" + value.length() + "] \"" + value + "\""));
    }

    class FlagCommand implements Command {
        private final List<String> mOnCommands = List.of("true", "on", "1", "enabled");
        private final List<String> mOffCommands = List.of("false", "off", "0", "disable");

        @Override
        public void execute(@NonNull PrintWriter pw, @NonNull List<String> args) {
            if (args.size() == 0) {
                pw.println("Error: no flag id supplied");
                help(pw);
                pw.println();
                printKnownFlags(pw);
                return;
            }

            if (args.size() > 2) {
                pw.println("Invalid number of arguments.");
                help(pw);
                return;
            }

            int id = 0;
            try {
                id = Integer.parseInt(args.get(0));
                if (!mAllFlags.containsKey(id)) {
                    pw.println("Unknown flag id: " + id);
                    pw.println();
                    printKnownFlags(pw);
                    return;
                }
            } catch (NumberFormatException e) {
                id = flagNameToId(args.get(0));
                if (id == 0) {
                    pw.println("Invalid flag. Must an integer id or flag name: " + args.get(0));
                    return;
                }
            }
            Flag<?> flag = mAllFlags.get(id);

            String cmd = "";
            if (args.size() == 2) {
                cmd = args.get(1).toLowerCase();
            }

            if ("erase".equals(cmd) || "reset".equals(cmd)) {
                eraseFlag(flag);
                return;
            }

            boolean newValue = true;
            if (args.size() == 1 || "toggle".equals(cmd)) {
                boolean enabled = isBooleanFlagEnabled(flag);

                if (args.size() == 1) {
                    pw.println("Flag " + id + " is " + enabled);
                    return;
                }

                newValue = !enabled;
            } else {
                newValue = mOnCommands.contains(cmd);
                if (!newValue && !mOffCommands.contains(cmd)) {
                    pw.println("Invalid on/off argument supplied");
                    help(pw);
                    return;
                }
            }

            pw.flush();  // Next command will restart sysui, so flush before we do so.
            setBooleanFlagInternal(flag, newValue);
        }

        @Override
        public void help(PrintWriter pw) {
            pw.println(
                    "Usage: adb shell cmd statusbar flag <id> "
                            + "[true|false|1|0|on|off|enable|disable|toggle|erase|reset]");
            pw.println("The id can either be a numeric integer or the corresponding field name");
            pw.println(
                    "If no argument is supplied after the id, the flags runtime value is output");
        }

        private boolean isBooleanFlagEnabled(Flag<?> flag) {
            if (flag instanceof ReleasedFlag) {
                return isEnabled((ReleasedFlag) flag);
            } else if (flag instanceof UnreleasedFlag) {
                return isEnabled((UnreleasedFlag) flag);
            } else if (flag instanceof ResourceBooleanFlag) {
                return isEnabled((ResourceBooleanFlag) flag);
            } else if (flag instanceof SysPropFlag) {
                return isEnabled((SysPropBooleanFlag) flag);
            }

            return false;
        }

        private int flagNameToId(String flagName) {
            List<Field> fields = Flags.getFlagFields();
            for (Field field : fields) {
                if (flagName.equals(field.getName())) {
                    return fieldToId(field);
                }
            }

            return 0;
        }

        private int fieldToId(Field field) {
            try {
                Flag<?> flag = (Flag<?>) field.get(null);
                return flag.getId();
            } catch (IllegalAccessException e) {
                // no-op
            }

            return 0;
        }

        private void printKnownFlags(PrintWriter pw) {
            List<Field> fields = Flags.getFlagFields();

            int longestFieldName = 0;
            for (Field field : fields) {
                longestFieldName = Math.max(longestFieldName, field.getName().length());
            }

            pw.println("Known Flags:");
            pw.print("Flag Name");
            for (int i = 0; i < longestFieldName - "Flag Name".length() + 1; i++) {
                pw.print(" ");
            }
            pw.println("ID   Enabled?");
            for (int i = 0; i < longestFieldName; i++) {
                pw.print("=");
            }
            pw.println(" ==== ========");
            for (Field field : fields) {
                int id = fieldToId(field);
                if (id == 0 || !mAllFlags.containsKey(id)) {
                    continue;
                }
                pw.print(field.getName());
                int fieldWidth = field.getName().length();
                for (int i = 0; i < longestFieldName - fieldWidth + 1; i++) {
                    pw.print(" ");
                }
                pw.printf("%-4d ", id);
                pw.println(isBooleanFlagEnabled(mAllFlags.get(id)));
            }
        }
    }
}
+57 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.systemui.flags

import android.content.Context
import com.android.systemui.CoreStartable
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dump.DumpManager
import com.android.systemui.statusbar.commandline.CommandRegistry
import dagger.Binds
import dagger.Module
import dagger.multibindings.ClassKey
import dagger.multibindings.IntoMap
import javax.inject.Inject

class FeatureFlagsDebugStartable
@Inject
constructor(
    @Application context: Context,
    dumpManager: DumpManager,
    private val commandRegistry: CommandRegistry,
    private val flagCommand: FlagCommand,
    featureFlags: FeatureFlags
) : CoreStartable(context) {

    init {
        dumpManager.registerDumpable(FeatureFlagsDebug.TAG) { pw, args ->
            featureFlags.dump(pw, args)
        }
    }

    override fun start() {
        commandRegistry.registerCommand(FlagCommand.FLAG_COMMAND) { flagCommand }
    }
}

@Module
abstract class FeatureFlagsDebugStartableModule {
    @Binds
    @IntoMap
    @ClassKey(FeatureFlagsDebugStartable::class)
    abstract fun bind(impl: FeatureFlagsDebugStartable): CoreStartable
}
Loading