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

Commit 7f7a3e1d authored by Dennis Shen's avatar Dennis Shen Committed by Android (Google) Code Review
Browse files

Merge "differentiate aconfig flags and legacy flags in device config dump" into main

parents bc048111 d828a1e3
Loading
Loading
Loading
Loading
+105 −22
Original line number Diff line number Diff line
@@ -40,8 +40,12 @@ import android.provider.UpdatableDeviceConfigServiceReadiness;

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.lang.reflect.Modifier;
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 @@ public final class DeviceConfigService extends Binder {
    @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,9 +183,8 @@ public final class DeviceConfigService extends Binder {
            mProvider = provider;
        }

        public static List<String> listAll(IContentProvider provider) {
            final ArrayList<String> lines = new ArrayList<>();

      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,
@@ -133,15 +195,36 @@ public final class DeviceConfigService extends Binder {
            if (b != null) {
                Map<String, String> flagsToValues =
                    (HashMap) b.getSerializable(Settings.NameValueTable.VALUE);
                    for (String key : flagsToValues.keySet()) {
                        lines.add(key + "=" + flagsToValues.get(key));
                allFlags.putAll(flagsToValues);
            }
        } 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);
            } catch (RemoteException e) {
                throw new RuntimeException("Failed in IPC", e);
        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;
      }