Merge "java reader reads directly from map" into main am: 9f254c6b5d am: f4565686e4

Original change: https://android-review.googlesource.com/c/platform/build/+/3251572

Change-Id: I334ca9039f83bfe1e0a3838c5492af6e11f0423f
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Treehugger Robot
2024-08-30 21:23:21 +00:00
committed by Automerger Merge Worker
11 changed files with 231 additions and 106 deletions

View File

@@ -16,41 +16,50 @@
package android.aconfig.storage; package android.aconfig.storage;
import static java.nio.charset.StandardCharsets.UTF_8;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
public class FlagTable { public class FlagTable {
private Header mHeader; private Header mHeader;
private Map<String, Node> mNodeMap; private ByteBufferReader mReader;
public static FlagTable fromBytes(ByteBuffer bytes) { public static FlagTable fromBytes(ByteBuffer bytes) {
FlagTable flagTable = new FlagTable(); FlagTable flagTable = new FlagTable();
ByteBufferReader reader = new ByteBufferReader(bytes); flagTable.mReader = new ByteBufferReader(bytes);
Header header = Header.fromBytes(reader); flagTable.mHeader = Header.fromBytes(flagTable.mReader);
flagTable.mHeader = header;
flagTable.mNodeMap = new HashMap(TableUtils.getTableSize(header.mNumFlags));
reader.position(header.mNodeOffset);
for (int i = 0; i < header.mNumFlags; i++) {
Node node = Node.fromBytes(reader);
flagTable.mNodeMap.put(makeKey(node.mPackageId, node.mFlagName), node);
}
return flagTable; return flagTable;
} }
public Node get(int packageId, String flagName) { public Node get(int packageId, String flagName) {
return mNodeMap.get(makeKey(packageId, flagName)); int numBuckets = (mHeader.mNodeOffset - mHeader.mBucketOffset) / 4;
int bucketIndex = TableUtils.getBucketIndex(makeKey(packageId, flagName), numBuckets);
mReader.position(mHeader.mBucketOffset + bucketIndex * 4);
int nodeIndex = mReader.readInt();
while (nodeIndex != -1) {
mReader.position(nodeIndex);
Node node = Node.fromBytes(mReader);
if (Objects.equals(flagName, node.mFlagName) && packageId == node.mPackageId) {
return node;
}
nodeIndex = node.mNextOffset;
}
throw new AconfigStorageException("get cannot find flag: " + flagName);
} }
public Header getHeader() { public Header getHeader() {
return mHeader; return mHeader;
} }
private static String makeKey(int packageId, String flagName) { private static byte[] makeKey(int packageId, String flagName) {
StringBuilder ret = new StringBuilder(); StringBuilder ret = new StringBuilder();
return ret.append(packageId).append('/').append(flagName).toString(); return ret.append(packageId).append('/').append(flagName).toString().getBytes(UTF_8);
} }
public static class Header { public static class Header {

View File

@@ -16,6 +16,8 @@
package android.aconfig.storage; package android.aconfig.storage;
import static java.nio.charset.StandardCharsets.UTF_8;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.Objects; import java.util.Objects;
@@ -33,13 +35,22 @@ public class PackageTable {
} }
public Node get(String packageName) { public Node get(String packageName) {
mReader.position(mHeader.mNodeOffset);
for (int i = 0; i < mHeader.mNumPackages; i++) { int numBuckets = (mHeader.mNodeOffset - mHeader.mBucketOffset) / 4;
int bucketIndex = TableUtils.getBucketIndex(packageName.getBytes(UTF_8), numBuckets);
mReader.position(mHeader.mBucketOffset + bucketIndex * 4);
int nodeIndex = mReader.readInt();
while (nodeIndex != -1) {
mReader.position(nodeIndex);
Node node = Node.fromBytes(mReader); Node node = Node.fromBytes(mReader);
if (Objects.equals(node.mPackageName, packageName)) { if (Objects.equals(packageName, node.mPackageName)) {
return node; return node;
} }
nodeIndex = node.mNextOffset;
} }
throw new AconfigStorageException("get cannot find package: " + packageName); throw new AconfigStorageException("get cannot find package: " + packageName);
} }

View File

@@ -44,43 +44,39 @@ public class SipHasher13 {
private void cRounds() { private void cRounds() {
v0 += v1; v0 += v1;
v1 = rotateLeft(v1, 13); v1 = Long.rotateLeft(v1, 13);
v1 ^= v0; v1 ^= v0;
v0 = rotateLeft(v0, 32); v0 = Long.rotateLeft(v0, 32);
v2 += v3; v2 += v3;
v3 = rotateLeft(v3, 16); v3 = Long.rotateLeft(v3, 16);
v3 ^= v2; v3 ^= v2;
v0 += v3; v0 += v3;
v3 = rotateLeft(v3, 21); v3 = Long.rotateLeft(v3, 21);
v3 ^= v0; v3 ^= v0;
v2 += v1; v2 += v1;
v1 = rotateLeft(v1, 17); v1 = Long.rotateLeft(v1, 17);
v1 ^= v2; v1 ^= v2;
v2 = rotateLeft(v2, 32); v2 = Long.rotateLeft(v2, 32);
} }
private void dRounds() { private void dRounds() {
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
v0 += v1; v0 += v1;
v1 = rotateLeft(v1, 13); v1 = Long.rotateLeft(v1, 13);
v1 ^= v0; v1 ^= v0;
v0 = rotateLeft(v0, 32); v0 = Long.rotateLeft(v0, 32);
v2 += v3; v2 += v3;
v3 = rotateLeft(v3, 16); v3 = Long.rotateLeft(v3, 16);
v3 ^= v2; v3 ^= v2;
v0 += v3; v0 += v3;
v3 = rotateLeft(v3, 21); v3 = Long.rotateLeft(v3, 21);
v3 ^= v0; v3 ^= v0;
v2 += v1; v2 += v1;
v1 = rotateLeft(v1, 17); v1 = Long.rotateLeft(v1, 17);
v1 ^= v2; v1 ^= v2;
v2 = rotateLeft(v2, 32); v2 = Long.rotateLeft(v2, 32);
} }
} }
private static long rotateLeft(long value, int shift) {
return (value << shift) | value >>> (64 - shift);
}
} }
public static long hash(byte[] data) { public static long hash(byte[] data) {

View File

@@ -58,4 +58,9 @@ public class TableUtils {
} }
throw new AconfigStorageException("Number of items in a hash table exceeds limit"); throw new AconfigStorageException("Number of items in a hash table exceeds limit");
} }
public static int getBucketIndex(byte[] val, int numBuckets) {
long hashVal = SipHasher13.hash(val);
return (int) Long.remainderUnsigned(hashVal, numBuckets);
}
} }

View File

@@ -30,9 +30,10 @@ android_test {
static_libs: [ static_libs: [
"androidx.test.runner", "androidx.test.runner",
"junit", "junit",
"aconfig_storage_file_java",
], ],
test_config: "AndroidStorageJaveTest.xml", test_config: "AndroidStorageJaveTest.xml",
certificate: "platform", sdk_version: "test_current",
data: [ data: [
"package.map", "package.map",
"flag.map", "flag.map",
@@ -42,4 +43,5 @@ android_test {
test_suites: [ test_suites: [
"general-tests", "general-tests",
], ],
jarjar_rules: "jarjar.txt",
} }

View File

@@ -0,0 +1,15 @@
rule android.aconfig.storage.AconfigStorageException android.aconfig.storage.test.AconfigStorageException
rule android.aconfig.storage.FlagTable android.aconfig.storage.test.FlagTable
rule android.aconfig.storage.PackageTable android.aconfig.storage.test.PackageTable
rule android.aconfig.storage.ByteBufferReader android.aconfig.storage.test.ByteBufferReader
rule android.aconfig.storage.FlagType android.aconfig.storage.test.FlagType
rule android.aconfig.storage.SipHasher13 android.aconfig.storage.test.SipHasher13
rule android.aconfig.storage.FileType android.aconfig.storage.test.FileType
rule android.aconfig.storage.FlagValueList android.aconfig.storage.test.FlagValueList
rule android.aconfig.storage.TableUtils android.aconfig.storage.test.TableUtils
rule android.aconfig.storage.FlagTable$* android.aconfig.storage.test.FlagTable$@1
rule android.aconfig.storage.PackageTable$* android.aconfig.storage.test.PackageTable$@1
rule android.aconfig.storage.FlagValueList$* android.aconfig.storage.test.FlagValueList@1
rule android.aconfig.storage.SipHasher13$* android.aconfig.storage.test.SipHasher13@1

View File

@@ -147,6 +147,7 @@ rust_ffi_shared {
crate_name: "aconfig_storage_read_api_rust_jni", crate_name: "aconfig_storage_read_api_rust_jni",
srcs: ["srcs/lib.rs"], srcs: ["srcs/lib.rs"],
rustlibs: [ rustlibs: [
"libaconfig_storage_file",
"libaconfig_storage_read_api", "libaconfig_storage_read_api",
"libanyhow", "libanyhow",
"libjni", "libjni",

View File

@@ -16,18 +16,14 @@
package android.aconfig.storage; package android.aconfig.storage;
import dalvik.annotation.optimization.FastNative;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import java.nio.MappedByteBuffer; import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import android.aconfig.storage.PackageReadContext;
import android.aconfig.storage.FlagReadContext;
import dalvik.annotation.optimization.FastNative;
public class AconfigStorageReadAPI { public class AconfigStorageReadAPI {
@@ -50,9 +46,8 @@ public class AconfigStorageReadAPI {
} }
// Map a storage file given container and file type // Map a storage file given container and file type
public static MappedByteBuffer getMappedFile( public static MappedByteBuffer getMappedFile(String container, StorageFileType type)
String container, throws IOException {
StorageFileType type) throws IOException{
switch (type) { switch (type) {
case PACKAGE_MAP: case PACKAGE_MAP:
return mapStorageFile(STORAGEDIR + "/maps/" + container + ".package.map"); return mapStorageFile(STORAGEDIR + "/maps/" + container + ".package.map");
@@ -79,7 +74,7 @@ public class AconfigStorageReadAPI {
// @param mappedFile: memory mapped package map file // @param mappedFile: memory mapped package map file
// @param packageName: package name // @param packageName: package name
// @throws IOException if the passed in file is not a valid package map file // @throws IOException if the passed in file is not a valid package map file
static public PackageReadContext getPackageReadContext ( public static PackageReadContext getPackageReadContext(
ByteBuffer mappedFile, String packageName) throws IOException { ByteBuffer mappedFile, String packageName) throws IOException {
ByteBuffer buffer = getPackageReadContextImpl(mappedFile, packageName); ByteBuffer buffer = getPackageReadContextImpl(mappedFile, packageName);
buffer.order(ByteOrder.LITTLE_ENDIAN); buffer.order(ByteOrder.LITTLE_ENDIAN);
@@ -115,8 +110,11 @@ public class AconfigStorageReadAPI {
// @throws IOException if the passed in file is not a valid flag value file or the // @throws IOException if the passed in file is not a valid flag value file or the
// flag index went over the file boundary. // flag index went over the file boundary.
@FastNative @FastNative
public static native boolean getBooleanFlagValue( public static native boolean getBooleanFlagValue(ByteBuffer mappedFile, int flagIndex)
ByteBuffer mappedFile, int flagIndex) throws IOException; throws IOException;
@FastNative
public static native long hash(String packageName) throws IOException;
static { static {
System.loadLibrary("aconfig_storage_read_api_rust_jni"); System.loadLibrary("aconfig_storage_read_api_rust_jni");

View File

@@ -1,5 +1,6 @@
//! aconfig storage read api java rust interlop //! aconfig storage read api java rust interlop
use aconfig_storage_file::SipHasher13;
use aconfig_storage_read_api::flag_table_query::find_flag_read_context; use aconfig_storage_read_api::flag_table_query::find_flag_read_context;
use aconfig_storage_read_api::flag_value_query::find_boolean_flag_value; use aconfig_storage_read_api::flag_value_query::find_boolean_flag_value;
use aconfig_storage_read_api::package_table_query::find_package_read_context; use aconfig_storage_read_api::package_table_query::find_package_read_context;
@@ -7,8 +8,9 @@ use aconfig_storage_read_api::{FlagReadContext, PackageReadContext};
use anyhow::Result; use anyhow::Result;
use jni::objects::{JByteBuffer, JClass, JString}; use jni::objects::{JByteBuffer, JClass, JString};
use jni::sys::{jboolean, jint}; use jni::sys::{jboolean, jint, jlong};
use jni::JNIEnv; use jni::JNIEnv;
use std::hash::Hasher;
/// Call rust find package read context /// Call rust find package read context
fn get_package_read_context_java( fn get_package_read_context_java(
@@ -158,3 +160,30 @@ pub extern "system" fn Java_android_aconfig_storage_AconfigStorageReadAPI_getBoo
} }
} }
} }
/// Get flag value JNI
#[no_mangle]
#[allow(unused)]
pub extern "system" fn Java_android_aconfig_storage_AconfigStorageReadAPI_hash<'local>(
mut env: JNIEnv<'local>,
class: JClass<'local>,
package_name: JString<'local>,
) -> jlong {
match siphasher13_hash(&mut env, package_name) {
Ok(value) => value as jlong,
Err(errmsg) => {
env.throw(("java/io/IOException", errmsg.to_string())).expect("failed to throw");
0i64
}
}
}
fn siphasher13_hash(env: &mut JNIEnv, package_name: JString) -> Result<u64> {
// SAFETY:
// The safety here is ensured as the flag name is guaranteed to be a java string
let flag_name: String = unsafe { env.get_string_unchecked(&package_name)?.into() };
let mut s = SipHasher13::new();
s.write(flag_name.as_bytes());
s.write_u8(0xff);
Ok(s.finish())
}

View File

@@ -16,25 +16,26 @@
package android.aconfig.storage.test; package android.aconfig.storage.test;
import java.io.IOException;
import java.nio.MappedByteBuffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import android.aconfig.DeviceProtos;
import android.aconfig.nano.Aconfig.parsed_flag;
import android.aconfig.storage.AconfigStorageReadAPI;
import android.aconfig.storage.FlagReadContext;
import android.aconfig.storage.FlagReadContext.StoredFlagType;
import android.aconfig.storage.PackageReadContext;
import android.aconfig.storage.SipHasher13;
import android.aconfig.storage.StorageInternalReader;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.junit.runners.JUnit4; import org.junit.runners.JUnit4;
import android.aconfig.storage.AconfigStorageReadAPI; import java.io.IOException;
import android.aconfig.storage.PackageReadContext; import java.nio.MappedByteBuffer;
import android.aconfig.storage.FlagReadContext; import java.util.ArrayList;
import android.aconfig.storage.FlagReadContext.StoredFlagType; import java.util.List;
@RunWith(JUnit4.class) @RunWith(JUnit4.class)
public class AconfigStorageReadAPITest { public class AconfigStorageReadAPITest {
@@ -45,25 +46,28 @@ public class AconfigStorageReadAPITest{
public void testPackageContextQuery() { public void testPackageContextQuery() {
MappedByteBuffer packageMap = null; MappedByteBuffer packageMap = null;
try { try {
packageMap = AconfigStorageReadAPI.mapStorageFile( packageMap =
mStorageDir + "/maps/mockup.package.map"); AconfigStorageReadAPI.mapStorageFile(mStorageDir + "/maps/mockup.package.map");
} catch (IOException ex) { } catch (IOException ex) {
assertTrue(ex.toString(), false); assertTrue(ex.toString(), false);
} }
assertTrue(packageMap != null); assertTrue(packageMap != null);
try { try {
PackageReadContext context = AconfigStorageReadAPI.getPackageReadContext( PackageReadContext context =
AconfigStorageReadAPI.getPackageReadContext(
packageMap, "com.android.aconfig.storage.test_1"); packageMap, "com.android.aconfig.storage.test_1");
assertEquals(context.mPackageId, 0); assertEquals(context.mPackageId, 0);
assertEquals(context.mBooleanStartIndex, 0); assertEquals(context.mBooleanStartIndex, 0);
context = AconfigStorageReadAPI.getPackageReadContext( context =
AconfigStorageReadAPI.getPackageReadContext(
packageMap, "com.android.aconfig.storage.test_2"); packageMap, "com.android.aconfig.storage.test_2");
assertEquals(context.mPackageId, 1); assertEquals(context.mPackageId, 1);
assertEquals(context.mBooleanStartIndex, 3); assertEquals(context.mBooleanStartIndex, 3);
context = AconfigStorageReadAPI.getPackageReadContext( context =
AconfigStorageReadAPI.getPackageReadContext(
packageMap, "com.android.aconfig.storage.test_4"); packageMap, "com.android.aconfig.storage.test_4");
assertEquals(context.mPackageId, 2); assertEquals(context.mPackageId, 2);
assertEquals(context.mBooleanStartIndex, 6); assertEquals(context.mBooleanStartIndex, 6);
@@ -76,16 +80,16 @@ public class AconfigStorageReadAPITest{
public void testNonExistPackageContextQuery() { public void testNonExistPackageContextQuery() {
MappedByteBuffer packageMap = null; MappedByteBuffer packageMap = null;
try { try {
packageMap = AconfigStorageReadAPI.mapStorageFile( packageMap =
mStorageDir + "/maps/mockup.package.map"); AconfigStorageReadAPI.mapStorageFile(mStorageDir + "/maps/mockup.package.map");
} catch (IOException ex) { } catch (IOException ex) {
assertTrue(ex.toString(), false); assertTrue(ex.toString(), false);
} }
assertTrue(packageMap != null); assertTrue(packageMap != null);
try { try {
PackageReadContext context = AconfigStorageReadAPI.getPackageReadContext( PackageReadContext context =
packageMap, "unknown"); AconfigStorageReadAPI.getPackageReadContext(packageMap, "unknown");
assertEquals(context.mPackageId, -1); assertEquals(context.mPackageId, -1);
assertEquals(context.mBooleanStartIndex, -1); assertEquals(context.mBooleanStartIndex, -1);
} catch (IOException ex) { } catch (IOException ex) {
@@ -97,8 +101,7 @@ public class AconfigStorageReadAPITest{
public void testFlagContextQuery() { public void testFlagContextQuery() {
MappedByteBuffer flagMap = null; MappedByteBuffer flagMap = null;
try { try {
flagMap = AconfigStorageReadAPI.mapStorageFile( flagMap = AconfigStorageReadAPI.mapStorageFile(mStorageDir + "/maps/mockup.flag.map");
mStorageDir + "/maps/mockup.flag.map");
} catch (IOException ex) { } catch (IOException ex) {
assertTrue(ex.toString(), false); assertTrue(ex.toString(), false);
} }
@@ -110,10 +113,8 @@ public class AconfigStorageReadAPITest{
public StoredFlagType mFlagType; public StoredFlagType mFlagType;
public int mFlagIndex; public int mFlagIndex;
public Baseline(int packageId, public Baseline(
String flagName, int packageId, String flagName, StoredFlagType flagType, int flagIndex) {
StoredFlagType flagType,
int flagIndex) {
mPackageId = packageId; mPackageId = packageId;
mFlagName = flagName; mFlagName = flagName;
mFlagType = flagType; mFlagType = flagType;
@@ -133,7 +134,8 @@ public class AconfigStorageReadAPITest{
try { try {
for (Baseline baseline : baselines) { for (Baseline baseline : baselines) {
FlagReadContext context = AconfigStorageReadAPI.getFlagReadContext( FlagReadContext context =
AconfigStorageReadAPI.getFlagReadContext(
flagMap, baseline.mPackageId, baseline.mFlagName); flagMap, baseline.mPackageId, baseline.mFlagName);
assertEquals(context.mFlagType, baseline.mFlagType); assertEquals(context.mFlagType, baseline.mFlagType);
assertEquals(context.mFlagIndex, baseline.mFlagIndex); assertEquals(context.mFlagIndex, baseline.mFlagIndex);
@@ -147,21 +149,19 @@ public class AconfigStorageReadAPITest{
public void testNonExistFlagContextQuery() { public void testNonExistFlagContextQuery() {
MappedByteBuffer flagMap = null; MappedByteBuffer flagMap = null;
try { try {
flagMap = AconfigStorageReadAPI.mapStorageFile( flagMap = AconfigStorageReadAPI.mapStorageFile(mStorageDir + "/maps/mockup.flag.map");
mStorageDir + "/maps/mockup.flag.map");
} catch (IOException ex) { } catch (IOException ex) {
assertTrue(ex.toString(), false); assertTrue(ex.toString(), false);
} }
assertTrue(flagMap != null); assertTrue(flagMap != null);
try { try {
FlagReadContext context = AconfigStorageReadAPI.getFlagReadContext( FlagReadContext context =
flagMap, 0, "unknown"); AconfigStorageReadAPI.getFlagReadContext(flagMap, 0, "unknown");
assertEquals(context.mFlagType, null); assertEquals(context.mFlagType, null);
assertEquals(context.mFlagIndex, -1); assertEquals(context.mFlagIndex, -1);
context = AconfigStorageReadAPI.getFlagReadContext( context = AconfigStorageReadAPI.getFlagReadContext(flagMap, 3, "enabled_ro");
flagMap, 3, "enabled_ro");
assertEquals(context.mFlagType, null); assertEquals(context.mFlagType, null);
assertEquals(context.mFlagIndex, -1); assertEquals(context.mFlagIndex, -1);
} catch (IOException ex) { } catch (IOException ex) {
@@ -173,8 +173,7 @@ public class AconfigStorageReadAPITest{
public void testBooleanFlagValueQuery() { public void testBooleanFlagValueQuery() {
MappedByteBuffer flagVal = null; MappedByteBuffer flagVal = null;
try { try {
flagVal = AconfigStorageReadAPI.mapStorageFile( flagVal = AconfigStorageReadAPI.mapStorageFile(mStorageDir + "/boot/mockup.val");
mStorageDir + "/boot/mockup.val");
} catch (IOException ex) { } catch (IOException ex) {
assertTrue(ex.toString(), false); assertTrue(ex.toString(), false);
} }
@@ -195,8 +194,7 @@ public class AconfigStorageReadAPITest{
public void testInvalidBooleanFlagValueQuery() { public void testInvalidBooleanFlagValueQuery() {
MappedByteBuffer flagVal = null; MappedByteBuffer flagVal = null;
try { try {
flagVal = AconfigStorageReadAPI.mapStorageFile( flagVal = AconfigStorageReadAPI.mapStorageFile(mStorageDir + "/boot/mockup.val");
mStorageDir + "/boot/mockup.val");
} catch (IOException ex) { } catch (IOException ex) {
assertTrue(ex.toString(), false); assertTrue(ex.toString(), false);
} }
@@ -210,4 +208,63 @@ public class AconfigStorageReadAPITest{
assertTrue(ex.toString(), ex.toString().contains(expectedErrmsg)); assertTrue(ex.toString(), ex.toString().contains(expectedErrmsg));
} }
} }
@Test
public void testRustJavaEqualHash() throws IOException {
List<parsed_flag> flags = DeviceProtos.loadAndParseFlagProtos();
for (parsed_flag flag : flags) {
String packageName = flag.package_;
String flagName = flag.name;
long rHash = AconfigStorageReadAPI.hash(packageName);
long jHash = SipHasher13.hash(packageName.getBytes());
assertEquals(rHash, jHash);
String fullFlagName = packageName + "/" + flagName;
rHash = AconfigStorageReadAPI.hash(fullFlagName);
jHash = SipHasher13.hash(fullFlagName.getBytes());
assertEquals(rHash, jHash);
}
}
@Test
public void testRustJavaEqualFlag() throws IOException {
List<parsed_flag> flags = DeviceProtos.loadAndParseFlagProtos();
String mapPath = "/metadata/aconfig/maps/";
String flagsPath = "/metadata/aconfig/boot/";
for (parsed_flag flag : flags) {
String container = flag.container;
String packageName = flag.package_;
String flagName = flag.name;
String fullFlagName = packageName + "/" + flagName;
MappedByteBuffer packageMap =
AconfigStorageReadAPI.mapStorageFile(mapPath + container + ".package.map");
MappedByteBuffer flagMap =
AconfigStorageReadAPI.mapStorageFile(mapPath + container + ".flag.map");
MappedByteBuffer flagValList =
AconfigStorageReadAPI.mapStorageFile(flagsPath + container + ".val");
PackageReadContext packageContext =
AconfigStorageReadAPI.getPackageReadContext(packageMap, packageName);
FlagReadContext flagContext =
AconfigStorageReadAPI.getFlagReadContext(
flagMap, packageContext.mPackageId, flagName);
boolean rVal =
AconfigStorageReadAPI.getBooleanFlagValue(
flagValList,
packageContext.mBooleanStartIndex + flagContext.mFlagIndex);
StorageInternalReader reader = new StorageInternalReader(container, packageName);
boolean jVal = reader.getBooleanFlagValue(flagContext.mFlagIndex);
long rHash = AconfigStorageReadAPI.hash(packageName);
long jHash = SipHasher13.hash(packageName.getBytes());
assertEquals(rVal, jVal);
}
}
} }

View File

@@ -2,6 +2,8 @@ android_test {
name: "aconfig_storage_read_api.test.java", name: "aconfig_storage_read_api.test.java",
srcs: ["./**/*.java"], srcs: ["./**/*.java"],
static_libs: [ static_libs: [
"aconfig_device_paths_java",
"aconfig_storage_file_java",
"aconfig_storage_reader_java", "aconfig_storage_reader_java",
"androidx.test.rules", "androidx.test.rules",
"libaconfig_storage_read_api_java", "libaconfig_storage_read_api_java",