diff --git a/remoteauth/service/java/com/android/server/remoteauth/jni/INativeRemoteAuthService.java b/remoteauth/service/java/com/android/server/remoteauth/jni/INativeRemoteAuthService.java new file mode 100644 index 0000000000..f79ec7e4f2 --- /dev/null +++ b/remoteauth/service/java/com/android/server/remoteauth/jni/INativeRemoteAuthService.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2023 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. + */ + +package com.android.server.remoteauth.jni; + +/** + * Interface defining a proxy between Rust and Java implementation of RemoteAuth protocol. + * + * @hide + */ +public interface INativeRemoteAuthService { + /** + * Interface for RemoteAuth PAL + * + * @hide + */ + interface IPlatform { + /** + * Sends message to the remote authenticator + * + * @param connectionId connection ID of the {@link android.remoteauth.RemoteAuthenticator} + * @param request payload of the request + * @param callback to be used to pass the response result + * + * @hide + */ + void sendRequest(int connectionId, byte[] request, ResponseCallback callback); + + /** + * Interface for a callback to send a response back. + * + * @hide + */ + interface ResponseCallback { + /** + * Invoked when message sending succeeds. + * + * @param response contains response + * + * @hide + */ + void onSuccess(byte[] response); + + /** + * Invoked when message sending fails. + * + * @param errorCode indicating the error + * + * @hide + */ + void onFailure(int errorCode); + } + } +} diff --git a/remoteauth/service/java/com/android/server/remoteauth/jni/NativeRemoteAuthService.java b/remoteauth/service/java/com/android/server/remoteauth/jni/NativeRemoteAuthService.java new file mode 100644 index 0000000000..39c2a74b4b --- /dev/null +++ b/remoteauth/service/java/com/android/server/remoteauth/jni/NativeRemoteAuthService.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2023 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. + */ + +package com.android.server.remoteauth.jni; + +import com.android.internal.annotations.Keep; +import com.android.server.remoteauth.jni.INativeRemoteAuthService.IPlatform; + +/** + * A service providing a proxy between Rust implementation and {@link + * com.android.server.remoteauth.RemoteAuthService}. + * + * @hide + */ +public class NativeRemoteAuthService { + private static final String TAG = NativeRemoteAuthService.class.getSimpleName(); + + private IPlatform mPlatform; + public final Object mNativeLock = new Object(); + + // Constructor should receive pointers to: + // ConnectivityManager, RangingManager and DB + public NativeRemoteAuthService() { + System.loadLibrary("remoteauth_jni_rust"); + synchronized (mNativeLock) { + native_init(); + } + } + + public void setDeviceListener(final IPlatform platform) { + mPlatform = platform; + } + + /** + * Sends message to the remote authenticator + * + * @param connectionId connection ID of the {@link android.remoteauth.RemoteAuthenticator} + * @param request payload of the request + * @param responseHandle a handle associated with the request, used to pass the response to the + * platform + * @param platformHandle a handle associated with the platform object, used to pass the response + * to the specific platform + * + * @hide + */ + @Keep + public void sendRequest( + int connectionId, byte[] request, long responseHandle, long platformHandle) { + mPlatform.sendRequest( + connectionId, + request, + new IPlatform.ResponseCallback() { + @Override + public void onSuccess(byte[] response) { + synchronized (mNativeLock) { + native_on_send_request_success( + response, platformHandle, responseHandle); + } + } + + @Override + public void onFailure(int errorCode) { + synchronized (mNativeLock) { + native_on_send_request_error(errorCode, platformHandle, responseHandle); + } + } + }); + } + + /* Native functions implemented in JNI */ + // This function should be implemented in remoteauth_jni_android_protocol + private native boolean native_init(); + + private native void native_on_send_request_success( + byte[] appResponse, long platformHandle, long responseHandle); + + private native void native_on_send_request_error( + int errorCode, long platformHandle, long responseHandle); +} diff --git a/remoteauth/service/java/com/android/server/remoteauth/jni/PlatformBadHandleException.java b/remoteauth/service/java/com/android/server/remoteauth/jni/PlatformBadHandleException.java new file mode 100644 index 0000000000..3ae9838b2a --- /dev/null +++ b/remoteauth/service/java/com/android/server/remoteauth/jni/PlatformBadHandleException.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2023 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. + */ + +/** + * Represents an unrecoverable error (invalid handle) that has occurred during accessing the + * platform. + */ +package com.android.server.remoteauth.jni; + +import com.android.internal.annotations.Keep; +/** + * Exception thrown by native platform rust implementation of {@link + * com.android.server.remoteauth.RemoteAuthService}. + * + * @hide + */ +@Keep +public class PlatformBadHandleException extends Exception { + public PlatformBadHandleException(final String message) { + super(message); + } + + public PlatformBadHandleException(final Exception e) { + super(e); + } + + public PlatformBadHandleException(final String message, final Exception e) { + super(message, e); + } +} diff --git a/remoteauth/service/jni/src/lib.rs b/remoteauth/service/jni/src/lib.rs index 0c18679c38..a816c947fd 100644 --- a/remoteauth/service/jni/src/lib.rs +++ b/remoteauth/service/jni/src/lib.rs @@ -19,6 +19,7 @@ mod jnames; mod unique_jvm; +mod utils; -//pub mod remoteauth_jni_android_protocol; pub mod remoteauth_jni_android_platform; +pub mod remoteauth_jni_android_protocol; diff --git a/remoteauth/service/jni/src/remoteauth_jni_android_platform.rs b/remoteauth/service/jni/src/remoteauth_jni_android_platform.rs index 4597561c2f..f3cf3eac19 100644 --- a/remoteauth/service/jni/src/remoteauth_jni_android_platform.rs +++ b/remoteauth/service/jni/src/remoteauth_jni_android_platform.rs @@ -97,12 +97,9 @@ pub struct JavaPlatform { impl JavaPlatform { // Method to create JavaPlatform - pub async fn create<'a>( - env: JNIEnv<'a>, - java_platform_native: JObject<'a>, + pub async fn create( + java_platform_native: JObject<'_>, ) -> Result>, JNIError> { - let jvm = env.get_java_vm()?; - let _ = unique_jvm::set_once(jvm); let platform_handle = generate_platform_handle(); let platform = Arc::new(Mutex::new(JavaPlatform::new( platform_handle, diff --git a/remoteauth/service/jni/src/remoteauth_jni_android_protocol.rs b/remoteauth/service/jni/src/remoteauth_jni_android_protocol.rs new file mode 100644 index 0000000000..1f7320744d --- /dev/null +++ b/remoteauth/service/jni/src/remoteauth_jni_android_protocol.rs @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2023 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. + */ + +use crate::unique_jvm; +use crate::utils::get_boolean_result; +use jni::objects::JObject; +use jni::sys::jboolean; +use jni::JNIEnv; + +#[no_mangle] +pub extern "system" fn Java_com_android_server_remoteauth_jni_NativeRemoteAuthJavaPlatform_native_init( + env: JNIEnv, + _: JObject, +) -> jboolean { + logger::init( + logger::Config::default() + .with_tag_on_device("remoteauth") + .with_min_level(log::Level::Trace) + .with_filter("trace,jni=info"), + ); + get_boolean_result(native_init(env), "native_init") +} + +fn native_init(env: JNIEnv) -> anyhow::Result<()> { + let jvm = env.get_java_vm()?; + unique_jvm::set_once(jvm) +} diff --git a/remoteauth/service/jni/src/utils.rs b/remoteauth/service/jni/src/utils.rs new file mode 100644 index 0000000000..e61b895780 --- /dev/null +++ b/remoteauth/service/jni/src/utils.rs @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2023 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. + */ + +use jni::sys::jboolean; +use log::error; + +pub(crate) fn get_boolean_result(result: anyhow::Result, error_msg: &str) -> jboolean { + match result { + Ok(_) => true, + Err(e) => { + error!("{} failed with {:?}", error_msg, &e); + false + } + } + .into() +}