update java local flag read code
This change updates the generated java code for java local flag read.
If the local read happens with in non-updatable framework, then it will
use PlatformAconfigPackageInternal to read the flag value. Otherwise it
will use AconfigPackageInternal to read the flag value.
Test: atest -c
Change-Id: I0f4e233e1e265530cb7cbcca0d1289b6a0211179
diff --git a/tools/aconfig/aconfig/src/codegen/java.rs b/tools/aconfig/aconfig/src/codegen/java.rs
index 2cb98ed..5c56ca6 100644
--- a/tools/aconfig/aconfig/src/codegen/java.rs
+++ b/tools/aconfig/aconfig/src/codegen/java.rs
@@ -32,6 +32,7 @@
codegen_mode: CodegenMode,
flag_ids: HashMap<String, u16>,
allow_instrumentation: bool,
+ package_fingerprint: u64,
) -> Result<Vec<OutputFile>>
where
I: Iterator<Item = ProtoParsedFlag>,
@@ -46,6 +47,7 @@
let runtime_lookup_required =
flag_elements.iter().any(|elem| elem.is_read_write) || library_exported;
let container = (flag_elements.first().expect("zero template flags").container).to_string();
+ let is_platform_container = matches!(container.as_str(), "system" | "product" | "vendor");
let context = Context {
flag_elements,
namespace_flags,
@@ -56,6 +58,8 @@
library_exported,
allow_instrumentation,
container,
+ is_platform_container,
+ package_fingerprint: format!("0x{:X}L", package_fingerprint),
};
let mut template = TinyTemplate::new();
template.add_template("Flags.java", include_str!("../../templates/Flags.java.template"))?;
@@ -123,6 +127,8 @@
pub library_exported: bool,
pub allow_instrumentation: bool,
pub container: String,
+ pub is_platform_container: bool,
+ pub package_fingerprint: String,
}
#[derive(Serialize, Debug)]
@@ -502,6 +508,7 @@
mode,
flag_ids,
true,
+ 5801144784618221668,
)
.unwrap();
let expect_flags_content = EXPECTED_FLAG_COMMON_CONTENT.to_string()
@@ -513,10 +520,13 @@
package com.android.aconfig.test;
// TODO(b/303773055): Remove the annotation after access issue is resolved.
import android.compat.annotation.UnsupportedAppUsage;
- import android.aconfig.storage.StorageInternalReader;
-
+ import android.os.Build;
+ import android.os.flagging.PlatformAconfigPackageInternal;
+ import android.os.flagging.AconfigStorageReadException;
+ import android.util.Log;
/** @hide */
public final class FeatureFlagsImpl implements FeatureFlags {
+ private static final String TAG = "com.android.aconfig.test.FeatureFlagsImpl";
private static volatile boolean isCached = false;
private static boolean disabledRw = false;
private static boolean disabledRwExported = false;
@@ -524,16 +534,27 @@
private static boolean enabledRw = true;
private void init() {
try {
- StorageInternalReader reader = new StorageInternalReader("system", "com.android.aconfig.test");
- disabledRw = reader.getBooleanFlagValue(1);
- disabledRwExported = reader.getBooleanFlagValue(2);
- enabledRw = reader.getBooleanFlagValue(8);
- disabledRwInOtherNamespace = reader.getBooleanFlagValue(3);
+ PlatformAconfigPackageInternal reader = PlatformAconfigPackageInternal.load("system", "com.android.aconfig.test", 0x5081CE7221C77064L);
+ AconfigStorageReadException error = reader.getException();
+ if (error == null) {
+ disabledRw = reader.getBooleanFlagValue(1);
+ disabledRwExported = reader.getBooleanFlagValue(2);
+ enabledRw = reader.getBooleanFlagValue(8);
+ disabledRwInOtherNamespace = reader.getBooleanFlagValue(3);
+ } else if (Build.VERSION.SDK_INT > 35 && error.getErrorCode() == 5 /* fingerprint doesn't match*/) {
+ disabledRw = reader.getBooleanFlagValue("disabled_rw", false);
+ disabledRwExported = reader.getBooleanFlagValue("disabled_rw_exported", false);
+ enabledRw = reader.getBooleanFlagValue("enabled_rw", true);
+ disabledRwInOtherNamespace = reader.getBooleanFlagValue("disabled_rw_in_other_namespace", false);
+ } else {
+ Log.e(TAG, error.getMessage());
+ }
} catch (Exception e) {
- // pass
+ Log.e(TAG, e.getMessage());
} catch (NoClassDefFoundError e) {
// for mainline module running on older devices.
// This should be replaces to version check, after the version bump.
+ Log.e(TAG, e.getMessage());
}
isCached = true;
}
@@ -653,6 +674,7 @@
mode,
flag_ids,
true,
+ 5801144784618221668,
)
.unwrap();
@@ -851,6 +873,7 @@
mode,
flag_ids,
true,
+ 5801144784618221668,
)
.unwrap();
@@ -972,6 +995,7 @@
mode,
flag_ids,
true,
+ 5801144784618221668,
)
.unwrap();
let expect_featureflags_content = r#"
diff --git a/tools/aconfig/aconfig/src/commands.rs b/tools/aconfig/aconfig/src/commands.rs
index 81119f3..c1989a2 100644
--- a/tools/aconfig/aconfig/src/commands.rs
+++ b/tools/aconfig/aconfig/src/commands.rs
@@ -225,6 +225,9 @@
bail!("no parsed flags, or the parsed flags use different packages");
};
let package = package.to_string();
+ let mut flag_names =
+ modified_parsed_flags.iter().map(|pf| pf.name().to_string()).collect::<Vec<_>>();
+ let package_fingerprint = compute_flags_fingerprint(&mut flag_names);
let flag_ids = assign_flag_ids(&package, modified_parsed_flags.iter())?;
generate_java_code(
&package,
@@ -232,6 +235,7 @@
codegen_mode,
flag_ids,
allow_instrumentation,
+ package_fingerprint,
)
}
diff --git a/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template b/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
index 98add32..c94bf33 100644
--- a/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
+++ b/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
@@ -5,11 +5,19 @@
// TODO(b/303773055): Remove the annotation after access issue is resolved.
import android.compat.annotation.UnsupportedAppUsage;
{{ -if runtime_lookup_required }}
-import android.aconfig.storage.StorageInternalReader;
+import android.os.Build;
+{{ if is_platform_container }}
+import android.os.flagging.PlatformAconfigPackageInternal;
+{{ -else }}
+import android.os.flagging.AconfigPackageInternal;
+{{ -endif }}
+import android.os.flagging.AconfigStorageReadException;
+import android.util.Log;
{{ -endif }}
/** @hide */
public final class FeatureFlagsImpl implements FeatureFlags \{
{{ -if runtime_lookup_required }}
+ private static final String TAG = "{package_name}.FeatureFlagsImpl";
private static volatile boolean isCached = false;
{{ for flag in flag_elements }}
{{ -if flag.is_read_write }}
@@ -19,19 +27,37 @@
private void init() \{
try \{
- StorageInternalReader reader = new StorageInternalReader("{container}", "{package_name}");
+{{ if is_platform_container }}
+ PlatformAconfigPackageInternal reader = PlatformAconfigPackageInternal.load("{container}", "{package_name}", {package_fingerprint});
+{{ -else }}
+ AconfigPackageInternal reader = AconfigPackageInternal.load("{container}", "{package_name}", {package_fingerprint});
+{{ -endif }}
+ AconfigStorageReadException error = reader.getException();
+ if (error == null) \{
{{ for namespace_with_flags in namespace_flags }}
{{ -for flag in namespace_with_flags.flags }}
- {{ if flag.is_read_write }}
+ {{ -if flag.is_read_write }}
{flag.method_name} = reader.getBooleanFlagValue({flag.flag_offset});
{{ endif }}
{{ -endfor }}
{{ -endfor }}
+ } else if (Build.VERSION.SDK_INT > 35 && error.getErrorCode() == 5 /* fingerprint doesn't match*/) \{
+ {{ for namespace_with_flags in namespace_flags }}
+ {{ -for flag in namespace_with_flags.flags }}
+ {{ -if flag.is_read_write }}
+ {flag.method_name} = reader.getBooleanFlagValue("{flag.flag_name}", {flag.default_value});
+ {{ -endif }}
+ {{ -endfor }}
+ {{ -endfor }}
+ } else \{
+ Log.e(TAG, error.getMessage());
+ }
} catch (Exception e) \{
- // pass
+ Log.e(TAG, e.getMessage());
} catch (NoClassDefFoundError e) \{
// for mainline module running on older devices.
// This should be replaces to version check, after the version bump.
+ Log.e(TAG, e.getMessage());
}
isCached = true;
}
diff --git a/tools/aconfig/aconfig_storage_read_api/Android.bp b/tools/aconfig/aconfig_storage_read_api/Android.bp
index 09daeea..6214e2c 100644
--- a/tools/aconfig/aconfig_storage_read_api/Android.bp
+++ b/tools/aconfig/aconfig_storage_read_api/Android.bp
@@ -167,27 +167,8 @@
],
sdk_version: "core_current",
host_supported: true,
- min_sdk_version: "29",
- apex_available: [
- "//apex_available:platform",
- "//apex_available:anyapex",
+ visibility: [
+ "//frameworks/base",
+ "//build/make/tools/aconfig/aconfig_storage_read_api/tests",
],
}
-
-java_library {
- name: "aconfig_storage_reader_java_none",
- srcs: [
- "srcs/android/aconfig/storage/StorageInternalReader.java",
- "srcs/android/os/flagging/PlatformAconfigPackageInternal.java",
- ],
- libs: [
- "unsupportedappusage-sdk-none",
- "fake_device_config",
- ],
- static_libs: [
- "aconfig_storage_file_java_none",
- ],
- sdk_version: "none",
- system_modules: "core-all-system-modules",
- host_supported: true,
-}
diff --git a/tools/aconfig/aconfig_storage_read_api/srcs/android/os/flagging/PlatformAconfigPackageInternal.java b/tools/aconfig/aconfig_storage_read_api/srcs/android/os/flagging/PlatformAconfigPackageInternal.java
index 83310be..e6b6db4 100644
--- a/tools/aconfig/aconfig_storage_read_api/srcs/android/os/flagging/PlatformAconfigPackageInternal.java
+++ b/tools/aconfig/aconfig_storage_read_api/srcs/android/os/flagging/PlatformAconfigPackageInternal.java
@@ -45,14 +45,14 @@
private final FlagValueList mFlagValueList;
private final int mPackageId;
private final int mPackageBooleanStartOffset;
- private final AconfigStorageException mException;
+ private final AconfigStorageReadException mException;
private PlatformAconfigPackageInternal(
FlagValueList flagValueList,
FlagTable flagTable,
int packageBooleanStartOffset,
int packageId,
- AconfigStorageException exception) {
+ AconfigStorageReadException exception) {
this.mFlagValueList = flagValueList;
this.mFlagTable = flagTable;
this.mPackageBooleanStartOffset = packageBooleanStartOffset;
@@ -150,7 +150,7 @@
if (pNode == null) {
return createExceptionInstance(
- AconfigStorageException.ERROR_PACKAGE_NOT_FOUND,
+ AconfigStorageReadException.ERROR_PACKAGE_NOT_FOUND,
"package "
+ packageName
+ " in container "
@@ -165,7 +165,7 @@
fileProvider.getFlagTable(container),
pNode.getBooleanStartIndex(),
pNode.getPackageId(),
- new AconfigStorageException(
+ new AconfigStorageReadException(
AconfigStorageException.ERROR_FILE_FINGERPRINT_MISMATCH,
"The fingerprint provided for the Aconfig package "
+ packageName
@@ -244,7 +244,7 @@
* @hide
*/
@UnsupportedAppUsage
- public Exception getException() {
+ public AconfigStorageReadException getException() {
return mException;
}
@@ -259,6 +259,6 @@
private static PlatformAconfigPackageInternal createExceptionInstance(
int errorCode, String message) {
return new PlatformAconfigPackageInternal(
- null, null, 0, 0, new AconfigStorageException(errorCode, message));
+ null, null, 0, 0, new AconfigStorageReadException(errorCode, message));
}
}
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/Android.bp b/tools/aconfig/aconfig_storage_read_api/tests/Android.bp
index fb2fc77..702325d 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/Android.bp
+++ b/tools/aconfig/aconfig_storage_read_api/tests/Android.bp
@@ -57,7 +57,6 @@
static_libs: [
"aconfig_device_paths_java",
"aconfig_storage_file_java",
- "aconfig_storage_reader_java",
"androidx.test.rules",
"libaconfig_storage_read_api_java",
"junit",
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/functional/srcs/PlatformAconfigPackageInternalTest.java b/tools/aconfig/aconfig_storage_read_api/tests/functional/srcs/PlatformAconfigPackageInternalTest.java
index 15cfc3b..c4a5560 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/functional/srcs/PlatformAconfigPackageInternalTest.java
+++ b/tools/aconfig/aconfig_storage_read_api/tests/functional/srcs/PlatformAconfigPackageInternalTest.java
@@ -122,13 +122,13 @@
PlatformAconfigPackageInternal.load("fake_container", "fake_package", 0);
assertEquals(
AconfigStorageException.ERROR_CANNOT_READ_STORAGE_FILE,
- ((AconfigStorageException) aPackage.getException()).getErrorCode());
+ aPackage.getException().getErrorCode());
// package not found
aPackage = PlatformAconfigPackageInternal.load("system", "fake_container", 0);
assertEquals(
AconfigStorageException.ERROR_PACKAGE_NOT_FOUND,
- ((AconfigStorageException) aPackage.getException()).getErrorCode());
+ aPackage.getException().getErrorCode());
// fingerprint doesn't match
List<parsed_flag> flags = DeviceProtos.loadAndParseFlagProtos();
@@ -148,7 +148,7 @@
aPackage = PlatformAconfigPackageInternal.load(container, packageName, fingerprint + 1);
assertEquals(
// AconfigStorageException.ERROR_FILE_FINGERPRINT_MISMATCH,
- 5, ((AconfigStorageException) aPackage.getException()).getErrorCode());
+ 5, aPackage.getException().getErrorCode());
assertEquals(aPackage.getBooleanFlagValue(flag.name, !value), value);
}
}
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/unit/srcs/PlatformAconfigPackageInternalTest.java b/tools/aconfig/aconfig_storage_read_api/tests/unit/srcs/PlatformAconfigPackageInternalTest.java
index 392f644..ce3786a 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/unit/srcs/PlatformAconfigPackageInternalTest.java
+++ b/tools/aconfig/aconfig_storage_read_api/tests/unit/srcs/PlatformAconfigPackageInternalTest.java
@@ -61,31 +61,31 @@
assertEquals(
AconfigStorageException.ERROR_PACKAGE_NOT_FOUND,
- ((AconfigStorageException) p.getException()).getErrorCode());
+ p.getException().getErrorCode());
// cannot find container
p = PlatformAconfigPackageInternal.load(null, "com.android.aconfig.storage.test_1", pr);
assertEquals(
AconfigStorageException.ERROR_CANNOT_READ_STORAGE_FILE,
- ((AconfigStorageException) p.getException()).getErrorCode());
+ p.getException().getErrorCode());
p = PlatformAconfigPackageInternal.load("test", "com.android.aconfig.storage.test_1", pr);
assertEquals(
AconfigStorageException.ERROR_CANNOT_READ_STORAGE_FILE,
- ((AconfigStorageException) p.getException()).getErrorCode());
+ p.getException().getErrorCode());
// new storage doesn't exist
pr = new StorageFileProvider("fake/path/", "fake/path/");
p = PlatformAconfigPackageInternal.load("mockup", "com.android.aconfig.storage.test_1", pr);
assertEquals(
AconfigStorageException.ERROR_CANNOT_READ_STORAGE_FILE,
- ((AconfigStorageException) p.getException()).getErrorCode());
+ p.getException().getErrorCode());
// file read issue
pr = new StorageFileProvider(TESTDATA_PATH, "fake/path/");
p = PlatformAconfigPackageInternal.load("mockup", "com.android.aconfig.storage.test_1", pr);
assertEquals(
AconfigStorageException.ERROR_CANNOT_READ_STORAGE_FILE,
- ((AconfigStorageException) p.getException()).getErrorCode());
+ p.getException().getErrorCode());
}
@Test
@@ -117,7 +117,7 @@
assertEquals(
AconfigStorageException.ERROR_PACKAGE_NOT_FOUND,
- ((AconfigStorageException) p.getException()).getErrorCode());
+ p.getException().getErrorCode());
// cannot find container
p =
@@ -125,20 +125,20 @@
null, "com.android.aconfig.storage.test_1", fingerprint, pr);
assertEquals(
AconfigStorageException.ERROR_CANNOT_READ_STORAGE_FILE,
- ((AconfigStorageException) p.getException()).getErrorCode());
+ p.getException().getErrorCode());
p =
PlatformAconfigPackageInternal.load(
"test", "com.android.aconfig.storage.test_1", fingerprint, pr);
assertEquals(
AconfigStorageException.ERROR_CANNOT_READ_STORAGE_FILE,
- ((AconfigStorageException) p.getException()).getErrorCode());
+ p.getException().getErrorCode());
// fingerprint doesn't match
p =
PlatformAconfigPackageInternal.load(
"mockup", "com.android.aconfig.storage.test_1", fingerprint + 1, pr);
assertEquals(
// AconfigStorageException.ERROR_FILE_FINGERPRINT_MISMATCH,
- 5, ((AconfigStorageException) p.getException()).getErrorCode());
+ 5, p.getException().getErrorCode());
// new storage doesn't exist
pr = new StorageFileProvider("fake/path/", "fake/path/");
@@ -147,7 +147,7 @@
"mockup", "com.android.aconfig.storage.test_1", fingerprint, pr);
assertEquals(
AconfigStorageException.ERROR_CANNOT_READ_STORAGE_FILE,
- ((AconfigStorageException) p.getException()).getErrorCode());
+ p.getException().getErrorCode());
// file read issue
pr = new StorageFileProvider(TESTDATA_PATH, "fake/path/");
@@ -156,7 +156,7 @@
"mockup", "com.android.aconfig.storage.test_1", fingerprint, pr);
assertEquals(
AconfigStorageException.ERROR_CANNOT_READ_STORAGE_FILE,
- ((AconfigStorageException) p.getException()).getErrorCode());
+ p.getException().getErrorCode());
}
@Test
diff --git a/tools/aconfig/fake_device_config/src/android/os/Build.java b/tools/aconfig/fake_device_config/src/android/os/Build.java
new file mode 100644
index 0000000..8ec72fb
--- /dev/null
+++ b/tools/aconfig/fake_device_config/src/android/os/Build.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+public class Build {
+ public static class VERSION {
+ public static final int SDK_INT = 0;
+ }
+}
diff --git a/tools/aconfig/fake_device_config/src/android/provider/AconfigPackage.java b/tools/aconfig/fake_device_config/src/android/provider/AconfigPackage.java
deleted file mode 100644
index 2f01b8c..0000000
--- a/tools/aconfig/fake_device_config/src/android/provider/AconfigPackage.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.provider;
-
-/*
- * This class allows generated aconfig code to compile independently of the framework.
- */
-public class AconfigPackage {
-
- /** Flag value is true */
- public static final int FLAG_BOOLEAN_VALUE_TRUE = 1;
-
- /** Flag value is false */
- public static final int FLAG_BOOLEAN_VALUE_FALSE = 0;
-
- /** Flag value doesn't exist */
- public static final int FLAG_BOOLEAN_VALUE_NOT_EXIST = 2;
-
- public static int getBooleanFlagValue(String packageName, String flagName) {
- return 0;
- }
-
- public AconfigPackage(String packageName) {}
-
- public int getBooleanFlagValue(String flagName) {
- return 0;
- }
-}
\ No newline at end of file