Merge "differentiate aconfig flags and legacy flags in device config dump" into main
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
index 00f2d0e..ffaebf4 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
@@ -40,8 +40,12 @@
import com.android.internal.util.FastPrintWriter;
+import java.io.File;
import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.FileOutputStream;
+import java.io.InputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Field;
@@ -49,14 +53,22 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Scanner;
/**
* Receives shell commands from the command line related to device config flags, and dispatches them
* to the SettingsProvider.
*/
public final class DeviceConfigService extends Binder {
+ private static final List<String> aconfigTextProtoFilesOnDevice = List.of(
+ "/system/etc/aconfig_flags.textproto",
+ "/system_ext/etc/aconfig_flags.textproto",
+ "/system_ext/etc/aconfig_flags.textproto",
+ "/vendor/etc/aconfig_flags.textproto");
+
final SettingsProvider mProvider;
public DeviceConfigService(SettingsProvider provider) {
@@ -78,10 +90,61 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
final IContentProvider iprovider = mProvider.getIContentProvider();
- pw.println("device config properties:");
+ pw.println("DeviceConfig flags:");
for (String line : MyShellCommand.listAll(iprovider)) {
pw.println(line);
}
+
+ ArrayList<String> missingFiles = new ArrayList<String>();
+ for (String fileName : aconfigTextProtoFilesOnDevice) {
+ File aconfigFile = new File(fileName);
+ if (!aconfigFile.exists()) {
+ missingFiles.add(fileName);
+ }
+ }
+
+ if (missingFiles.isEmpty()) {
+ pw.println("\nAconfig flags:");
+ for (String name : MyShellCommand.listAllAconfigFlags(iprovider)) {
+ pw.println(name);
+ }
+ } else {
+ pw.println("\nFailed to dump aconfig flags due to missing files:");
+ for (String fileName : missingFiles) {
+ pw.println(fileName);
+ }
+ }
+ }
+
+ private static HashSet<String> getAconfigFlagNamesInDeviceConfig() {
+ HashSet<String> nameSet = new HashSet<String>();
+ for (String fileName : aconfigTextProtoFilesOnDevice) {
+ try{
+ File aconfigFile = new File(fileName);
+ String packageName = "";
+ String namespace = "";
+ String name = "";
+
+ try (Scanner scanner = new Scanner(aconfigFile)) {
+ while (scanner.hasNextLine()) {
+ String data = scanner.nextLine().replaceAll("\\s+","");
+ if (data.startsWith("package:\"")) {
+ packageName = data.substring(9, data.length()-1);
+ } else if (data.startsWith("name:\"")) {
+ name = data.substring(6, data.length()-1);
+ } else if (data.startsWith("namespace:\"")) {
+ namespace = data.substring(11, data.length()-1);
+ nameSet.add(namespace + "/" + packageName + "." + name);
+ }
+ }
+ }
+
+ } catch (FileNotFoundException e) {
+ continue;
+ }
+ }
+
+ return nameSet;
}
private void callUpdableDeviceConfigShellCommandHandler(FileDescriptor in, FileDescriptor out,
@@ -120,31 +183,51 @@
mProvider = provider;
}
- public static List<String> listAll(IContentProvider provider) {
- final ArrayList<String> lines = new ArrayList<>();
-
- try {
- Bundle args = new Bundle();
- args.putInt(Settings.CALL_METHOD_USER_KEY,
- ActivityManager.getService().getCurrentUser().id);
- Bundle b = provider.call(new AttributionSource(Process.myUid(),
- resolveCallingPackage(), null), Settings.AUTHORITY,
- Settings.CALL_METHOD_LIST_CONFIG, null, args);
- if (b != null) {
- Map<String, String> flagsToValues =
- (HashMap) b.getSerializable(Settings.NameValueTable.VALUE);
- for (String key : flagsToValues.keySet()) {
- lines.add(key + "=" + flagsToValues.get(key));
- }
- }
-
- Collections.sort(lines);
- } catch (RemoteException e) {
- throw new RuntimeException("Failed in IPC", e);
+ public static HashMap<String, String> getAllFlags(IContentProvider provider) {
+ HashMap<String, String> allFlags = new HashMap<String, String>();
+ try {
+ Bundle args = new Bundle();
+ args.putInt(Settings.CALL_METHOD_USER_KEY,
+ ActivityManager.getService().getCurrentUser().id);
+ Bundle b = provider.call(new AttributionSource(Process.myUid(),
+ resolveCallingPackage(), null), Settings.AUTHORITY,
+ Settings.CALL_METHOD_LIST_CONFIG, null, args);
+ if (b != null) {
+ Map<String, String> flagsToValues =
+ (HashMap) b.getSerializable(Settings.NameValueTable.VALUE);
+ allFlags.putAll(flagsToValues);
}
- return lines;
+ } catch (RemoteException e) {
+ throw new RuntimeException("Failed in IPC", e);
}
+ return allFlags;
+ }
+
+ public static List<String> listAll(IContentProvider provider) {
+ HashMap<String, String> allFlags = getAllFlags(provider);
+ final ArrayList<String> lines = new ArrayList<>();
+ for (String key : allFlags.keySet()) {
+ lines.add(key + "=" + allFlags.get(key));
+ }
+ Collections.sort(lines);
+ return lines;
+ }
+
+ public static List<String> listAllAconfigFlags(IContentProvider provider) {
+ HashMap<String, String> allFlags = getAllFlags(provider);
+ HashSet<String> aconfigFlagNames = getAconfigFlagNamesInDeviceConfig();
+ final ArrayList<String> lines = new ArrayList<>();
+ for (String key : aconfigFlagNames) {
+ String val = allFlags.get(key);
+ if (val != null) {
+ lines.add(key + "=" + val);
+ }
+ }
+ Collections.sort(lines);
+ return lines;
+ }
+
@SuppressLint("AndroidFrameworkRequiresPermission")
@Override
public int onCommand(String cmd) {