Loading packages/SystemUI/shared/src/com/android/systemui/flags/FlagSerializer.kt +7 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ private const val FIELD_VALUE = "value" private const val FIELD_TYPE = "type" private const val TYPE_BOOLEAN = "boolean" private const val TYPE_STRING = "string" private const val TYPE_INT = "int" private const val TAG = "FlagSerializer" Loading Loading @@ -77,4 +78,10 @@ object StringFlagSerializer : FlagSerializer<String>( JSONObject::getString ) object IntFlagSerializer : FlagSerializer<Int>( TYPE_INT, JSONObject::put, JSONObject::getInt ) class InvalidFlagStorageException : Exception("Data found but is invalid") packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.kt +6 −0 Original line number Diff line number Diff line Loading @@ -44,4 +44,10 @@ interface FeatureFlags : FlagListenable, Dumpable { /** Returns a string value for the given flag. */ fun getString(flag: ResourceStringFlag): String /** Returns an int value for a given flag/ */ fun getInt(flag: IntFlag): Int /** Returns an int value for a given flag/ */ fun getInt(flag: ResourceIntFlag): Int } packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java +36 −0 Original line number Diff line number Diff line Loading @@ -81,6 +81,7 @@ public class FeatureFlagsDebug implements FeatureFlags { private final Map<Integer, Flag<?>> mAllFlags; private final Map<Integer, Boolean> mBooleanFlagCache = new TreeMap<>(); private final Map<Integer, String> mStringFlagCache = new TreeMap<>(); private final Map<Integer, Integer> mIntFlagCache = new TreeMap<>(); private final Restarter mRestarter; private final ServerFlagReader.ChangeListener mOnPropertiesChanged = Loading Loading @@ -209,6 +210,31 @@ public class FeatureFlagsDebug implements FeatureFlags { return mStringFlagCache.get(id); } @NonNull @Override public int getInt(@NonNull IntFlag flag) { int id = flag.getId(); if (!mIntFlagCache.containsKey(id)) { mIntFlagCache.put(id, readFlagValue(id, flag.getDefault(), IntFlagSerializer.INSTANCE)); } return mIntFlagCache.get(id); } @NonNull @Override public int getInt(@NonNull ResourceIntFlag flag) { int id = flag.getId(); if (!mIntFlagCache.containsKey(id)) { mIntFlagCache.put(id, readFlagValue(id, mResources.getInteger(flag.getResourceId()), IntFlagSerializer.INSTANCE)); } return mIntFlagCache.get(id); } /** Specific override for Boolean flags that checks against the teamfood list. */ private boolean readFlagValue(int id, boolean defaultValue) { Boolean result = readBooleanFlagOverride(id); Loading Loading @@ -351,6 +377,16 @@ public class FeatureFlagsDebug implements FeatureFlags { } } void setIntFlagInternal(Flag<?> flag, int value) { if (flag instanceof IntFlag) { setFlagValue(flag.getId(), value, IntFlagSerializer.INSTANCE); } else if (flag instanceof ResourceIntFlag) { setFlagValue(flag.getId(), value, IntFlagSerializer.INSTANCE); } else { throw new IllegalArgumentException("Unknown flag type"); } } private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Loading packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsRelease.java +12 −0 Original line number Diff line number Diff line Loading @@ -165,6 +165,18 @@ public class FeatureFlagsRelease implements FeatureFlags { return defaultValue; } @NonNull @Override public int getInt(@NonNull IntFlag flag) { return flag.getDefault(); } @NonNull @Override public int getInt(@NonNull ResourceIntFlag flag) { return mResources.getInteger(flag.getResourceId()); } @Override public void dump(@NonNull PrintWriter pw, @NonNull String[] args) { pw.println("can override: false"); Loading packages/SystemUI/src/com/android/systemui/flags/FlagCommand.java +124 −26 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ public 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"); private final List<String> mSetCommands = List.of("set", "put"); private final FeatureFlagsDebug mFeatureFlags; private final Map<Integer, Flag<?>> mAllFlags; Loading @@ -60,12 +61,6 @@ public class FlagCommand implements Command { return; } if (args.size() > 2) { pw.println("Invalid number of arguments."); help(pw); return; } int id = 0; try { id = Integer.parseInt(args.get(0)); Loading @@ -85,48 +80,113 @@ public class FlagCommand implements Command { Flag<?> flag = mAllFlags.get(id); String cmd = ""; if (args.size() == 2) { if (args.size() > 1) { cmd = args.get(1).toLowerCase(); } if ("erase".equals(cmd) || "reset".equals(cmd)) { mFeatureFlags.eraseFlag(flag); if (args.size() > 2) { pw.println("Invalid number of arguments to reset a flag."); help(pw); return; } boolean newValue = true; if (args.size() == 1 || "toggle".equals(cmd)) { boolean enabled = isBooleanFlagEnabled(flag); mFeatureFlags.eraseFlag(flag); return; } boolean shouldSet = true; if (args.size() == 1) { pw.println("Flag " + id + " is " + enabled); shouldSet = false; } if (isBooleanFlag(flag)) { if (args.size() > 2) { pw.println("Invalid number of arguments for a boolean flag."); help(pw); return; } newValue = !enabled; } else { newValue = mOnCommands.contains(cmd); if (!newValue && !mOffCommands.contains(cmd)) { 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 " + id + " 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 " + id + " 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 " + id + " 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 " + id + " to " + value); pw.flush(); // Next command will restart sysui, so flush before we do so. mFeatureFlags.setIntFlagInternal(flag, value); } else { pw.println("Flag " + id + " is " + getIntFlag(flag)); } return; } } @Override public void help(PrintWriter pw) { pw.println( "Usage: adb shell cmd statusbar flag <id> " 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) || (flag instanceof DeviceConfigBooleanFlag); } private boolean isBooleanFlagEnabled(Flag<?> flag) { if (flag instanceof ReleasedFlag) { return mFeatureFlags.isEnabled((ReleasedFlag) flag); Loading @@ -141,6 +201,34 @@ public class FlagCommand implements Command { 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) { List<Field> fields = Flags.getFlagFields(); for (Field field : fields) { Loading Loading @@ -176,13 +264,15 @@ public class FlagCommand implements Command { for (int i = 0; i < longestFieldName - "Flag Name".length() + 1; i++) { pw.print(" "); } pw.println("ID Enabled?"); pw.println("ID Value"); for (int i = 0; i < longestFieldName; i++) { pw.print("="); } pw.println(" ==== ========"); pw.println(" ==== ====="); for (Field field : fields) { int id = fieldToId(field); Flag<?> flag = mAllFlags.get(id); if (id == 0 || !mAllFlags.containsKey(id)) { continue; } Loading @@ -192,7 +282,15 @@ public class FlagCommand implements Command { pw.print(" "); } pw.printf("%-4d ", id); if (isBooleanFlag(flag)) { pw.println(isBooleanFlagEnabled(mAllFlags.get(id))); } else if (isStringFlag(flag)) { pw.println(getStringFlag(flag)); } else if (isIntFlag(flag)) { pw.println(getIntFlag(flag)); } else { pw.println("<unknown flag type>"); } } } } Loading
packages/SystemUI/shared/src/com/android/systemui/flags/FlagSerializer.kt +7 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ private const val FIELD_VALUE = "value" private const val FIELD_TYPE = "type" private const val TYPE_BOOLEAN = "boolean" private const val TYPE_STRING = "string" private const val TYPE_INT = "int" private const val TAG = "FlagSerializer" Loading Loading @@ -77,4 +78,10 @@ object StringFlagSerializer : FlagSerializer<String>( JSONObject::getString ) object IntFlagSerializer : FlagSerializer<Int>( TYPE_INT, JSONObject::put, JSONObject::getInt ) class InvalidFlagStorageException : Exception("Data found but is invalid")
packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.kt +6 −0 Original line number Diff line number Diff line Loading @@ -44,4 +44,10 @@ interface FeatureFlags : FlagListenable, Dumpable { /** Returns a string value for the given flag. */ fun getString(flag: ResourceStringFlag): String /** Returns an int value for a given flag/ */ fun getInt(flag: IntFlag): Int /** Returns an int value for a given flag/ */ fun getInt(flag: ResourceIntFlag): Int }
packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java +36 −0 Original line number Diff line number Diff line Loading @@ -81,6 +81,7 @@ public class FeatureFlagsDebug implements FeatureFlags { private final Map<Integer, Flag<?>> mAllFlags; private final Map<Integer, Boolean> mBooleanFlagCache = new TreeMap<>(); private final Map<Integer, String> mStringFlagCache = new TreeMap<>(); private final Map<Integer, Integer> mIntFlagCache = new TreeMap<>(); private final Restarter mRestarter; private final ServerFlagReader.ChangeListener mOnPropertiesChanged = Loading Loading @@ -209,6 +210,31 @@ public class FeatureFlagsDebug implements FeatureFlags { return mStringFlagCache.get(id); } @NonNull @Override public int getInt(@NonNull IntFlag flag) { int id = flag.getId(); if (!mIntFlagCache.containsKey(id)) { mIntFlagCache.put(id, readFlagValue(id, flag.getDefault(), IntFlagSerializer.INSTANCE)); } return mIntFlagCache.get(id); } @NonNull @Override public int getInt(@NonNull ResourceIntFlag flag) { int id = flag.getId(); if (!mIntFlagCache.containsKey(id)) { mIntFlagCache.put(id, readFlagValue(id, mResources.getInteger(flag.getResourceId()), IntFlagSerializer.INSTANCE)); } return mIntFlagCache.get(id); } /** Specific override for Boolean flags that checks against the teamfood list. */ private boolean readFlagValue(int id, boolean defaultValue) { Boolean result = readBooleanFlagOverride(id); Loading Loading @@ -351,6 +377,16 @@ public class FeatureFlagsDebug implements FeatureFlags { } } void setIntFlagInternal(Flag<?> flag, int value) { if (flag instanceof IntFlag) { setFlagValue(flag.getId(), value, IntFlagSerializer.INSTANCE); } else if (flag instanceof ResourceIntFlag) { setFlagValue(flag.getId(), value, IntFlagSerializer.INSTANCE); } else { throw new IllegalArgumentException("Unknown flag type"); } } private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Loading
packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsRelease.java +12 −0 Original line number Diff line number Diff line Loading @@ -165,6 +165,18 @@ public class FeatureFlagsRelease implements FeatureFlags { return defaultValue; } @NonNull @Override public int getInt(@NonNull IntFlag flag) { return flag.getDefault(); } @NonNull @Override public int getInt(@NonNull ResourceIntFlag flag) { return mResources.getInteger(flag.getResourceId()); } @Override public void dump(@NonNull PrintWriter pw, @NonNull String[] args) { pw.println("can override: false"); Loading
packages/SystemUI/src/com/android/systemui/flags/FlagCommand.java +124 −26 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ public 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"); private final List<String> mSetCommands = List.of("set", "put"); private final FeatureFlagsDebug mFeatureFlags; private final Map<Integer, Flag<?>> mAllFlags; Loading @@ -60,12 +61,6 @@ public class FlagCommand implements Command { return; } if (args.size() > 2) { pw.println("Invalid number of arguments."); help(pw); return; } int id = 0; try { id = Integer.parseInt(args.get(0)); Loading @@ -85,48 +80,113 @@ public class FlagCommand implements Command { Flag<?> flag = mAllFlags.get(id); String cmd = ""; if (args.size() == 2) { if (args.size() > 1) { cmd = args.get(1).toLowerCase(); } if ("erase".equals(cmd) || "reset".equals(cmd)) { mFeatureFlags.eraseFlag(flag); if (args.size() > 2) { pw.println("Invalid number of arguments to reset a flag."); help(pw); return; } boolean newValue = true; if (args.size() == 1 || "toggle".equals(cmd)) { boolean enabled = isBooleanFlagEnabled(flag); mFeatureFlags.eraseFlag(flag); return; } boolean shouldSet = true; if (args.size() == 1) { pw.println("Flag " + id + " is " + enabled); shouldSet = false; } if (isBooleanFlag(flag)) { if (args.size() > 2) { pw.println("Invalid number of arguments for a boolean flag."); help(pw); return; } newValue = !enabled; } else { newValue = mOnCommands.contains(cmd); if (!newValue && !mOffCommands.contains(cmd)) { 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 " + id + " 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 " + id + " 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 " + id + " 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 " + id + " to " + value); pw.flush(); // Next command will restart sysui, so flush before we do so. mFeatureFlags.setIntFlagInternal(flag, value); } else { pw.println("Flag " + id + " is " + getIntFlag(flag)); } return; } } @Override public void help(PrintWriter pw) { pw.println( "Usage: adb shell cmd statusbar flag <id> " 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) || (flag instanceof DeviceConfigBooleanFlag); } private boolean isBooleanFlagEnabled(Flag<?> flag) { if (flag instanceof ReleasedFlag) { return mFeatureFlags.isEnabled((ReleasedFlag) flag); Loading @@ -141,6 +201,34 @@ public class FlagCommand implements Command { 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) { List<Field> fields = Flags.getFlagFields(); for (Field field : fields) { Loading Loading @@ -176,13 +264,15 @@ public class FlagCommand implements Command { for (int i = 0; i < longestFieldName - "Flag Name".length() + 1; i++) { pw.print(" "); } pw.println("ID Enabled?"); pw.println("ID Value"); for (int i = 0; i < longestFieldName; i++) { pw.print("="); } pw.println(" ==== ========"); pw.println(" ==== ====="); for (Field field : fields) { int id = fieldToId(field); Flag<?> flag = mAllFlags.get(id); if (id == 0 || !mAllFlags.containsKey(id)) { continue; } Loading @@ -192,7 +282,15 @@ public class FlagCommand implements Command { pw.print(" "); } pw.printf("%-4d ", id); if (isBooleanFlag(flag)) { pw.println(isBooleanFlagEnabled(mAllFlags.get(id))); } else if (isStringFlag(flag)) { pw.println(getStringFlag(flag)); } else if (isIntFlag(flag)) { pw.println(getIntFlag(flag)); } else { pw.println("<unknown flag type>"); } } } }