1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.aconfig.storage; 18 19 import java.io.FileInputStream; 20 import java.io.IOException; 21 import java.nio.ByteBuffer; 22 import java.nio.ByteOrder; 23 import java.nio.MappedByteBuffer; 24 import java.nio.channels.FileChannel; 25 import java.nio.channels.FileChannel.MapMode; 26 27 import android.aconfig.storage.PackageReadContext; 28 import android.aconfig.storage.FlagReadContext; 29 30 import dalvik.annotation.optimization.FastNative; 31 32 public class AconfigStorageReadAPI { 33 34 // Storage file dir on device 35 private static final String STORAGEDIR = "/metadata/aconfig"; 36 37 // Stoarge file type 38 public enum StorageFileType { 39 PACKAGE_MAP, 40 FLAG_MAP, 41 FLAG_VAL, 42 FLAG_INFO 43 } 44 45 // Map a storage file given file path mapStorageFile(String file)46 public static MappedByteBuffer mapStorageFile(String file) throws IOException { 47 FileInputStream stream = new FileInputStream(file); 48 FileChannel channel = stream.getChannel(); 49 return channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size()); 50 } 51 52 // Map a storage file given container and file type getMappedFile( String container, StorageFileType type)53 public static MappedByteBuffer getMappedFile( 54 String container, 55 StorageFileType type) throws IOException{ 56 switch (type) { 57 case PACKAGE_MAP: 58 return mapStorageFile(STORAGEDIR + "/maps/" + container + ".package.map"); 59 case FLAG_MAP: 60 return mapStorageFile(STORAGEDIR + "/maps/" + container + ".flag.map"); 61 case FLAG_VAL: 62 return mapStorageFile(STORAGEDIR + "/boot/" + container + ".val"); 63 case FLAG_INFO: 64 return mapStorageFile(STORAGEDIR + "/boot/" + container + ".info"); 65 default: 66 throw new IOException("Invalid storage file type"); 67 } 68 } 69 70 // JNI interface to get package read context 71 // @param mappedFile: memory mapped package map file 72 // @param packageName: package name 73 // @throws IOException if the passed in file is not a valid package map file 74 @FastNative getPackageReadContextImpl( ByteBuffer mappedFile, String packageName)75 private static native ByteBuffer getPackageReadContextImpl( 76 ByteBuffer mappedFile, String packageName) throws IOException; 77 78 // API to get package read context 79 // @param mappedFile: memory mapped package map file 80 // @param packageName: package name 81 // @throws IOException if the passed in file is not a valid package map file getPackageReadContext( ByteBuffer mappedFile, String packageName)82 static public PackageReadContext getPackageReadContext ( 83 ByteBuffer mappedFile, String packageName) throws IOException { 84 ByteBuffer buffer = getPackageReadContextImpl(mappedFile, packageName); 85 buffer.order(ByteOrder.LITTLE_ENDIAN); 86 return new PackageReadContext(buffer.getInt(), buffer.getInt(4)); 87 } 88 89 // JNI interface to get flag read context 90 // @param mappedFile: memory mapped flag map file 91 // @param packageId: package id to represent a specific package, obtained from 92 // package map file 93 // @param flagName: flag name 94 // @throws IOException if the passed in file is not a valid flag map file 95 @FastNative getFlagReadContextImpl( ByteBuffer mappedFile, int packageId, String flagName)96 private static native ByteBuffer getFlagReadContextImpl( 97 ByteBuffer mappedFile, int packageId, String flagName) throws IOException; 98 99 // API to get flag read context 100 // @param mappedFile: memory mapped flag map file 101 // @param packageId: package id to represent a specific package, obtained from 102 // package map file 103 // @param flagName: flag name 104 // @throws IOException if the passed in file is not a valid flag map file getFlagReadContext( ByteBuffer mappedFile, int packageId, String flagName)105 public static FlagReadContext getFlagReadContext( 106 ByteBuffer mappedFile, int packageId, String flagName) throws IOException { 107 ByteBuffer buffer = getFlagReadContextImpl(mappedFile, packageId, flagName); 108 buffer.order(ByteOrder.LITTLE_ENDIAN); 109 return new FlagReadContext(buffer.getInt(), buffer.getInt(4)); 110 } 111 112 // JNI interface to get boolean flag value 113 // @param mappedFile: memory mapped flag value file 114 // @param flagIndex: flag global index in the flag value array 115 // @throws IOException if the passed in file is not a valid flag value file or the 116 // flag index went over the file boundary. 117 @FastNative getBooleanFlagValue( ByteBuffer mappedFile, int flagIndex)118 public static native boolean getBooleanFlagValue( 119 ByteBuffer mappedFile, int flagIndex) throws IOException; 120 121 static { 122 System.loadLibrary("aconfig_storage_read_api_rust_jni"); 123 } 124 } 125