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

Commit deebf047 authored by Ted Bauer's avatar Ted Bauer
Browse files

Reduce Binder transaction size in getAllProperties

getAllStrings makes a Binder transaction to retrieve all flag keys and values.
The transaction is becoming prohibitively large, so switch to making a Binder
call to retrieve the namespaces first, then call getStrings with each namespace.

Change-Id: Icb3d946a2cdf9c4497ab0605b4fe9101ed67598d
Flag: android.provider.reduce_binder_transaction_size
Test: m
Bug: 362652574
parent ec3c8b5e
Loading
Loading
Loading
Loading
+35 −7
Original line number Diff line number Diff line
@@ -111,6 +111,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -3022,6 +3023,9 @@ public final class Settings {
    /** @hide - Private call() method to query the 'configuration' table */
    public static final String CALL_METHOD_LIST_CONFIG = "LIST_config";
    /** @hide - Private call() method to query the 'configuration' tables' namespaces */
    public static final String CALL_METHOD_LIST_NAMESPACES_CONFIG = "LIST_namespaces_config";
    /** @hide - Private call() method to disable / re-enable syncs to the 'configuration' table */
    public static final String CALL_METHOD_SET_SYNC_DISABLED_MODE_CONFIG =
            "SET_SYNC_DISABLED_MODE_config";
@@ -20458,6 +20462,10 @@ public final class Settings {
         *
         * The keys take the form {@code namespace/flag}, and the values are the flag values.
         *
         * Note: this API is _not_ performant, and may make a large number of
         * Binder calls. It is intended for use in testing and debugging, and
         * should not be used in performance-sensitive code.
         *
         * @hide
         */
        @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@@ -20469,14 +20477,34 @@ public final class Settings {
                Bundle arg = new Bundle();
                arg.putInt(Settings.CALL_METHOD_USER_KEY, resolver.getUserId());
                IContentProvider cp = sProviderHolder.getProvider(resolver);
                if (Flags.reduceBinderTransactionSizeForGetAllProperties()) {
                    Bundle b = cp.call(resolver.getAttributionSource(),
                            sProviderHolder.mUri.getAuthority(),
                                CALL_METHOD_LIST_NAMESPACES_CONFIG, null, arg);
                    if (b != null) {
                        HashSet<String> namespaces =
                                (HashSet) b.getSerializable(Settings.NameValueTable.VALUE,
                                                java.util.HashSet.class);
                        for (String namespace : namespaces) {
                            Map<String, String> keyValues =
                                    getStrings(namespace, new ArrayList());
                            for (String key : keyValues.keySet()) {
                                allFlags.put(namespace + "/" + key, keyValues.get(key));
                            }
                        }
                    }
                } else {
                    Bundle b = cp.call(resolver.getAttributionSource(),
                        sProviderHolder.mUri.getAuthority(), CALL_METHOD_LIST_CONFIG, null, arg);
                            sProviderHolder.mUri.getAuthority(),
                            CALL_METHOD_LIST_CONFIG, null, arg);
                    if (b != null) {
                        Map<String, String> flagsToValues =
                                (HashMap) b.getSerializable(Settings.NameValueTable.VALUE,
                                                java.util.HashMap.class);
                        allFlags.putAll(flagsToValues);
                    }
                }
            } catch (RemoteException e) {
                Log.w(TAG, "Can't query configuration table for " + CONTENT_URI, e);
            }
+11 −0
Original line number Diff line number Diff line
@@ -52,3 +52,14 @@ flag {
    description: "Enable the new ContactsContract Default Account APIs."
    bug: "359957527"
}

flag {
    name: "reduce_binder_transaction_size_for_get_all_properties"
    namespace: "core_experiments_team_internal"
    description: "Reduce Binder transaction size in getAllProperties calls"
    bug: "362652574"
    is_fixed_read_only: true
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}
+27 −0
Original line number Diff line number Diff line
@@ -545,6 +545,10 @@ public class SettingsProvider extends ContentProvider {
                reportDeviceConfigAccess(prefix);
                return result;
            }
            case Settings.CALL_METHOD_LIST_NAMESPACES_CONFIG -> {
                Bundle result = packageNamespacesForCallResult(getAllConfigFlagNamespaces());
                return result;
            }
            case Settings.CALL_METHOD_REGISTER_MONITOR_CALLBACK_CONFIG -> {
                RemoteCallback callback = args.getParcelable(
                        Settings.CALL_METHOD_MONITOR_CALLBACK_KEY);
@@ -1336,6 +1340,23 @@ public class SettingsProvider extends ContentProvider {
        return false;
    }

    @NonNull
    private HashSet<String> getAllConfigFlagNamespaces() {
        Set<String> flagNames = getAllConfigFlags(null).keySet();
        HashSet<String> namespaces = new HashSet();
        for (String name : flagNames) {
            int slashIndex = name.indexOf("/");
            boolean validSlashIndex = slashIndex != -1
                        && slashIndex != 0
                        && slashIndex != name.length();
            if (validSlashIndex) {
                String namespace = name.substring(0, slashIndex);
                namespaces.add(namespace);
            }
        }
        return namespaces;
    }

    @NonNull
    private HashMap<String, String> getAllConfigFlags(@Nullable String prefix) {
        if (DEBUG) {
@@ -2561,6 +2582,12 @@ public class SettingsProvider extends ContentProvider {
        return result;
    }

    private Bundle packageNamespacesForCallResult(@NonNull HashSet<String> namespaces) {
        Bundle result = new Bundle();
        result.putSerializable(Settings.NameValueTable.VALUE, namespaces);
        return result;
    }

    private void setMonitorCallback(RemoteCallback callback) {
        if (callback == null) {
            return;