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

Commit f25bd8d7 authored by Andrew Walbran's avatar Andrew Walbran Committed by Automerger Merge Worker
Browse files

Merge "Add Rust API for RPC binder." am: 7a821197 am: 5e9adf8c am: 1343e29b

parents 52753e6e 1343e29b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -446,6 +446,7 @@ cc_library {
    // This library is intentionally limited to these targets, and it will be removed later.
    // Do not expand the visibility.
    visibility: [
        ":__subpackages__",
        "//packages/modules/Virtualization:__subpackages__",
    ],
}
+0 −28
Original line number Diff line number Diff line
@@ -144,24 +144,6 @@ rust_bindgen {
    min_sdk_version: "Tiramisu",
}

// TODO(b/184872979): remove once the Rust API is created.
rust_bindgen {
    name: "libbinder_rpc_unstable_bindgen",
    wrapper_src: ":libbinder_rpc_unstable_header",
    crate_name: "binder_rpc_unstable_bindgen",
    visibility: ["//packages/modules/Virtualization:__subpackages__"],
    source_stem: "bindings",
    shared_libs: [
        "libutils",
    ],
    apex_available: [
        "com.android.compos",
        "com.android.uwb",
        "com.android.virt",
    ],
    min_sdk_version: "Tiramisu",
}

rust_test {
    name: "libbinder_rs-internal_test",
    crate_name: "binder",
@@ -188,13 +170,3 @@ rust_test {
    clippy_lints: "none",
    lints: "none",
}

rust_test {
    name: "libbinder_rpc_unstable_bindgen_test",
    srcs: [":libbinder_rpc_unstable_bindgen"],
    crate_name: "binder_rpc_unstable_bindgen",
    test_suites: ["general-tests"],
    auto_gen_config: true,
    clippy_lints: "none",
    lints: "none",
}
+50 −0
Original line number Diff line number Diff line
rust_library {
    name: "librpcbinder_rs",
    crate_name: "rpcbinder",
    srcs: ["src/lib.rs"],
    shared_libs: [
        "libutils",
    ],
    rustlibs: [
        "libbinder_ndk_sys",
        "libbinder_rpc_unstable_bindgen",
        "libbinder_rs",
        "libdowncast_rs",
        "liblibc",
    ],
    apex_available: [
        "com.android.compos",
        "com.android.uwb",
        "com.android.virt",
    ],
    min_sdk_version: "Tiramisu",
}

// TODO(b/184872979): remove once the RPC Binder API is stabilised.
rust_bindgen {
    name: "libbinder_rpc_unstable_bindgen",
    wrapper_src: ":libbinder_rpc_unstable_header",
    crate_name: "binder_rpc_unstable_bindgen",
    visibility: [":__subpackages__"],
    source_stem: "bindings",
    shared_libs: [
        "libbinder_rpc_unstable",
        "libutils",
    ],
    apex_available: [
        "com.android.compos",
        "com.android.uwb",
        "com.android.virt",
    ],
    min_sdk_version: "Tiramisu",
}

rust_test {
    name: "libbinder_rpc_unstable_bindgen_test",
    srcs: [":libbinder_rpc_unstable_bindgen"],
    crate_name: "binder_rpc_unstable_bindgen",
    test_suites: ["general-tests"],
    auto_gen_config: true,
    clippy_lints: "none",
    lints: "none",
}
+92 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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 binder::{
    unstable_api::{new_spibinder, AIBinder},
    FromIBinder, SpIBinder, StatusCode, Strong,
};
use std::os::{
    raw::{c_int, c_void},
    unix::io::RawFd,
};

/// Connects to an RPC Binder server over vsock.
pub fn get_vsock_rpc_service(cid: u32, port: u32) -> Option<SpIBinder> {
    // SAFETY: AIBinder returned by RpcClient has correct reference count, and the ownership can
    // safely be taken by new_spibinder.
    unsafe { new_spibinder(binder_rpc_unstable_bindgen::RpcClient(cid, port) as *mut AIBinder) }
}

/// Connects to an RPC Binder server for a particular interface over vsock.
pub fn get_vsock_rpc_interface<T: FromIBinder + ?Sized>(
    cid: u32,
    port: u32,
) -> Result<Strong<T>, StatusCode> {
    interface_cast(get_vsock_rpc_service(cid, port))
}

/// Connects to an RPC Binder server, using the given callback to get (and take ownership of)
/// file descriptors already connected to it.
pub fn get_preconnected_rpc_service(
    mut request_fd: impl FnMut() -> Option<RawFd>,
) -> Option<SpIBinder> {
    // Double reference the factory because trait objects aren't FFI safe.
    let mut request_fd_ref: RequestFd = &mut request_fd;
    let param = &mut request_fd_ref as *mut RequestFd as *mut c_void;

    // SAFETY: AIBinder returned by RpcPreconnectedClient has correct reference count, and the
    // ownership can be safely taken by new_spibinder. RpcPreconnectedClient does not take ownership
    // of param, only passing it to request_fd_wrapper.
    unsafe {
        new_spibinder(binder_rpc_unstable_bindgen::RpcPreconnectedClient(
            Some(request_fd_wrapper),
            param,
        ) as *mut AIBinder)
    }
}

type RequestFd<'a> = &'a mut dyn FnMut() -> Option<RawFd>;

unsafe extern "C" fn request_fd_wrapper(param: *mut c_void) -> c_int {
    // SAFETY: This is only ever called by RpcPreconnectedClient, within the lifetime of the
    // BinderFdFactory reference, with param being a properly aligned non-null pointer to an
    // initialized instance.
    let request_fd_ptr = param as *mut RequestFd;
    let request_fd = request_fd_ptr.as_mut().unwrap();
    if let Some(fd) = request_fd() {
        fd
    } else {
        -1
    }
}

/// Connects to an RPC Binder server for a particular interface, using the given callback to get
/// (and take ownership of) file descriptors already connected to it.
pub fn get_preconnected_rpc_interface<T: FromIBinder + ?Sized>(
    request_fd: impl FnMut() -> Option<RawFd>,
) -> Result<Strong<T>, StatusCode> {
    interface_cast(get_preconnected_rpc_service(request_fd))
}

fn interface_cast<T: FromIBinder + ?Sized>(
    service: Option<SpIBinder>,
) -> Result<Strong<T>, StatusCode> {
    if let Some(service) = service {
        FromIBinder::try_from(service)
    } else {
        Err(StatusCode::NAME_NOT_FOUND)
    }
}
+26 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.
 */

//! API for RPC Binder services.

mod client;
mod server;

pub use client::{
    get_preconnected_rpc_interface, get_preconnected_rpc_service, get_vsock_rpc_interface,
    get_vsock_rpc_service,
};
pub use server::{run_rpc_server, run_rpc_server_with_factory};
Loading