summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Mark Punzalan <markpun@google.com> 2025-02-10 15:18:15 -0800
committer Mark Punzalan <markpun@google.com> 2025-02-10 15:18:15 -0800
commit0dd2f0b325904192cc3254135ce068cd76683bf9 (patch)
tree5043871efe31cf036b60a5efd1c2c0bcd5d49503
parent17e32cd63514278bef6550567ece2f33ec0bc98b (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.aconfig13
-rw-r--r--core/java/com/android/internal/pm/pkg/component/AconfigFlags.java77
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);
}