Loading service/src/com/android/server/bluetooth/BluetoothManagerService.java +24 −105 Original line number Diff line number Diff line Loading @@ -76,7 +76,6 @@ import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.provider.DeviceConfig; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.sysprop.BluetoothProperties; Loading Loading @@ -118,7 +117,6 @@ import java.util.concurrent.FutureTask; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.stream.Collectors; class BluetoothManagerService { private static final String TAG = BluetoothManagerService.class.getSimpleName(); Loading Loading @@ -2317,13 +2315,6 @@ class BluetoothManagerService { } String errorMsg = null; String flagString = ""; try { flagString = dumpBluetoothFlags(writer); } catch (Exception e) { writer.println("Exception while dumping Bluetooth Flags"); } writer.println("Bluetooth Status"); writer.println(" enabled: " + isEnabled()); writer.println(" state: " + mState); Loading Loading @@ -2373,17 +2364,19 @@ class BluetoothManagerService { writer.println(""); writer.flush(); dumpBluetoothFlags(writer); writer.println(""); if (mAdapter == null) { errorMsg = "Bluetooth Service not connected"; } else { if (args.length == 0) { // Add arg to produce output args = new String[1]; args[0] = "--print"; } writer.println(flagString); if (mAdapter == null) { errorMsg = "Bluetooth Service not connected"; } else { try { mAdapter.getAdapterBinder().asBinder().dumpAsync(fd, args); } catch (RemoteException re) { Loading @@ -2395,96 +2388,22 @@ class BluetoothManagerService { } } private static class FlagValue { private final String mSnakeName; private final boolean mDefaultValue; private final boolean mManuallyEnabledInJava; private final boolean mManuallyEnabledInNative; FlagValue(String name, boolean defaultValue) { mSnakeName = name.replaceAll("([A-Z])", "_$1").toLowerCase(Locale.US); mDefaultValue = defaultValue; mManuallyEnabledInJava = getJavaFlagValue(); mManuallyEnabledInNative = getNativeFlagValue(); } private boolean getJavaFlagValue() { return DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_BLUETOOTH, "com.android.bluetooth.flags." + mSnakeName, false); } private boolean getNativeFlagValue() { return SystemProperties.getBoolean( "persist.device_config.aconfig_flags.bluetooth.com.android.bluetooth.flags." + mSnakeName, false); } boolean isManuallyOverridden() { return mManuallyEnabledInJava || mManuallyEnabledInNative; } boolean isPartiallyOverridden() { return isManuallyOverridden() && (mDefaultValue != mManuallyEnabledInJava || mDefaultValue != mManuallyEnabledInNative || mManuallyEnabledInJava != mManuallyEnabledInNative); } static String toIcon(boolean flagValue) { return flagValue ? "[■]" : "[ ]"; } void dump(StringBuilder sb) { sb.append("\t").append(toIcon(mDefaultValue)).append(": ").append(mSnakeName); if (isManuallyOverridden()) { sb.append(" (Manual override)"); if (isPartiallyOverridden()) { sb.append(String.format(" (%s: Java)", toIcon(mManuallyEnabledInJava))); sb.append(String.format(" (%s: Native)", toIcon(mManuallyEnabledInNative))); sb.append(" INCONSISTENT OVERRIDE FOR THIS FLAG.") .append(" This can lead to unpredictable behavior."); } } sb.append("\n"); } } private String dumpBluetoothFlags(PrintWriter writer) { List<FlagValue> flags = private void dumpBluetoothFlags(PrintWriter writer) { writer.println("🚩Flag dump:"); Arrays.stream(Flags.class.getDeclaredMethods()) .map( .forEach( (Method m) -> { String name = m.getName().replaceAll("([A-Z])", "_$1").toLowerCase(Locale.US); boolean flagValue; try { return new FlagValue(m.getName(), (boolean) m.invoke(null)); flagValue = (boolean) m.invoke(null); } catch (IllegalAccessException | InvocationTargetException e) { writer.println("Exception caught while dumping flag:" + e); writer.println("Cannot invoke " + name + " flag:" + e); throw new RuntimeException(e); } }) .collect(Collectors.toList()); StringBuilder flagOverride = new StringBuilder(); flags.stream().filter(FlagValue::isManuallyOverridden).forEach(f -> f.dump(flagOverride)); if (flagOverride.length() > 0) { writer.println("🚩Some flags have a local override. Make sure this is expected"); if (flags.stream().anyMatch(FlagValue::isPartiallyOverridden)) { writer.println("CRITICAL WARNING:"); writer.println("\tSome flags differ between native and java code !"); writer.println( "\tEither they are only enabled in java or only enabled in native. This can" + " lead to critical failure and/or hard to debug issues."); } writer.println(flagOverride.toString()); writer.println("---------------------------------------------------------------------"); writer.println(""); } StringBuilder flagDumpBuilder = new StringBuilder("🚩Flag dump:\n"); flags.stream().forEach(f -> f.dump(flagDumpBuilder)); return flagDumpBuilder.toString(); writer.println("\t" + (flagValue ? "[■]" : "[ ]") + ": " + name); }); } private void dumpProto(FileDescriptor fd) { Loading Loading
service/src/com/android/server/bluetooth/BluetoothManagerService.java +24 −105 Original line number Diff line number Diff line Loading @@ -76,7 +76,6 @@ import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.provider.DeviceConfig; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.sysprop.BluetoothProperties; Loading Loading @@ -118,7 +117,6 @@ import java.util.concurrent.FutureTask; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.stream.Collectors; class BluetoothManagerService { private static final String TAG = BluetoothManagerService.class.getSimpleName(); Loading Loading @@ -2317,13 +2315,6 @@ class BluetoothManagerService { } String errorMsg = null; String flagString = ""; try { flagString = dumpBluetoothFlags(writer); } catch (Exception e) { writer.println("Exception while dumping Bluetooth Flags"); } writer.println("Bluetooth Status"); writer.println(" enabled: " + isEnabled()); writer.println(" state: " + mState); Loading Loading @@ -2373,17 +2364,19 @@ class BluetoothManagerService { writer.println(""); writer.flush(); dumpBluetoothFlags(writer); writer.println(""); if (mAdapter == null) { errorMsg = "Bluetooth Service not connected"; } else { if (args.length == 0) { // Add arg to produce output args = new String[1]; args[0] = "--print"; } writer.println(flagString); if (mAdapter == null) { errorMsg = "Bluetooth Service not connected"; } else { try { mAdapter.getAdapterBinder().asBinder().dumpAsync(fd, args); } catch (RemoteException re) { Loading @@ -2395,96 +2388,22 @@ class BluetoothManagerService { } } private static class FlagValue { private final String mSnakeName; private final boolean mDefaultValue; private final boolean mManuallyEnabledInJava; private final boolean mManuallyEnabledInNative; FlagValue(String name, boolean defaultValue) { mSnakeName = name.replaceAll("([A-Z])", "_$1").toLowerCase(Locale.US); mDefaultValue = defaultValue; mManuallyEnabledInJava = getJavaFlagValue(); mManuallyEnabledInNative = getNativeFlagValue(); } private boolean getJavaFlagValue() { return DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_BLUETOOTH, "com.android.bluetooth.flags." + mSnakeName, false); } private boolean getNativeFlagValue() { return SystemProperties.getBoolean( "persist.device_config.aconfig_flags.bluetooth.com.android.bluetooth.flags." + mSnakeName, false); } boolean isManuallyOverridden() { return mManuallyEnabledInJava || mManuallyEnabledInNative; } boolean isPartiallyOverridden() { return isManuallyOverridden() && (mDefaultValue != mManuallyEnabledInJava || mDefaultValue != mManuallyEnabledInNative || mManuallyEnabledInJava != mManuallyEnabledInNative); } static String toIcon(boolean flagValue) { return flagValue ? "[■]" : "[ ]"; } void dump(StringBuilder sb) { sb.append("\t").append(toIcon(mDefaultValue)).append(": ").append(mSnakeName); if (isManuallyOverridden()) { sb.append(" (Manual override)"); if (isPartiallyOverridden()) { sb.append(String.format(" (%s: Java)", toIcon(mManuallyEnabledInJava))); sb.append(String.format(" (%s: Native)", toIcon(mManuallyEnabledInNative))); sb.append(" INCONSISTENT OVERRIDE FOR THIS FLAG.") .append(" This can lead to unpredictable behavior."); } } sb.append("\n"); } } private String dumpBluetoothFlags(PrintWriter writer) { List<FlagValue> flags = private void dumpBluetoothFlags(PrintWriter writer) { writer.println("🚩Flag dump:"); Arrays.stream(Flags.class.getDeclaredMethods()) .map( .forEach( (Method m) -> { String name = m.getName().replaceAll("([A-Z])", "_$1").toLowerCase(Locale.US); boolean flagValue; try { return new FlagValue(m.getName(), (boolean) m.invoke(null)); flagValue = (boolean) m.invoke(null); } catch (IllegalAccessException | InvocationTargetException e) { writer.println("Exception caught while dumping flag:" + e); writer.println("Cannot invoke " + name + " flag:" + e); throw new RuntimeException(e); } }) .collect(Collectors.toList()); StringBuilder flagOverride = new StringBuilder(); flags.stream().filter(FlagValue::isManuallyOverridden).forEach(f -> f.dump(flagOverride)); if (flagOverride.length() > 0) { writer.println("🚩Some flags have a local override. Make sure this is expected"); if (flags.stream().anyMatch(FlagValue::isPartiallyOverridden)) { writer.println("CRITICAL WARNING:"); writer.println("\tSome flags differ between native and java code !"); writer.println( "\tEither they are only enabled in java or only enabled in native. This can" + " lead to critical failure and/or hard to debug issues."); } writer.println(flagOverride.toString()); writer.println("---------------------------------------------------------------------"); writer.println(""); } StringBuilder flagDumpBuilder = new StringBuilder("🚩Flag dump:\n"); flags.stream().forEach(f -> f.dump(flagDumpBuilder)); return flagDumpBuilder.toString(); writer.println("\t" + (flagValue ? "[■]" : "[ ]") + ": " + name); }); } private void dumpProto(FileDescriptor fd) { Loading