Merge "Implement Discovery PLATFORM logic in Rust" into main

This commit is contained in:
Igor Zaslavsky 2023-09-01 16:28:34 +00:00 • committed by Gerrit Code Review
commit 9cdea69732

View file

@ -15,7 +15,6 @@
use crate::jnames::{SEND_REQUEST_MNAME, SEND_REQUEST_MSIG};
use crate::unique_jvm;
use anyhow::anyhow;
use async_trait::async_trait;
use jni::errors::Error as JNIError;
use jni::objects::{GlobalRef, JMethodID, JObject, JValue};
use jni::signature::TypeSignature;
@ -26,11 +25,7 @@ use log::{debug, error, info};
use std::collections::HashMap;
use std::sync::{
atomic::{AtomicI64, Ordering},
Arc,
};
use tokio::{
runtime::Runtime,
sync::{mpsc, Mutex},
Arc, Mutex,
};
/// Macro capturing the name of the function calling this macro.
@ -65,7 +60,7 @@ fn generate_platform_handle() -> i64 {
HANDLE_RN.fetch_add(1, Ordering::SeqCst)
}
async fn insert_platform_handle(handle: i64, item: Arc<Mutex<JavaPlatform>>) {
fn insert_platform_handle(handle: i64, item: Arc<Mutex<JavaPlatform>>) {
if 0 == handle {
// Init once
logger::init(
@ -75,14 +70,22 @@ async fn insert_platform_handle(handle: i64, item: Arc<Mutex<JavaPlatform>>) {
.with_filter("trace,jni=info"),
);
}
HANDLE_MAPPING.lock().await.insert(handle, Arc::clone(&item));
HANDLE_MAPPING.lock().unwrap().insert(handle, Arc::clone(&item));
}
pub trait ResponseCallback {
fn on_response(&mut self, response: Vec<u8>);
fn on_error(&mut self, error_code: i32);
}
#[async_trait]
pub trait Platform {
/// Send a binary message to the remote with the given connection id and return the response.
async fn send_request(&mut self, connection_id: i32, request: &[u8])
-> anyhow::Result<Vec<u8>>;
fn send_request(
&mut self,
connection_id: i32,
request: &[u8],
callback: Box<dyn ResponseCallback + Send>,
) -> anyhow::Result<()>;
}
//////////////////////////////////
@ -91,13 +94,13 @@ pub struct JavaPlatform {
vm: &'static Arc<JavaVM>,
platform_native_obj: GlobalRef,
send_request_method_id: JMethodID,
map_futures: Mutex<HashMap<i64, mpsc::Sender<Vec<u8>>>>,
map_futures: Mutex<HashMap<i64, Box<dyn ResponseCallback + Send>>>,
atomic_handle: AtomicI64,
}
impl JavaPlatform {
// Method to create JavaPlatform
pub async fn create(
pub fn create(
java_platform_native: JObject<'_>,
) -> Result<Arc<Mutex<impl Platform>>, JNIError> {
let platform_handle = generate_platform_handle();
@ -106,7 +109,7 @@ impl JavaPlatform {
unique_jvm::get_static_ref().ok_or(JNIError::InvalidCtorReturn)?,
java_platform_native,
)?));
insert_platform_handle(platform_handle, Arc::clone(&platform)).await;
insert_platform_handle(platform_handle, Arc::clone(&platform));
Ok(Arc::clone(&platform))
}
@ -133,19 +136,18 @@ impl JavaPlatform {
}
}
#[async_trait]
impl Platform for JavaPlatform {
async fn send_request(
fn send_request(
&mut self,
connection_id: i32,
request: &[u8],
) -> anyhow::Result<Vec<u8>> {
callback: Box<dyn ResponseCallback + Send>,
) -> anyhow::Result<()> {
let type_signature = TypeSignature::from_str(SEND_REQUEST_MSIG)
.map_err(|e| anyhow!("JNI: Invalid type signature: {:?}", e))?;
let (tx, mut rx) = mpsc::channel(1);
let response_handle = self.atomic_handle.fetch_add(1, Ordering::SeqCst);
self.map_futures.lock().await.insert(response_handle, tx);
self.map_futures.lock().unwrap().insert(response_handle, callback);
self.vm
.attach_current_thread()
.and_then(|env| {
@ -172,21 +174,20 @@ impl Platform for JavaPlatform {
))
})
.map_err(|e| anyhow!("JNI: Failed to attach current thread: {:?}", e))?;
rx.recv().await.ok_or(anyhow!("{} failed in awaiting for a result", function_name!()))
Ok(())
}
}
impl JavaPlatform {
async fn on_send_request_success(&mut self, response: &[u8], response_handle: i64) {
fn on_send_request_success(&mut self, response: &[u8], response_handle: i64) {
info!(
"{} completed successfully {}:{}",
function_name!(),
self.platform_handle,
response_handle
);
if let Some(tx) = self.map_futures.lock().await.remove(&response_handle) {
let _ = tx.send(response.to_vec()).await;
if let Some(mut callback) = self.map_futures.lock().unwrap().remove(&response_handle) {
callback.on_response(response.to_vec());
} else {
error!(
"Failed to find TX for {} and {}:{}",
@ -197,7 +198,7 @@ impl JavaPlatform {
}
}
async fn on_send_request_error(&self, error_code: i32, response_handle: i64) {
fn on_send_request_error(&self, error_code: i32, response_handle: i64) {
error!(
"{} completed with error {} {}:{}",
function_name!(),
@ -205,12 +206,11 @@ impl JavaPlatform {
self.platform_handle,
response_handle
);
if let Some(tx) = self.map_futures.lock().await.remove(&response_handle) {
// `rx.recv()` ends with `Err`
drop(tx);
if let Some(mut callback) = self.map_futures.lock().unwrap().remove(&response_handle) {
callback.on_error(error_code);
} else {
error!(
"Failed to find TX for {} and {}:{}",
"Failed to find callback for {} and {}:{}",
function_name!(),
self.platform_handle,
response_handle
@ -228,25 +228,20 @@ pub extern "system" fn Java_com_android_server_remoteauth_jni_NativeRemoteAuthJa
response_handle: jlong,
) {
debug!("{}: enter", function_name!());
Runtime::new().unwrap().block_on(native_on_send_request_success(
env,
app_response,
platform_handle,
response_handle,
));
native_on_send_request_success(env, app_response, platform_handle, response_handle);
}
async fn native_on_send_request_success(
fn native_on_send_request_success(
env: JNIEnv<'_>,
app_response: jbyteArray,
platform_handle: jlong,
response_handle: jlong,
) {
if let Some(platform) = HANDLE_MAPPING.lock().await.get(&platform_handle) {
if let Some(platform) = HANDLE_MAPPING.lock().unwrap().get(&platform_handle) {
let response =
env.convert_byte_array(app_response).map_err(|_| JNIError::InvalidCtorReturn).unwrap();
let mut platform = (*platform).lock().await;
platform.on_send_request_success(&response, response_handle).await;
let mut platform = (*platform).lock().unwrap();
platform.on_send_request_success(&response, response_handle);
} else {
let _ = env.throw_new(
"com/android/server/remoteauth/jni/BadHandleException",
@ -264,23 +259,18 @@ pub extern "system" fn Java_com_android_server_remoteauth_jni_NativeRemoteAuthJa
response_handle: jlong,
) {
debug!("{}: enter", function_name!());
Runtime::new().unwrap().block_on(native_on_send_request_error(
env,
error_code,
platform_handle,
response_handle,
));
native_on_send_request_error(env, error_code, platform_handle, response_handle);
}
async fn native_on_send_request_error(
fn native_on_send_request_error(
env: JNIEnv<'_>,
error_code: jint,
platform_handle: jlong,
response_handle: jlong,
) {
if let Some(platform) = HANDLE_MAPPING.lock().await.get(&platform_handle) {
let platform = (*platform).lock().await;
platform.on_send_request_error(error_code, response_handle).await;
if let Some(platform) = HANDLE_MAPPING.lock().unwrap().get(&platform_handle) {
let platform = (*platform).lock().unwrap();
platform.on_send_request_error(error_code, response_handle);
} else {
let _ = env.throw_new(
"com/android/server/remoteauth/jni/BadHandleException",