blob: daf9429344a79948e1bab13ff3c648492a13fed4 [file] [log] [blame]
/*
* 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 static com.android.systemui.flags.FlagsCommonModule.ALL_FLAGS;
import androidx.annotation.NonNull;
import com.android.systemui.statusbar.commandline.Command;
import java.io.PrintWriter;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Named;
/**
* A {@link Command} used to flip flags in SystemUI.
*/
public class FlagCommand implements Command {
public static final String FLAG_COMMAND = "flag";
private final List<String> mOnCommands = List.of("true", "on", "1", "enabled");
private final List<String> mOffCommands = List.of("false", "off", "0", "disable");
private final List<String> mSetCommands = List.of("set", "put");
private final FeatureFlagsDebug mFeatureFlags;
private final Map<String, Flag<?>> mAllFlags;
@Inject
FlagCommand(
FeatureFlagsDebug featureFlags,
@Named(ALL_FLAGS) Map<String, Flag<?>> allFlags
) {
mFeatureFlags = featureFlags;
mAllFlags = allFlags;
}
@Override
public void execute(@NonNull PrintWriter pw, @NonNull List<String> args) {
if (args.size() == 0) {
pw.println("Error: no flag name supplied");
help(pw);
pw.println();
printKnownFlags(pw);
return;
}
String name = args.get(0);
if (!mAllFlags.containsKey(name)) {
pw.println("Unknown flag name: " + name);
pw.println();
printKnownFlags(pw);
return;
}
Flag<?> flag = mAllFlags.get(name);
String cmd = "";
if (args.size() > 1) {
cmd = args.get(1).toLowerCase();
}
if ("erase".equals(cmd) || "reset".equals(cmd)) {
if (args.size() > 2) {
pw.println("Invalid number of arguments to reset a flag.");
help(pw);
return;
}
mFeatureFlags.eraseFlag(flag);
return;
}
boolean shouldSet = true;
if (args.size() == 1) {
shouldSet = false;
}
if (isBooleanFlag(flag)) {
if (args.size() > 2) {
pw.println("Invalid number of arguments for a boolean flag.");
help(pw);
return;
}
boolean newValue = isBooleanFlagEnabled(flag);
if ("toggle".equals(cmd)) {
newValue = !newValue;
} else if (mOnCommands.contains(cmd)) {
newValue = true;
} else if (mOffCommands.contains(cmd)) {
newValue = false;
} else if (shouldSet) {
pw.println("Invalid on/off argument supplied");
help(pw);
return;
}
pw.println("Flag " + name + " is " + newValue);
pw.flush(); // Next command will restart sysui, so flush before we do so.
if (shouldSet) {
mFeatureFlags.setBooleanFlagInternal(flag, newValue);
}
return;
} else if (isStringFlag(flag)) {
if (shouldSet) {
if (args.size() != 3) {
pw.println("Invalid number of arguments a StringFlag.");
help(pw);
return;
} else if (!mSetCommands.contains(cmd)) {
pw.println("Unknown command: " + cmd);
help(pw);
return;
}
String value = args.get(2);
pw.println("Setting Flag " + name + " to " + value);
pw.flush(); // Next command will restart sysui, so flush before we do so.
mFeatureFlags.setStringFlagInternal(flag, args.get(2));
} else {
pw.println("Flag " + name + " is " + getStringFlag(flag));
}
return;
} else if (isIntFlag(flag)) {
if (shouldSet) {
if (args.size() != 3) {
pw.println("Invalid number of arguments for an IntFlag.");
help(pw);
return;
} else if (!mSetCommands.contains(cmd)) {
pw.println("Unknown command: " + cmd);
help(pw);
return;
}
int value = Integer.parseInt(args.get(2));
pw.println("Setting Flag " + name + " to " + value);
pw.flush(); // Next command will restart sysui, so flush before we do so.
mFeatureFlags.setIntFlagInternal(flag, value);
} else {
pw.println("Flag " + name + " is " + getIntFlag(flag));
}
return;
}
}
@Override
public void help(PrintWriter pw) {
pw.println("Usage: adb shell cmd statusbar flag <id> [options]");
pw.println();
pw.println(" Boolean Flag Options: "
+ "[true|false|1|0|on|off|enable|disable|toggle|erase|reset]");
pw.println(" String Flag Options: [set|put \"<value>\"]");
pw.println(" Int Flag Options: [set|put <value>]");
pw.println();
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 isBooleanFlag(Flag<?> flag) {
return (flag instanceof BooleanFlag)
|| (flag instanceof ResourceBooleanFlag)
|| (flag instanceof SysPropFlag);
}
private boolean isBooleanFlagEnabled(Flag<?> flag) {
if (flag instanceof ReleasedFlag) {
return mFeatureFlags.isEnabled((ReleasedFlag) flag);
} else if (flag instanceof UnreleasedFlag) {
return mFeatureFlags.isEnabled((UnreleasedFlag) flag);
} else if (flag instanceof ResourceBooleanFlag) {
return mFeatureFlags.isEnabled((ResourceBooleanFlag) flag);
} else if (flag instanceof SysPropFlag) {
return mFeatureFlags.isEnabled((SysPropBooleanFlag) flag);
}
return false;
}
private boolean isStringFlag(Flag<?> flag) {
return (flag instanceof StringFlag) || (flag instanceof ResourceStringFlag);
}
private String getStringFlag(Flag<?> flag) {
if (flag instanceof StringFlag) {
return mFeatureFlags.getString((StringFlag) flag);
} else if (flag instanceof ResourceStringFlag) {
return mFeatureFlags.getString((ResourceStringFlag) flag);
}
return "";
}
private boolean isIntFlag(Flag<?> flag) {
return (flag instanceof IntFlag) || (flag instanceof ResourceIntFlag);
}
private int getIntFlag(Flag<?> flag) {
if (flag instanceof IntFlag) {
return mFeatureFlags.getInt((IntFlag) flag);
} else if (flag instanceof ResourceIntFlag) {
return mFeatureFlags.getInt((ResourceIntFlag) flag);
}
return 0;
}
private int flagNameToId(String flagName) {
Map<String, Flag<?>> flagFields = FlagsFactory.INSTANCE.getKnownFlags();
for (String fieldName : flagFields.keySet()) {
if (flagName.equals(fieldName)) {
return flagFields.get(fieldName).getId();
}
}
return 0;
}
private void printKnownFlags(PrintWriter pw) {
Map<String, Flag<?>> fields = FlagsFactory.INSTANCE.getKnownFlags();
int longestFieldName = 0;
for (String fieldName : fields.keySet()) {
longestFieldName = Math.max(longestFieldName, fieldName.length());
}
pw.println("Known Flags:");
pw.print("Flag Name");
for (int i = 0; i < longestFieldName - "Flag Name".length() + 1; i++) {
pw.print(" ");
}
pw.println(" Value");
for (int i = 0; i < longestFieldName; i++) {
pw.print("=");
}
pw.println(" ========");
for (String fieldName : fields.keySet()) {
Flag<?> flag = fields.get(fieldName);
if (!mAllFlags.containsKey(flag.getName())) {
continue;
}
pw.print(fieldName);
int fieldWidth = fieldName.length();
for (int i = 0; i < longestFieldName - fieldWidth + 1; i++) {
pw.print(" ");
}
pw.print(" ");
if (isBooleanFlag(flag)) {
pw.println(isBooleanFlagEnabled(flag));
} else if (isStringFlag(flag)) {
pw.println(getStringFlag(flag));
} else if (isIntFlag(flag)) {
pw.println(getIntFlag(flag));
} else {
pw.println("<unknown flag type>");
}
}
}
}