• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! aconfig storage read api java rust interlop
2 
3 use aconfig_storage_read_api::flag_table_query::find_flag_read_context;
4 use aconfig_storage_read_api::flag_value_query::find_boolean_flag_value;
5 use aconfig_storage_read_api::package_table_query::find_package_read_context;
6 use aconfig_storage_read_api::{FlagReadContext, PackageReadContext};
7 
8 use anyhow::Result;
9 use jni::objects::{JByteBuffer, JClass, JString};
10 use jni::sys::{jboolean, jint};
11 use jni::JNIEnv;
12 
13 /// Call rust find package read context
get_package_read_context_java( env: &mut JNIEnv, file: JByteBuffer, package: JString, ) -> Result<Option<PackageReadContext>>14 fn get_package_read_context_java(
15     env: &mut JNIEnv,
16     file: JByteBuffer,
17     package: JString,
18 ) -> Result<Option<PackageReadContext>> {
19     // SAFETY:
20     // The safety here is ensured as the package name is guaranteed to be a java string
21     let package_name: String = unsafe { env.get_string_unchecked(&package)?.into() };
22     let buffer_ptr = env.get_direct_buffer_address(&file)?;
23     let buffer_size = env.get_direct_buffer_capacity(&file)?;
24     // SAFETY:
25     // The safety here is ensured as only non null MemoryMappedBuffer will be passed in,
26     // so the conversion to slice is guaranteed to be valid
27     let buffer = unsafe { std::slice::from_raw_parts(buffer_ptr, buffer_size) };
28     Ok(find_package_read_context(buffer, &package_name)?)
29 }
30 
31 /// Get package read context JNI
32 #[no_mangle]
33 #[allow(unused)]
Java_android_aconfig_storage_AconfigStorageReadAPI_getPackageReadContextImpl< 'local, >( mut env: JNIEnv<'local>, class: JClass<'local>, file: JByteBuffer<'local>, package: JString<'local>, ) -> JByteBuffer<'local>34 pub extern "system" fn Java_android_aconfig_storage_AconfigStorageReadAPI_getPackageReadContextImpl<
35     'local,
36 >(
37     mut env: JNIEnv<'local>,
38     class: JClass<'local>,
39     file: JByteBuffer<'local>,
40     package: JString<'local>,
41 ) -> JByteBuffer<'local> {
42     let mut package_id = -1;
43     let mut boolean_start_index = -1;
44 
45     match get_package_read_context_java(&mut env, file, package) {
46         Ok(context_opt) => {
47             if let Some(context) = context_opt {
48                 package_id = context.package_id as i32;
49                 boolean_start_index = context.boolean_start_index as i32;
50             }
51         }
52         Err(errmsg) => {
53             env.throw(("java/io/IOException", errmsg.to_string())).expect("failed to throw");
54         }
55     }
56 
57     let mut bytes = Vec::new();
58     bytes.extend_from_slice(&package_id.to_le_bytes());
59     bytes.extend_from_slice(&boolean_start_index.to_le_bytes());
60     let (addr, len) = {
61         let buf = bytes.leak();
62         (buf.as_mut_ptr(), buf.len())
63     };
64     // SAFETY:
65     // The safety here is ensured as the content is ensured to be valid
66     unsafe { env.new_direct_byte_buffer(addr, len).expect("failed to create byte buffer") }
67 }
68 
69 /// Call rust find flag read context
get_flag_read_context_java( env: &mut JNIEnv, file: JByteBuffer, package_id: jint, flag: JString, ) -> Result<Option<FlagReadContext>>70 fn get_flag_read_context_java(
71     env: &mut JNIEnv,
72     file: JByteBuffer,
73     package_id: jint,
74     flag: JString,
75 ) -> Result<Option<FlagReadContext>> {
76     // SAFETY:
77     // The safety here is ensured as the flag name is guaranteed to be a java string
78     let flag_name: String = unsafe { env.get_string_unchecked(&flag)?.into() };
79     let buffer_ptr = env.get_direct_buffer_address(&file)?;
80     let buffer_size = env.get_direct_buffer_capacity(&file)?;
81     // SAFETY:
82     // The safety here is ensured as only non null MemoryMappedBuffer will be passed in,
83     // so the conversion to slice is guaranteed to be valid
84     let buffer = unsafe { std::slice::from_raw_parts(buffer_ptr, buffer_size) };
85     Ok(find_flag_read_context(buffer, package_id as u32, &flag_name)?)
86 }
87 
88 /// Get flag read context JNI
89 #[no_mangle]
90 #[allow(unused)]
Java_android_aconfig_storage_AconfigStorageReadAPI_getFlagReadContextImpl< 'local, >( mut env: JNIEnv<'local>, class: JClass<'local>, file: JByteBuffer<'local>, package_id: jint, flag: JString<'local>, ) -> JByteBuffer<'local>91 pub extern "system" fn Java_android_aconfig_storage_AconfigStorageReadAPI_getFlagReadContextImpl<
92     'local,
93 >(
94     mut env: JNIEnv<'local>,
95     class: JClass<'local>,
96     file: JByteBuffer<'local>,
97     package_id: jint,
98     flag: JString<'local>,
99 ) -> JByteBuffer<'local> {
100     let mut flag_type = -1;
101     let mut flag_index = -1;
102 
103     match get_flag_read_context_java(&mut env, file, package_id, flag) {
104         Ok(context_opt) => {
105             if let Some(context) = context_opt {
106                 flag_type = context.flag_type as i32;
107                 flag_index = context.flag_index as i32;
108             }
109         }
110         Err(errmsg) => {
111             env.throw(("java/io/IOException", errmsg.to_string())).expect("failed to throw");
112         }
113     }
114 
115     let mut bytes = Vec::new();
116     bytes.extend_from_slice(&flag_type.to_le_bytes());
117     bytes.extend_from_slice(&flag_index.to_le_bytes());
118     let (addr, len) = {
119         let buf = bytes.leak();
120         (buf.as_mut_ptr(), buf.len())
121     };
122     // SAFETY:
123     // The safety here is ensured as the content is ensured to be valid
124     unsafe { env.new_direct_byte_buffer(addr, len).expect("failed to create byte buffer") }
125 }
126 
127 /// Call rust find boolean flag value
get_boolean_flag_value_java( env: &mut JNIEnv, file: JByteBuffer, flag_index: jint, ) -> Result<bool>128 fn get_boolean_flag_value_java(
129     env: &mut JNIEnv,
130     file: JByteBuffer,
131     flag_index: jint,
132 ) -> Result<bool> {
133     let buffer_ptr = env.get_direct_buffer_address(&file)?;
134     let buffer_size = env.get_direct_buffer_capacity(&file)?;
135     // SAFETY:
136     // The safety here is ensured as only non null MemoryMappedBuffer will be passed in,
137     // so the conversion to slice is guaranteed to be valid
138     let buffer = unsafe { std::slice::from_raw_parts(buffer_ptr, buffer_size) };
139     Ok(find_boolean_flag_value(buffer, flag_index as u32)?)
140 }
141 
142 /// Get flag value JNI
143 #[no_mangle]
144 #[allow(unused)]
Java_android_aconfig_storage_AconfigStorageReadAPI_getBooleanFlagValue< 'local, >( mut env: JNIEnv<'local>, class: JClass<'local>, file: JByteBuffer<'local>, flag_index: jint, ) -> jboolean145 pub extern "system" fn Java_android_aconfig_storage_AconfigStorageReadAPI_getBooleanFlagValue<
146     'local,
147 >(
148     mut env: JNIEnv<'local>,
149     class: JClass<'local>,
150     file: JByteBuffer<'local>,
151     flag_index: jint,
152 ) -> jboolean {
153     match get_boolean_flag_value_java(&mut env, file, flag_index) {
154         Ok(value) => value as u8,
155         Err(errmsg) => {
156             env.throw(("java/io/IOException", errmsg.to_string())).expect("failed to throw");
157             0u8
158         }
159     }
160 }
161