Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 910ad04d authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "aconfig: update java read api for performance" into main

parents fc19715e a8e28dfe
Loading
Loading
Loading
Loading
+43 −7
Original line number Diff line number Diff line
@@ -19,13 +19,13 @@ package android.aconfig.storage;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;

import android.aconfig.storage.PackageReadContext;
import android.aconfig.storage.FlagReadContext;
import android.aconfig.storage.BooleanFlagValue;

import dalvik.annotation.optimization.FastNative;

@@ -68,19 +68,55 @@ public class AconfigStorageReadAPI {
    }

    // JNI interface to get package read context
    // @param mappedFile: memory mapped package map file
    // @param packageName: package name
    // @throws IOException if the passed in file is not a valid package map file
    @FastNative
    public static native PackageReadContext getPackageReadContext(
        ByteBuffer mappedFile, String packageName);
    private static native ByteBuffer getPackageReadContextImpl(
        ByteBuffer mappedFile, String packageName) throws IOException;

    // API to get package read context
    // @param mappedFile: memory mapped package map file
    // @param packageName: package name
    // @throws IOException if the passed in file is not a valid package map file
    static public PackageReadContext getPackageReadContext (
        ByteBuffer mappedFile, String packageName) throws IOException {
        ByteBuffer buffer = getPackageReadContextImpl(mappedFile, packageName);
        buffer.order(ByteOrder.LITTLE_ENDIAN);
        return new PackageReadContext(buffer.getInt(), buffer.getInt(4));
    }

    // JNI interface to get flag read context
    // @param mappedFile: memory mapped flag map file
    // @param packageId: package id to represent a specific package, obtained from
    // package map file
    // @param flagName: flag name
    // @throws IOException if the passed in file is not a valid flag map file
    @FastNative
    public static native FlagReadContext getFlagReadContext(
        ByteBuffer mappedFile, int packageId, String flagName);
    private static native ByteBuffer getFlagReadContextImpl(
        ByteBuffer mappedFile, int packageId, String flagName) throws IOException;

    // API to get flag read context
    // @param mappedFile: memory mapped flag map file
    // @param packageId: package id to represent a specific package, obtained from
    // package map file
    // @param flagName: flag name
    // @throws IOException if the passed in file is not a valid flag map file
    public static FlagReadContext getFlagReadContext(
        ByteBuffer mappedFile, int packageId, String flagName) throws IOException {
        ByteBuffer buffer = getFlagReadContextImpl(mappedFile, packageId, flagName);
        buffer.order(ByteOrder.LITTLE_ENDIAN);
        return new FlagReadContext(buffer.getInt(), buffer.getInt(4));
    }

    // JNI interface to get boolean flag value
    // @param mappedFile: memory mapped flag value file
    // @param flagIndex: flag global index in the flag value array
    // @throws IOException if the passed in file is not a valid flag value file or the
    // flag index went over the file boundary.
    @FastNative
    public static native BooleanFlagValue getBooleanFlagValue(
        ByteBuffer mappedFile, int flagIndex);
    public static native boolean getBooleanFlagValue(
        ByteBuffer mappedFile, int flagIndex) throws IOException;

    static {
        System.loadLibrary("aconfig_storage_read_api_rust_jni");
+0 −30
Original line number Diff line number Diff line
package android.aconfig.storage;
/*
 * 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.
 */

public class BooleanFlagValue {
    public boolean mQuerySuccess;
    public String mErrorMessage;
    public boolean mFlagValue;

    public BooleanFlagValue(boolean querySuccess,
            String errorMessage,
            boolean value) {
        mQuerySuccess = querySuccess;
        mErrorMessage = errorMessage;
        mFlagValue = value;
    }
}
+1 −10
Original line number Diff line number Diff line
@@ -16,20 +16,11 @@ package android.aconfig.storage;
 */

public class FlagReadContext {
    public boolean mQuerySuccess;
    public String mErrorMessage;
    public boolean mFlagExists;
    public StoredFlagType mFlagType;
    public int mFlagIndex;

    public FlagReadContext(boolean querySuccess,
            String errorMessage,
            boolean flagExists,
            int flagType,
    public FlagReadContext(int flagType,
            int flagIndex) {
        mQuerySuccess = querySuccess;
        mErrorMessage = errorMessage;
        mFlagExists = flagExists;
        mFlagType = StoredFlagType.fromInteger(flagType);
        mFlagIndex = flagIndex;
    }
+1 −10
Original line number Diff line number Diff line
@@ -16,20 +16,11 @@ package android.aconfig.storage;
 */

public class PackageReadContext {
    public boolean mQuerySuccess;
    public String mErrorMessage;
    public boolean mPackageExists;
    public int mPackageId;
    public int mBooleanStartIndex;

    public PackageReadContext(boolean querySuccess,
                              String errorMessage,
                              boolean packageExists,
                              int packageId,
    public PackageReadContext(int packageId,
                              int booleanStartIndex) {
        mQuerySuccess = querySuccess;
        mErrorMessage = errorMessage;
        mPackageExists = packageExists;
        mPackageId = packageId;
        mBooleanStartIndex = booleanStartIndex;
    }
+51 −94
Original line number Diff line number Diff line
@@ -6,8 +6,8 @@ use aconfig_storage_read_api::package_table_query::find_package_read_context;
use aconfig_storage_read_api::{FlagReadContext, PackageReadContext};

use anyhow::Result;
use jni::objects::{JByteBuffer, JClass, JString, JValue};
use jni::sys::{jint, jobject};
use jni::objects::{JByteBuffer, JClass, JString};
use jni::sys::{jboolean, jint};
use jni::JNIEnv;

/// Call rust find package read context
@@ -28,55 +28,42 @@ fn get_package_read_context_java(
    Ok(find_package_read_context(buffer, &package_name)?)
}

/// Create java package read context return
fn create_java_package_read_context(
    env: &mut JNIEnv,
    success_query: bool,
    error_message: String,
    pkg_found: bool,
    pkg_id: u32,
    start_index: u32,
) -> jobject {
    let query_success = JValue::Bool(success_query as u8);
    let errmsg = env.new_string(error_message).expect("failed to create JString");
    let package_exists = JValue::Bool(pkg_found as u8);
    let package_id = JValue::Int(pkg_id as i32);
    let boolean_start_index = JValue::Int(start_index as i32);
    let context = env.new_object(
        "android/aconfig/storage/PackageReadContext",
        "(ZLjava/lang/String;ZII)V",
        &[query_success, (&errmsg).into(), package_exists, package_id, boolean_start_index],
    );
    context.expect("failed to call PackageReadContext constructor").into_raw()
}

/// Get package read context JNI
#[no_mangle]
#[allow(unused)]
pub extern "system" fn Java_android_aconfig_storage_AconfigStorageReadAPI_getPackageReadContext<
pub extern "system" fn Java_android_aconfig_storage_AconfigStorageReadAPI_getPackageReadContextImpl<
    'local,
>(
    mut env: JNIEnv<'local>,
    class: JClass<'local>,
    file: JByteBuffer<'local>,
    package: JString<'local>,
) -> jobject {
) -> JByteBuffer<'local> {
    let mut package_id = -1;
    let mut boolean_start_index = -1;

    match get_package_read_context_java(&mut env, file, package) {
        Ok(context_opt) => match context_opt {
            Some(context) => create_java_package_read_context(
                &mut env,
                true,
                String::from(""),
                true,
                context.package_id,
                context.boolean_start_index,
            ),
            None => create_java_package_read_context(&mut env, true, String::from(""), false, 0, 0),
        },
        Ok(context_opt) => {
            if let Some(context) = context_opt {
                package_id = context.package_id as i32;
                boolean_start_index = context.boolean_start_index as i32;
            }
        }
        Err(errmsg) => {
            create_java_package_read_context(&mut env, false, format!("{:?}", errmsg), false, 0, 0)
            env.throw(("java/io/IOException", errmsg.to_string())).expect("failed to throw");
        }
    }

    let mut bytes = Vec::new();
    bytes.extend_from_slice(&package_id.to_le_bytes());
    bytes.extend_from_slice(&boolean_start_index.to_le_bytes());
    let (addr, len) = {
        let buf = bytes.leak();
        (buf.as_mut_ptr(), buf.len())
    };
    // SAFETY:
    // The safety here is ensured as the content is ensured to be valid
    unsafe { env.new_direct_byte_buffer(addr, len).expect("failed to create byte buffer") }
}

/// Call rust find flag read context
@@ -98,32 +85,10 @@ fn get_flag_read_context_java(
    Ok(find_flag_read_context(buffer, package_id as u32, &flag_name)?)
}

/// Create java flag read context return
fn create_java_flag_read_context(
    env: &mut JNIEnv,
    success_query: bool,
    error_message: String,
    flg_found: bool,
    flg_type: u32,
    flg_index: u32,
) -> jobject {
    let query_success = JValue::Bool(success_query as u8);
    let errmsg = env.new_string(error_message).expect("failed to create JString");
    let flag_exists = JValue::Bool(flg_found as u8);
    let flag_type = JValue::Int(flg_type as i32);
    let flag_index = JValue::Int(flg_index as i32);
    let context = env.new_object(
        "android/aconfig/storage/FlagReadContext",
        "(ZLjava/lang/String;ZII)V",
        &[query_success, (&errmsg).into(), flag_exists, flag_type, flag_index],
    );
    context.expect("failed to call FlagReadContext constructor").into_raw()
}

/// Get flag read context JNI
#[no_mangle]
#[allow(unused)]
pub extern "system" fn Java_android_aconfig_storage_AconfigStorageReadAPI_getFlagReadContext<
pub extern "system" fn Java_android_aconfig_storage_AconfigStorageReadAPI_getFlagReadContextImpl<
    'local,
>(
    mut env: JNIEnv<'local>,
@@ -131,41 +96,32 @@ pub extern "system" fn Java_android_aconfig_storage_AconfigStorageReadAPI_getFla
    file: JByteBuffer<'local>,
    package_id: jint,
    flag: JString<'local>,
) -> jobject {
) -> JByteBuffer<'local> {
    let mut flag_type = -1;
    let mut flag_index = -1;

    match get_flag_read_context_java(&mut env, file, package_id, flag) {
        Ok(context_opt) => match context_opt {
            Some(context) => create_java_flag_read_context(
                &mut env,
                true,
                String::from(""),
                true,
                context.flag_type as u32,
                context.flag_index as u32,
            ),
            None => create_java_flag_read_context(&mut env, true, String::from(""), false, 9999, 0),
        },
        Err(errmsg) => {
            create_java_flag_read_context(&mut env, false, format!("{:?}", errmsg), false, 9999, 0)
        Ok(context_opt) => {
            if let Some(context) = context_opt {
                flag_type = context.flag_type as i32;
                flag_index = context.flag_index as i32;
            }
        }
        Err(errmsg) => {
            env.throw(("java/io/IOException", errmsg.to_string())).expect("failed to throw");
        }
    }

/// Create java boolean flag value return
fn create_java_boolean_flag_value(
    env: &mut JNIEnv,
    success_query: bool,
    error_message: String,
    value: bool,
) -> jobject {
    let query_success = JValue::Bool(success_query as u8);
    let errmsg = env.new_string(error_message).expect("failed to create JString");
    let flag_value = JValue::Bool(value as u8);
    let context = env.new_object(
        "android/aconfig/storage/BooleanFlagValue",
        "(ZLjava/lang/String;Z)V",
        &[query_success, (&errmsg).into(), flag_value],
    );
    context.expect("failed to call BooleanFlagValue constructor").into_raw()
    let mut bytes = Vec::new();
    bytes.extend_from_slice(&flag_type.to_le_bytes());
    bytes.extend_from_slice(&flag_index.to_le_bytes());
    let (addr, len) = {
        let buf = bytes.leak();
        (buf.as_mut_ptr(), buf.len())
    };
    // SAFETY:
    // The safety here is ensured as the content is ensured to be valid
    unsafe { env.new_direct_byte_buffer(addr, len).expect("failed to create byte buffer") }
}

/// Call rust find boolean flag value
@@ -193,11 +149,12 @@ pub extern "system" fn Java_android_aconfig_storage_AconfigStorageReadAPI_getBoo
    class: JClass<'local>,
    file: JByteBuffer<'local>,
    flag_index: jint,
) -> jobject {
) -> jboolean {
    match get_boolean_flag_value_java(&mut env, file, flag_index) {
        Ok(value) => create_java_boolean_flag_value(&mut env, true, String::from(""), value),
        Ok(value) => value as u8,
        Err(errmsg) => {
            create_java_boolean_flag_value(&mut env, false, format!("{:?}", errmsg), false)
            env.throw(("java/io/IOException", errmsg.to_string())).expect("failed to throw");
            0u8
        }
    }
}
Loading