diff options
| author | 2025-02-10 15:18:15 -0800 | |
|---|---|---|
| committer | 2025-02-10 15:18:15 -0800 | |
| commit | 0dd2f0b325904192cc3254135ce068cd76683bf9 (patch) | |
| tree | 5043871efe31cf036b60a5efd1c2c0bcd5d49503 | |
| parent | 17e32cd63514278bef6550567ece2f33ec0bc98b (diff) | |
Use new flag storage in AconfigFlags
Also reduced logging level of one of the statements from ERROR to WARNING
Bug: 352348353
Bug: 383143057
Flag: android.content.res.use_new_aconfig_storage
Test: build + boot on Pixel 6 Pro
Change-Id: I33949c04a5fa3544dbc48ce5f80e31204f705477
| -rw-r--r-- | core/java/android/content/res/flags.aconfig | 13 | ||||
| -rw-r--r-- | core/java/com/android/internal/pm/pkg/component/AconfigFlags.java | 77 |
2 files changed, 74 insertions, 16 deletions
diff --git a/core/java/android/content/res/flags.aconfig b/core/java/android/content/res/flags.aconfig index e24f1a8155ef..2c64cc3c02da 100644 --- a/core/java/android/content/res/flags.aconfig +++ b/core/java/android/content/res/flags.aconfig @@ -129,4 +129,15 @@ flag { namespace: "resource_manager" description: "flag always meant to be false, for testing resource flagging within cts tests" bug: "377974898" -}
\ No newline at end of file +} + +flag { + name: "use_new_aconfig_storage" + is_exported: true + namespace: "resource_manager" + description: "Retrieve flag values from new Aconfig flag storage in AconfigFlags.java" + bug: "352348353" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/core/java/com/android/internal/pm/pkg/component/AconfigFlags.java b/core/java/com/android/internal/pm/pkg/component/AconfigFlags.java index 445dac7411da..21d000dc5224 100644 --- a/core/java/com/android/internal/pm/pkg/component/AconfigFlags.java +++ b/core/java/com/android/internal/pm/pkg/component/AconfigFlags.java @@ -16,6 +16,7 @@ package com.android.internal.pm.pkg.component; +import static android.provider.flags.Flags.newStoragePublicApi; import static com.android.internal.pm.pkg.parsing.ParsingUtils.ANDROID_RES_NAMESPACE; import android.aconfig.DeviceProtos; @@ -27,6 +28,7 @@ import android.annotation.Nullable; import android.content.res.Flags; import android.os.Environment; import android.os.Process; +import android.os.flagging.AconfigPackage; import android.util.ArrayMap; import android.util.Slog; import android.util.Xml; @@ -43,6 +45,7 @@ import java.io.FileInputStream; import java.io.IOException; import java.util.Arrays; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * A class that manages a cache of all device feature flags and their default + override values. @@ -58,7 +61,8 @@ public class AconfigFlags { private static final String OVERRIDE_PREFIX = "device_config_overrides/"; private static final String STAGED_PREFIX = "staged/"; - private final ArrayMap<String, Boolean> mFlagValues = new ArrayMap<>(); + private final Map<String, Boolean> mFlagValues = new ArrayMap<>(); + private final Map<String, AconfigPackage> mAconfigPackages = new ConcurrentHashMap<>(); public AconfigFlags() { if (!Flags.manifestFlagging()) { @@ -67,23 +71,33 @@ public class AconfigFlags { } return; } - final var defaultFlagProtoFiles = - (Process.myUid() == Process.SYSTEM_UID) ? DeviceProtos.parsedFlagsProtoPaths() - : Arrays.asList(DeviceProtos.PATHS); - for (String fileName : defaultFlagProtoFiles) { - try (var inputStream = new FileInputStream(fileName)) { - loadAconfigDefaultValues(inputStream.readAllBytes()); - } catch (IOException e) { - Slog.e(LOG_TAG, "Failed to read Aconfig values from " + fileName, e); + + if (useNewStorage()) { + Slog.i(LOG_TAG, "Using new flag storage"); + } else { + Slog.i(LOG_TAG, "Using OLD proto flag storage"); + final var defaultFlagProtoFiles = + (Process.myUid() == Process.SYSTEM_UID) ? DeviceProtos.parsedFlagsProtoPaths() + : Arrays.asList(DeviceProtos.PATHS); + for (String fileName : defaultFlagProtoFiles) { + try (var inputStream = new FileInputStream(fileName)) { + loadAconfigDefaultValues(inputStream.readAllBytes()); + } catch (IOException e) { + Slog.w(LOG_TAG, "Failed to read Aconfig values from " + fileName, e); + } + } + if (Process.myUid() == Process.SYSTEM_UID) { + // Server overrides are only accessible to the system, no need to even try loading + // them in user processes. + loadServerOverrides(); } - } - if (Process.myUid() == Process.SYSTEM_UID) { - // Server overrides are only accessible to the system, no need to even try loading them - // in user processes. - loadServerOverrides(); } } + private static boolean useNewStorage() { + return newStoragePublicApi() && Flags.useNewAconfigStorage(); + } + private void loadServerOverrides() { // Reading the proto files is enough for READ_ONLY flags but if it's a READ_WRITE flag // (which you can check with `flag.getPermission() == flag_permission.READ_WRITE`) then we @@ -200,7 +214,40 @@ public class AconfigFlags { */ @Nullable public Boolean getFlagValue(@NonNull String flagPackageAndName) { - Boolean value = mFlagValues.get(flagPackageAndName); + if (useNewStorage()) { + return getFlagValueFromNewStorage(flagPackageAndName); + } else { + Boolean value = mFlagValues.get(flagPackageAndName); + if (DEBUG) { + Slog.v(LOG_TAG, "Aconfig flag value for " + flagPackageAndName + " = " + value); + } + return value; + } + } + + private Boolean getFlagValueFromNewStorage(String flagPackageAndName) { + int index = flagPackageAndName.lastIndexOf('.'); + if (index < 0) { + Slog.e(LOG_TAG, "Unable to parse package name from " + flagPackageAndName); + return null; + } + String flagPackage = flagPackageAndName.substring(0, index); + String flagName = flagPackageAndName.substring(index + 1); + Boolean value = null; + AconfigPackage aconfigPackage = mAconfigPackages.computeIfAbsent(flagPackage, p -> { + try { + return AconfigPackage.load(p); + } catch (Exception e) { + Slog.e(LOG_TAG, "Failed to load aconfig package " + p, e); + return null; + } + }); + if (aconfigPackage != null) { + // Default value is false for when the flag is not found. + // Note: Unlike with the old storage, with AconfigPackage, we don't have a way to + // know if the flag is not found or if it's found but the value is false. + value = aconfigPackage.getBooleanFlagValue(flagName, false); + } if (DEBUG) { Slog.v(LOG_TAG, "Aconfig flag value for " + flagPackageAndName + " = " + value); } |