Merge "add hide and unsupportedadppusage annotation to read library" into main
This commit is contained in:
@@ -1,18 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2023 The Android Open Source Project
|
* Copyright (C) 2023 The Android Open Source Project
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
@@ -508,12 +508,15 @@ mod tests {
|
|||||||
private static FeatureFlags FEATURE_FLAGS = new FeatureFlagsImpl();
|
private static FeatureFlags FEATURE_FLAGS = new FeatureFlagsImpl();
|
||||||
}"#;
|
}"#;
|
||||||
|
|
||||||
let expect_featureflagsimpl_content = r#"
|
let expected_featureflagsmpl_content_0 = r#"
|
||||||
package com.android.aconfig.test;
|
package com.android.aconfig.test;
|
||||||
// TODO(b/303773055): Remove the annotation after access issue is resolved.
|
// TODO(b/303773055): Remove the annotation after access issue is resolved.
|
||||||
import android.compat.annotation.UnsupportedAppUsage;
|
import android.compat.annotation.UnsupportedAppUsage;
|
||||||
import android.provider.DeviceConfig;
|
import android.provider.DeviceConfig;
|
||||||
import android.provider.DeviceConfig.Properties;
|
import android.provider.DeviceConfig.Properties;
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let expected_featureflagsmpl_content_1 = r#"
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public final class FeatureFlagsImpl implements FeatureFlags {
|
public final class FeatureFlagsImpl implements FeatureFlags {
|
||||||
private static boolean aconfig_test_is_cached = false;
|
private static boolean aconfig_test_is_cached = false;
|
||||||
@@ -522,48 +525,8 @@ mod tests {
|
|||||||
private static boolean disabledRwExported = false;
|
private static boolean disabledRwExported = false;
|
||||||
private static boolean disabledRwInOtherNamespace = false;
|
private static boolean disabledRwInOtherNamespace = false;
|
||||||
private static boolean enabledRw = true;
|
private static boolean enabledRw = true;
|
||||||
|
"#;
|
||||||
|
let expected_featureflagsmpl_content_2 = r#"
|
||||||
private void load_overrides_aconfig_test() {
|
|
||||||
try {
|
|
||||||
Properties properties = DeviceConfig.getProperties("aconfig_test");
|
|
||||||
disabledRw =
|
|
||||||
properties.getBoolean(Flags.FLAG_DISABLED_RW, false);
|
|
||||||
disabledRwExported =
|
|
||||||
properties.getBoolean(Flags.FLAG_DISABLED_RW_EXPORTED, false);
|
|
||||||
enabledRw =
|
|
||||||
properties.getBoolean(Flags.FLAG_ENABLED_RW, true);
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
throw new RuntimeException(
|
|
||||||
"Cannot read value from namespace aconfig_test "
|
|
||||||
+ "from DeviceConfig. It could be that the code using flag "
|
|
||||||
+ "executed before SettingsProvider initialization. Please use "
|
|
||||||
+ "fixed read-only flag by adding is_fixed_read_only: true in "
|
|
||||||
+ "flag declaration.",
|
|
||||||
e
|
|
||||||
);
|
|
||||||
}
|
|
||||||
aconfig_test_is_cached = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void load_overrides_other_namespace() {
|
|
||||||
try {
|
|
||||||
Properties properties = DeviceConfig.getProperties("other_namespace");
|
|
||||||
disabledRwInOtherNamespace =
|
|
||||||
properties.getBoolean(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE, false);
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
throw new RuntimeException(
|
|
||||||
"Cannot read value from namespace other_namespace "
|
|
||||||
+ "from DeviceConfig. It could be that the code using flag "
|
|
||||||
+ "executed before SettingsProvider initialization. Please use "
|
|
||||||
+ "fixed read-only flag by adding is_fixed_read_only: true in "
|
|
||||||
+ "flag declaration.",
|
|
||||||
e
|
|
||||||
);
|
|
||||||
}
|
|
||||||
other_namespace_is_cached = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@com.android.aconfig.annotations.AconfigFlagAccessor
|
@com.android.aconfig.annotations.AconfigFlagAccessor
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
@@ -632,9 +595,229 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
|
let expect_featureflagsimpl_content_old = expected_featureflagsmpl_content_0.to_owned()
|
||||||
|
+ expected_featureflagsmpl_content_1
|
||||||
|
+ r#"
|
||||||
|
private void load_overrides_aconfig_test() {
|
||||||
|
try {
|
||||||
|
Properties properties = DeviceConfig.getProperties("aconfig_test");
|
||||||
|
disabledRw =
|
||||||
|
properties.getBoolean(Flags.FLAG_DISABLED_RW, false);
|
||||||
|
disabledRwExported =
|
||||||
|
properties.getBoolean(Flags.FLAG_DISABLED_RW_EXPORTED, false);
|
||||||
|
enabledRw =
|
||||||
|
properties.getBoolean(Flags.FLAG_ENABLED_RW, true);
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
throw new RuntimeException(
|
||||||
|
"Cannot read value from namespace aconfig_test "
|
||||||
|
+ "from DeviceConfig. It could be that the code using flag "
|
||||||
|
+ "executed before SettingsProvider initialization. Please use "
|
||||||
|
+ "fixed read-only flag by adding is_fixed_read_only: true in "
|
||||||
|
+ "flag declaration.",
|
||||||
|
e
|
||||||
|
);
|
||||||
|
}
|
||||||
|
aconfig_test_is_cached = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void load_overrides_other_namespace() {
|
||||||
|
try {
|
||||||
|
Properties properties = DeviceConfig.getProperties("other_namespace");
|
||||||
|
disabledRwInOtherNamespace =
|
||||||
|
properties.getBoolean(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE, false);
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
throw new RuntimeException(
|
||||||
|
"Cannot read value from namespace other_namespace "
|
||||||
|
+ "from DeviceConfig. It could be that the code using flag "
|
||||||
|
+ "executed before SettingsProvider initialization. Please use "
|
||||||
|
+ "fixed read-only flag by adding is_fixed_read_only: true in "
|
||||||
|
+ "flag declaration.",
|
||||||
|
e
|
||||||
|
);
|
||||||
|
}
|
||||||
|
other_namespace_is_cached = true;
|
||||||
|
}"#
|
||||||
|
+ expected_featureflagsmpl_content_2;
|
||||||
|
|
||||||
let mut file_set = HashMap::from([
|
let mut file_set = HashMap::from([
|
||||||
("com/android/aconfig/test/Flags.java", expect_flags_content.as_str()),
|
("com/android/aconfig/test/Flags.java", expect_flags_content.as_str()),
|
||||||
("com/android/aconfig/test/FeatureFlagsImpl.java", expect_featureflagsimpl_content),
|
(
|
||||||
|
"com/android/aconfig/test/FeatureFlagsImpl.java",
|
||||||
|
&expect_featureflagsimpl_content_old,
|
||||||
|
),
|
||||||
|
("com/android/aconfig/test/FeatureFlags.java", EXPECTED_FEATUREFLAGS_COMMON_CONTENT),
|
||||||
|
(
|
||||||
|
"com/android/aconfig/test/CustomFeatureFlags.java",
|
||||||
|
EXPECTED_CUSTOMFEATUREFLAGS_CONTENT,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"com/android/aconfig/test/FakeFeatureFlagsImpl.java",
|
||||||
|
EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT,
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
|
||||||
|
for file in generated_files {
|
||||||
|
let file_path = file.path.to_str().unwrap();
|
||||||
|
assert!(file_set.contains_key(file_path), "Cannot find {}", file_path);
|
||||||
|
assert_eq!(
|
||||||
|
None,
|
||||||
|
crate::test::first_significant_code_diff(
|
||||||
|
file_set.get(file_path).unwrap(),
|
||||||
|
&String::from_utf8(file.contents).unwrap()
|
||||||
|
),
|
||||||
|
"File {} content is not correct",
|
||||||
|
file_path
|
||||||
|
);
|
||||||
|
file_set.remove(file_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert!(file_set.is_empty());
|
||||||
|
|
||||||
|
let parsed_flags = crate::test::parse_test_flags();
|
||||||
|
let mode = CodegenMode::Production;
|
||||||
|
let modified_parsed_flags =
|
||||||
|
crate::commands::modify_parsed_flags_based_on_mode(parsed_flags, mode).unwrap();
|
||||||
|
let flag_ids =
|
||||||
|
assign_flag_ids(crate::test::TEST_PACKAGE, modified_parsed_flags.iter()).unwrap();
|
||||||
|
let generated_files = generate_java_code(
|
||||||
|
crate::test::TEST_PACKAGE,
|
||||||
|
modified_parsed_flags.into_iter(),
|
||||||
|
mode,
|
||||||
|
flag_ids,
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let expect_featureflagsimpl_content_new = expected_featureflagsmpl_content_0.to_owned()
|
||||||
|
+ r#"
|
||||||
|
import android.aconfig.storage.StorageInternalReader;
|
||||||
|
import android.util.Log;
|
||||||
|
import java.io.File;
|
||||||
|
"#
|
||||||
|
+ expected_featureflagsmpl_content_1
|
||||||
|
+ r#"
|
||||||
|
StorageInternalReader reader;
|
||||||
|
boolean readFromNewStorage;
|
||||||
|
|
||||||
|
private final static String TAG = "AconfigJavaCodegen";
|
||||||
|
|
||||||
|
public FeatureFlagsImpl() {
|
||||||
|
File file = new File("/metadata/aconfig_test_missions/mission_1");
|
||||||
|
if (file.exists()) {
|
||||||
|
readFromNewStorage = true;
|
||||||
|
try {
|
||||||
|
reader = new StorageInternalReader("system", "com.android.aconfig.test");
|
||||||
|
} catch (Exception e) {
|
||||||
|
reader = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void load_overrides_aconfig_test() {
|
||||||
|
try {
|
||||||
|
boolean val;
|
||||||
|
Properties properties = DeviceConfig.getProperties("aconfig_test");
|
||||||
|
disabledRw =
|
||||||
|
properties.getBoolean(Flags.FLAG_DISABLED_RW, false);
|
||||||
|
if (readFromNewStorage && reader != null) {
|
||||||
|
try {
|
||||||
|
val = reader.getBooleanFlagValue(1);
|
||||||
|
if (val == disabledRw) {
|
||||||
|
Log.i(TAG, "success: disabledRw value matches");
|
||||||
|
} else {
|
||||||
|
Log.i(TAG, String.format(
|
||||||
|
"error: disabledRw value mismatch, new storage value is %s, old storage value is %s",
|
||||||
|
val, disabledRw));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "error: failed to read flag value of disabledRw", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
disabledRwExported =
|
||||||
|
properties.getBoolean(Flags.FLAG_DISABLED_RW_EXPORTED, false);
|
||||||
|
if (readFromNewStorage && reader != null) {
|
||||||
|
try {
|
||||||
|
val = reader.getBooleanFlagValue(2);
|
||||||
|
if (val == disabledRwExported) {
|
||||||
|
Log.i(TAG, "success: disabledRwExported value matches");
|
||||||
|
} else {
|
||||||
|
Log.i(TAG, String.format(
|
||||||
|
"error: disabledRwExported value mismatch, new storage value is %s, old storage value is %s",
|
||||||
|
val, disabledRwExported));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "error: failed to read flag value of disabledRwExported", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enabledRw =
|
||||||
|
properties.getBoolean(Flags.FLAG_ENABLED_RW, true);
|
||||||
|
if (readFromNewStorage && reader != null) {
|
||||||
|
try {
|
||||||
|
val = reader.getBooleanFlagValue(8);
|
||||||
|
if (val == enabledRw) {
|
||||||
|
Log.i(TAG, "success: enabledRw value matches");
|
||||||
|
} else {
|
||||||
|
Log.i(TAG, String.format(
|
||||||
|
"error: enabledRw value mismatch, new storage value is %s, old storage value is %s",
|
||||||
|
val, enabledRw));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "error: failed to read flag value of enabledRw", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
throw new RuntimeException(
|
||||||
|
"Cannot read value from namespace aconfig_test "
|
||||||
|
+ "from DeviceConfig. It could be that the code using flag "
|
||||||
|
+ "executed before SettingsProvider initialization. Please use "
|
||||||
|
+ "fixed read-only flag by adding is_fixed_read_only: true in "
|
||||||
|
+ "flag declaration.",
|
||||||
|
e
|
||||||
|
);
|
||||||
|
}
|
||||||
|
aconfig_test_is_cached = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void load_overrides_other_namespace() {
|
||||||
|
try {
|
||||||
|
boolean val;
|
||||||
|
Properties properties = DeviceConfig.getProperties("other_namespace");
|
||||||
|
disabledRwInOtherNamespace =
|
||||||
|
properties.getBoolean(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE, false);
|
||||||
|
if (readFromNewStorage && reader != null) {
|
||||||
|
try {
|
||||||
|
val = reader.getBooleanFlagValue(3);
|
||||||
|
if (val == disabledRwInOtherNamespace) {
|
||||||
|
Log.i(TAG, "success: disabledRwInOtherNamespace value matches");
|
||||||
|
} else {
|
||||||
|
Log.i(TAG, String.format(
|
||||||
|
"error: disabledRwInOtherNamespace value mismatch, new storage value is %s, old storage value is %s",
|
||||||
|
val, disabledRwInOtherNamespace));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "error: failed to read flag value of disabledRwInOtherNamespace", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
throw new RuntimeException(
|
||||||
|
"Cannot read value from namespace other_namespace "
|
||||||
|
+ "from DeviceConfig. It could be that the code using flag "
|
||||||
|
+ "executed before SettingsProvider initialization. Please use "
|
||||||
|
+ "fixed read-only flag by adding is_fixed_read_only: true in "
|
||||||
|
+ "flag declaration.",
|
||||||
|
e
|
||||||
|
);
|
||||||
|
}
|
||||||
|
other_namespace_is_cached = true;
|
||||||
|
}"# + expected_featureflagsmpl_content_2;
|
||||||
|
|
||||||
|
let mut file_set = HashMap::from([
|
||||||
|
("com/android/aconfig/test/Flags.java", expect_flags_content.as_str()),
|
||||||
|
(
|
||||||
|
"com/android/aconfig/test/FeatureFlagsImpl.java",
|
||||||
|
&expect_featureflagsimpl_content_new,
|
||||||
|
),
|
||||||
("com/android/aconfig/test/FeatureFlags.java", EXPECTED_FEATUREFLAGS_COMMON_CONTENT),
|
("com/android/aconfig/test/FeatureFlags.java", EXPECTED_FEATUREFLAGS_COMMON_CONTENT),
|
||||||
(
|
(
|
||||||
"com/android/aconfig/test/CustomFeatureFlags.java",
|
"com/android/aconfig/test/CustomFeatureFlags.java",
|
||||||
|
@@ -45,7 +45,7 @@ public final class FeatureFlagsImpl implements FeatureFlags \{
|
|||||||
readFromNewStorage = true;
|
readFromNewStorage = true;
|
||||||
try \{
|
try \{
|
||||||
reader = new StorageInternalReader("{container}", "{package_name}");
|
reader = new StorageInternalReader("{container}", "{package_name}");
|
||||||
} catch(Exception e) \{
|
} catch (Exception e) \{
|
||||||
reader = null;
|
reader = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -78,7 +78,7 @@ public final class FeatureFlagsImpl implements FeatureFlags \{
|
|||||||
val, {flag.method_name}));
|
val, {flag.method_name}));
|
||||||
}
|
}
|
||||||
} catch (Exception e) \{
|
} catch (Exception e) \{
|
||||||
Log.e(TAG,"error: failed to read flag value of {flag.method_name}", e);
|
Log.e(TAG, "error: failed to read flag value of {flag.method_name}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{{ -endif }}
|
{{ -endif }}
|
||||||
|
@@ -32,7 +32,6 @@ android_test {
|
|||||||
"androidx.test.runner",
|
"androidx.test.runner",
|
||||||
"junit",
|
"junit",
|
||||||
],
|
],
|
||||||
sdk_version: "test_current",
|
|
||||||
test_config: "AndroidStorageJaveTest.xml",
|
test_config: "AndroidStorageJaveTest.xml",
|
||||||
data: [
|
data: [
|
||||||
"package.map",
|
"package.map",
|
||||||
|
@@ -171,6 +171,9 @@ java_library {
|
|||||||
srcs: [
|
srcs: [
|
||||||
"srcs/android/aconfig/storage/StorageInternalReader.java",
|
"srcs/android/aconfig/storage/StorageInternalReader.java",
|
||||||
],
|
],
|
||||||
|
libs: [
|
||||||
|
"unsupportedappusage",
|
||||||
|
],
|
||||||
static_libs: [
|
static_libs: [
|
||||||
"aconfig_storage_file_java",
|
"aconfig_storage_file_java",
|
||||||
],
|
],
|
||||||
|
@@ -16,10 +16,13 @@
|
|||||||
|
|
||||||
package android.aconfig.storage;
|
package android.aconfig.storage;
|
||||||
|
|
||||||
|
import android.compat.annotation.UnsupportedAppUsage;
|
||||||
|
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.nio.MappedByteBuffer;
|
import java.nio.MappedByteBuffer;
|
||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
public class StorageInternalReader {
|
public class StorageInternalReader {
|
||||||
|
|
||||||
private static final String MAP_PATH = "/metadata/aconfig/maps/";
|
private static final String MAP_PATH = "/metadata/aconfig/maps/";
|
||||||
@@ -30,16 +33,19 @@ public class StorageInternalReader {
|
|||||||
|
|
||||||
private int mPackageBooleanStartOffset;
|
private int mPackageBooleanStartOffset;
|
||||||
|
|
||||||
|
@UnsupportedAppUsage
|
||||||
public StorageInternalReader(String container, String packageName) {
|
public StorageInternalReader(String container, String packageName) {
|
||||||
this(packageName, MAP_PATH + container + ".package.map", BOOT_PATH + container + ".val");
|
this(packageName, MAP_PATH + container + ".package.map", BOOT_PATH + container + ".val");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UnsupportedAppUsage
|
||||||
public StorageInternalReader(String packageName, String packageMapFile, String flagValueFile) {
|
public StorageInternalReader(String packageName, String packageMapFile, String flagValueFile) {
|
||||||
mPackageTable = PackageTable.fromBytes(mapStorageFile(packageMapFile));
|
mPackageTable = PackageTable.fromBytes(mapStorageFile(packageMapFile));
|
||||||
mFlagValueList = FlagValueList.fromBytes(mapStorageFile(flagValueFile));
|
mFlagValueList = FlagValueList.fromBytes(mapStorageFile(flagValueFile));
|
||||||
mPackageBooleanStartOffset = getPackageBooleanStartOffset(packageName);
|
mPackageBooleanStartOffset = getPackageBooleanStartOffset(packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UnsupportedAppUsage
|
||||||
public boolean getBooleanFlagValue(int index) {
|
public boolean getBooleanFlagValue(int index) {
|
||||||
index += mPackageBooleanStartOffset;
|
index += mPackageBooleanStartOffset;
|
||||||
if (index >= mFlagValueList.size()) {
|
if (index >= mFlagValueList.size()) {
|
||||||
|
Reference in New Issue
Block a user