diff options
29 files changed, 897 insertions, 250 deletions
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp index a5c0c602c7..95a05cdcde 100644 --- a/cmds/servicemanager/ServiceManager.cpp +++ b/cmds/servicemanager/ServiceManager.cpp @@ -790,7 +790,8 @@ Status ServiceManager::registerClientCallback(const std::string& name, const sp< if (OK != IInterface::asBinder(cb)->linkToDeath(sp<ServiceManager>::fromExisting(this))) { - ALOGE("%s Could not linkToDeath when adding client callback for %s", name.c_str()); + ALOGE("%s Could not linkToDeath when adding client callback for %s", + ctx.toDebugString().c_str(), name.c_str()); return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, "Couldn't linkToDeath."); } diff --git a/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl index f8a8843309..3ddfefa311 100644 --- a/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl +++ b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl @@ -43,6 +43,18 @@ interface IPackageManagerNative { @utf8InCpp String[] getNamesForUids(in int[] uids); /** + * Return the UID associated with the given package name. + * Note that the same package will have different UIDs under different UserHandle on + * the same device. + * @param packageName The full name (i.e. com.google.apps.contacts) of the desired package. + * @param flags Additional option flags to modify the data returned. + * @param userId The user handle identifier to look up the package under. + * @return Returns an integer UID who owns the given package name, or -1 if no such package is + * available to the caller. + */ + int getPackageUid(in @utf8InCpp String packageName, in long flags, in int userId); + + /** * Returns the name of the installer (a package) which installed the named * package. Preloaded packages return the string "preload". Sideloaded packages * return an empty string. Unknown or unknowable are returned as empty strings. diff --git a/libs/binder/binder_module.h b/libs/binder/binder_module.h index eef07aef2d..b3a2d9ec28 100644 --- a/libs/binder/binder_module.h +++ b/libs/binder/binder_module.h @@ -32,77 +32,4 @@ #include <linux/android/binder.h> #include <sys/ioctl.h> -#ifndef BR_FROZEN_REPLY -// Temporary definition of BR_FROZEN_REPLY. For production -// this will come from UAPI binder.h -#define BR_FROZEN_REPLY _IO('r', 18) -#endif // BR_FROZEN_REPLY - -#ifndef BINDER_FREEZE -/* - * Temporary definitions for freeze support. For the final version - * these will be defined in the UAPI binder.h file from upstream kernel. - */ -#define BINDER_FREEZE _IOW('b', 14, struct binder_freeze_info) - -struct binder_freeze_info { - // - // Group-leader PID of process to be frozen - // - uint32_t pid; - // - // Enable(1) / Disable(0) freeze for given PID - // - uint32_t enable; - // - // Timeout to wait for transactions to drain. - // 0: don't wait (ioctl will return EAGAIN if not drained) - // N: number of ms to wait - uint32_t timeout_ms; -}; -#endif // BINDER_FREEZE - -#ifndef BINDER_GET_FROZEN_INFO - -#define BINDER_GET_FROZEN_INFO _IOWR('b', 15, struct binder_frozen_status_info) - -struct binder_frozen_status_info { - // - // Group-leader PID of process to be queried - // - __u32 pid; - // - // Indicates whether the process has received any sync calls since last - // freeze (cleared at freeze/unfreeze) - // bit 0: received sync transaction after being frozen - // bit 1: new pending sync transaction during freezing - // - __u32 sync_recv; - // - // Indicates whether the process has received any async calls since last - // freeze (cleared at freeze/unfreeze) - // - __u32 async_recv; -}; -#endif // BINDER_GET_FROZEN_INFO - -#ifndef BR_ONEWAY_SPAM_SUSPECT -// Temporary definition of BR_ONEWAY_SPAM_SUSPECT. For production -// this will come from UAPI binder.h -#define BR_ONEWAY_SPAM_SUSPECT _IO('r', 19) -#endif // BR_ONEWAY_SPAM_SUSPECT - -#ifndef BINDER_ENABLE_ONEWAY_SPAM_DETECTION -/* - * Temporary definitions for oneway spam detection support. For the final version - * these will be defined in the UAPI binder.h file from upstream kernel. - */ -#define BINDER_ENABLE_ONEWAY_SPAM_DETECTION _IOW('b', 16, __u32) -#endif // BINDER_ENABLE_ONEWAY_SPAM_DETECTION - -#ifndef BR_TRANSACTION_PENDING_FROZEN -// Temporary definition of BR_TRANSACTION_PENDING_FROZEN until UAPI binder.h includes it. -#define BR_TRANSACTION_PENDING_FROZEN _IO('r', 20) -#endif // BR_TRANSACTION_PENDING_FROZEN - #endif // _BINDER_MODULE_H_ diff --git a/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp b/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp index 7d0acd1843..392ebb5b0a 100644 --- a/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp +++ b/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp @@ -73,6 +73,17 @@ void ARpcServer_setSupportedFileDescriptorTransportModes( const ARpcSession_FileDescriptorTransportMode modes[], size_t modes_len); +// Sets the maximum number of threads that the Server will use for +// incoming client connections. +// +// This must be called before adding a client session. This corresponds +// to the number of incoming connections to RpcSession objects in the +// server, which will correspond to the number of outgoing connections +// in client RpcSession objects. +// +// If this is not specified, this will be a single-threaded server. +void ARpcServer_setMaxThreads(ARpcServer* server, size_t threads); + // Runs ARpcServer_join() in a background thread. Immediately returns. void ARpcServer_start(ARpcServer* server); diff --git a/libs/binder/libbinder_rpc_unstable.cpp b/libs/binder/libbinder_rpc_unstable.cpp index cb44c58c2c..21537fc50d 100644 --- a/libs/binder/libbinder_rpc_unstable.cpp +++ b/libs/binder/libbinder_rpc_unstable.cpp @@ -167,6 +167,10 @@ void ARpcServer_setSupportedFileDescriptorTransportModes( server->setSupportedFileDescriptorTransportModes(modevec); } +void ARpcServer_setMaxThreads(ARpcServer* handle, size_t threads) { + handleToStrongPointer<RpcServer>(handle)->setMaxThreads(threads); +} + void ARpcServer_start(ARpcServer* handle) { handleToStrongPointer<RpcServer>(handle)->start(); } diff --git a/libs/binder/rust/rpcbinder/Android.bp b/libs/binder/rust/rpcbinder/Android.bp index 535ce010f7..2e463451f9 100644 --- a/libs/binder/rust/rpcbinder/Android.bp +++ b/libs/binder/rust/rpcbinder/Android.bp @@ -18,6 +18,7 @@ rust_library { "libbinder_ndk_sys", "libbinder_rpc_unstable_bindgen_sys", "libbinder_rs", + "libcfg_if", "libdowncast_rs", "libforeign_types", "liblibc", diff --git a/libs/binder/rust/rpcbinder/src/lib.rs b/libs/binder/rust/rpcbinder/src/lib.rs index 163f000ac8..7e5c9ddc35 100644 --- a/libs/binder/rust/rpcbinder/src/lib.rs +++ b/libs/binder/rust/rpcbinder/src/lib.rs @@ -16,10 +16,10 @@ //! API for RPC Binder services. -#[cfg(not(target_os = "trusty"))] mod server; mod session; +pub use server::RpcServer; #[cfg(not(target_os = "trusty"))] -pub use server::{RpcServer, RpcServerRef}; +pub use server::RpcServerRef; pub use session::{FileDescriptorTransportMode, RpcSession, RpcSessionRef}; diff --git a/libs/binder/rust/rpcbinder/src/server.rs b/libs/binder/rust/rpcbinder/src/server.rs index 6fda878d07..d6bdbd831f 100644 --- a/libs/binder/rust/rpcbinder/src/server.rs +++ b/libs/binder/rust/rpcbinder/src/server.rs @@ -14,160 +14,12 @@ * limitations under the License. */ -use crate::session::FileDescriptorTransportMode; -use binder::{unstable_api::AsNative, SpIBinder}; -use binder_rpc_unstable_bindgen::ARpcServer; -use foreign_types::{foreign_type, ForeignType, ForeignTypeRef}; -use std::ffi::CString; -use std::io::{Error, ErrorKind}; -use std::os::unix::io::{IntoRawFd, OwnedFd}; - -foreign_type! { - type CType = binder_rpc_unstable_bindgen::ARpcServer; - fn drop = binder_rpc_unstable_bindgen::ARpcServer_free; - - /// A type that represents a foreign instance of RpcServer. - #[derive(Debug)] - pub struct RpcServer; - /// A borrowed RpcServer. - pub struct RpcServerRef; -} - -/// SAFETY: The opaque handle can be cloned freely. -unsafe impl Send for RpcServer {} -/// SAFETY: The underlying C++ RpcServer class is thread-safe. -unsafe impl Sync for RpcServer {} - -impl RpcServer { - /// Creates a binder RPC server, serving the supplied binder service implementation on the given - /// vsock port. Only connections from the given CID are accepted. - /// - // Set `cid` to libc::VMADDR_CID_ANY to accept connections from any client. - // Set `cid` to libc::VMADDR_CID_LOCAL to only bind to the local vsock interface. - pub fn new_vsock(mut service: SpIBinder, cid: u32, port: u32) -> Result<RpcServer, Error> { - let service = service.as_native_mut(); - - // SAFETY: Service ownership is transferring to the server and won't be valid afterward. - // Plus the binder objects are threadsafe. - unsafe { - Self::checked_from_ptr(binder_rpc_unstable_bindgen::ARpcServer_newVsock( - service, cid, port, - )) - } - } - - /// Creates a binder RPC server, serving the supplied binder service implementation on the given - /// socket file descriptor. The socket should be bound to an address before calling this - /// function. - pub fn new_bound_socket( - mut service: SpIBinder, - socket_fd: OwnedFd, - ) -> Result<RpcServer, Error> { - let service = service.as_native_mut(); - - // SAFETY: Service ownership is transferring to the server and won't be valid afterward. - // Plus the binder objects are threadsafe. - // The server takes ownership of the socket FD. - unsafe { - Self::checked_from_ptr(binder_rpc_unstable_bindgen::ARpcServer_newBoundSocket( - service, - socket_fd.into_raw_fd(), - )) - } - } - - /// Creates a binder RPC server that bootstraps sessions using an existing Unix domain socket - /// pair, with a given root IBinder object. Callers should create a pair of SOCK_STREAM Unix - /// domain sockets, pass one to the server and the other to the client. Multiple client session - /// can be created from the client end of the pair. - pub fn new_unix_domain_bootstrap( - mut service: SpIBinder, - bootstrap_fd: OwnedFd, - ) -> Result<RpcServer, Error> { - let service = service.as_native_mut(); - - // SAFETY: Service ownership is transferring to the server and won't be valid afterward. - // Plus the binder objects are threadsafe. - // The server takes ownership of the bootstrap FD. - unsafe { - Self::checked_from_ptr(binder_rpc_unstable_bindgen::ARpcServer_newUnixDomainBootstrap( - service, - bootstrap_fd.into_raw_fd(), - )) - } - } - - /// Creates a binder RPC server, serving the supplied binder service implementation on the given - /// IP address and port. - pub fn new_inet(mut service: SpIBinder, address: &str, port: u32) -> Result<RpcServer, Error> { - let address = match CString::new(address) { - Ok(s) => s, - Err(e) => { - log::error!("Cannot convert {} to CString. Error: {:?}", address, e); - return Err(Error::from(ErrorKind::InvalidInput)); - } - }; - let service = service.as_native_mut(); - - // SAFETY: Service ownership is transferring to the server and won't be valid afterward. - // Plus the binder objects are threadsafe. - unsafe { - Self::checked_from_ptr(binder_rpc_unstable_bindgen::ARpcServer_newInet( - service, - address.as_ptr(), - port, - )) - } - } - - unsafe fn checked_from_ptr(ptr: *mut ARpcServer) -> Result<RpcServer, Error> { - if ptr.is_null() { - return Err(Error::new(ErrorKind::Other, "Failed to start server")); - } - // SAFETY: Our caller must pass us a valid or null pointer, and we've checked that it's not - // null. - Ok(unsafe { RpcServer::from_ptr(ptr) }) - } -} - -impl RpcServerRef { - /// Sets the list of file descriptor transport modes supported by this server. - pub fn set_supported_file_descriptor_transport_modes( - &self, - modes: &[FileDescriptorTransportMode], - ) { - // SAFETY: Does not keep the pointer after returning does, nor does it - // read past its boundary. Only passes the 'self' pointer as an opaque handle. - unsafe { - binder_rpc_unstable_bindgen::ARpcServer_setSupportedFileDescriptorTransportModes( - self.as_ptr(), - modes.as_ptr(), - modes.len(), - ) - } - } - - /// Starts a new background thread and calls join(). Returns immediately. - pub fn start(&self) { - // SAFETY: RpcServerRef wraps a valid pointer to an ARpcServer. - unsafe { binder_rpc_unstable_bindgen::ARpcServer_start(self.as_ptr()) }; - } - - /// Joins the RpcServer thread. The call blocks until the server terminates. - /// This must be called from exactly one thread. - pub fn join(&self) { - // SAFETY: RpcServerRef wraps a valid pointer to an ARpcServer. - unsafe { binder_rpc_unstable_bindgen::ARpcServer_join(self.as_ptr()) }; - } - - /// Shuts down the running RpcServer. Can be called multiple times and from - /// multiple threads. Called automatically during drop(). - pub fn shutdown(&self) -> Result<(), Error> { - // SAFETY: RpcServerRef wraps a valid pointer to an ARpcServer. - if unsafe { binder_rpc_unstable_bindgen::ARpcServer_shutdown(self.as_ptr()) } { - Ok(()) - } else { - Err(Error::from(ErrorKind::UnexpectedEof)) - } +cfg_if::cfg_if! { + if #[cfg(target_os = "trusty")] { + mod trusty; + pub use trusty::*; + } else { + mod android; + pub use android::*; } } diff --git a/libs/binder/rust/rpcbinder/src/server/android.rs b/libs/binder/rust/rpcbinder/src/server/android.rs new file mode 100644 index 0000000000..2ab34472a9 --- /dev/null +++ b/libs/binder/rust/rpcbinder/src/server/android.rs @@ -0,0 +1,187 @@ +/* + * 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. + */ + +use crate::session::FileDescriptorTransportMode; +use binder::{unstable_api::AsNative, SpIBinder}; +use binder_rpc_unstable_bindgen::ARpcServer; +use foreign_types::{foreign_type, ForeignType, ForeignTypeRef}; +use std::ffi::CString; +use std::io::{Error, ErrorKind}; +use std::os::unix::io::{IntoRawFd, OwnedFd}; + +foreign_type! { + type CType = binder_rpc_unstable_bindgen::ARpcServer; + fn drop = binder_rpc_unstable_bindgen::ARpcServer_free; + + /// A type that represents a foreign instance of RpcServer. + #[derive(Debug)] + pub struct RpcServer; + /// A borrowed RpcServer. + pub struct RpcServerRef; +} + +/// SAFETY: The opaque handle can be cloned freely. +unsafe impl Send for RpcServer {} +/// SAFETY: The underlying C++ RpcServer class is thread-safe. +unsafe impl Sync for RpcServer {} + +impl RpcServer { + /// Creates a binder RPC server, serving the supplied binder service implementation on the given + /// vsock port. Only connections from the given CID are accepted. + /// + // Set `cid` to libc::VMADDR_CID_ANY to accept connections from any client. + // Set `cid` to libc::VMADDR_CID_LOCAL to only bind to the local vsock interface. + pub fn new_vsock(mut service: SpIBinder, cid: u32, port: u32) -> Result<RpcServer, Error> { + let service = service.as_native_mut(); + + // SAFETY: Service ownership is transferring to the server and won't be valid afterward. + // Plus the binder objects are threadsafe. + unsafe { + Self::checked_from_ptr(binder_rpc_unstable_bindgen::ARpcServer_newVsock( + service, cid, port, + )) + } + } + + /// Creates a binder RPC server, serving the supplied binder service implementation on the given + /// socket file descriptor. The socket should be bound to an address before calling this + /// function. + pub fn new_bound_socket( + mut service: SpIBinder, + socket_fd: OwnedFd, + ) -> Result<RpcServer, Error> { + let service = service.as_native_mut(); + + // SAFETY: Service ownership is transferring to the server and won't be valid afterward. + // Plus the binder objects are threadsafe. + // The server takes ownership of the socket FD. + unsafe { + Self::checked_from_ptr(binder_rpc_unstable_bindgen::ARpcServer_newBoundSocket( + service, + socket_fd.into_raw_fd(), + )) + } + } + + /// Creates a binder RPC server that bootstraps sessions using an existing Unix domain socket + /// pair, with a given root IBinder object. Callers should create a pair of SOCK_STREAM Unix + /// domain sockets, pass one to the server and the other to the client. Multiple client session + /// can be created from the client end of the pair. + pub fn new_unix_domain_bootstrap( + mut service: SpIBinder, + bootstrap_fd: OwnedFd, + ) -> Result<RpcServer, Error> { + let service = service.as_native_mut(); + + // SAFETY: Service ownership is transferring to the server and won't be valid afterward. + // Plus the binder objects are threadsafe. + // The server takes ownership of the bootstrap FD. + unsafe { + Self::checked_from_ptr(binder_rpc_unstable_bindgen::ARpcServer_newUnixDomainBootstrap( + service, + bootstrap_fd.into_raw_fd(), + )) + } + } + + /// Creates a binder RPC server, serving the supplied binder service implementation on the given + /// IP address and port. + pub fn new_inet(mut service: SpIBinder, address: &str, port: u32) -> Result<RpcServer, Error> { + let address = match CString::new(address) { + Ok(s) => s, + Err(e) => { + log::error!("Cannot convert {} to CString. Error: {:?}", address, e); + return Err(Error::from(ErrorKind::InvalidInput)); + } + }; + let service = service.as_native_mut(); + + // SAFETY: Service ownership is transferring to the server and won't be valid afterward. + // Plus the binder objects are threadsafe. + unsafe { + Self::checked_from_ptr(binder_rpc_unstable_bindgen::ARpcServer_newInet( + service, + address.as_ptr(), + port, + )) + } + } + + unsafe fn checked_from_ptr(ptr: *mut ARpcServer) -> Result<RpcServer, Error> { + if ptr.is_null() { + return Err(Error::new(ErrorKind::Other, "Failed to start server")); + } + // SAFETY: Our caller must pass us a valid or null pointer, and we've checked that it's not + // null. + Ok(unsafe { RpcServer::from_ptr(ptr) }) + } +} + +impl RpcServerRef { + /// Sets the list of file descriptor transport modes supported by this server. + pub fn set_supported_file_descriptor_transport_modes( + &self, + modes: &[FileDescriptorTransportMode], + ) { + // SAFETY: Does not keep the pointer after returning does, nor does it + // read past its boundary. Only passes the 'self' pointer as an opaque handle. + unsafe { + binder_rpc_unstable_bindgen::ARpcServer_setSupportedFileDescriptorTransportModes( + self.as_ptr(), + modes.as_ptr(), + modes.len(), + ) + } + } + + /// Sets the max number of threads this Server uses for incoming client connections. + /// + /// This must be called before adding a client session. This corresponds + /// to the number of incoming connections to RpcSession objects in the + /// server, which will correspond to the number of outgoing connections + /// in client RpcSession objects. Specifically this is useful for handling + /// client-side callback connections. + /// + /// If this is not specified, this will be a single-threaded server. + pub fn set_max_threads(&self, count: usize) { + // SAFETY: RpcServerRef wraps a valid pointer to an ARpcServer. + unsafe { binder_rpc_unstable_bindgen::ARpcServer_setMaxThreads(self.as_ptr(), count) }; + } + + /// Starts a new background thread and calls join(). Returns immediately. + pub fn start(&self) { + // SAFETY: RpcServerRef wraps a valid pointer to an ARpcServer. + unsafe { binder_rpc_unstable_bindgen::ARpcServer_start(self.as_ptr()) }; + } + + /// Joins the RpcServer thread. The call blocks until the server terminates. + /// This must be called from exactly one thread. + pub fn join(&self) { + // SAFETY: RpcServerRef wraps a valid pointer to an ARpcServer. + unsafe { binder_rpc_unstable_bindgen::ARpcServer_join(self.as_ptr()) }; + } + + /// Shuts down the running RpcServer. Can be called multiple times and from + /// multiple threads. Called automatically during drop(). + pub fn shutdown(&self) -> Result<(), Error> { + // SAFETY: RpcServerRef wraps a valid pointer to an ARpcServer. + if unsafe { binder_rpc_unstable_bindgen::ARpcServer_shutdown(self.as_ptr()) } { + Ok(()) + } else { + Err(Error::from(ErrorKind::UnexpectedEof)) + } + } +} diff --git a/libs/binder/rust/rpcbinder/src/server/trusty.rs b/libs/binder/rust/rpcbinder/src/server/trusty.rs new file mode 100644 index 0000000000..fe45decf25 --- /dev/null +++ b/libs/binder/rust/rpcbinder/src/server/trusty.rs @@ -0,0 +1,161 @@ +/* + * 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 binder::{unstable_api::AsNative, SpIBinder}; +use libc::size_t; +use std::ffi::{c_char, c_void}; +use std::ptr; +use tipc::{ConnectResult, Handle, MessageResult, PortCfg, TipcError, UnbufferedService, Uuid}; + +pub trait PerSessionCallback: Fn(Uuid) -> Option<SpIBinder> + Send + Sync + 'static {} +impl<T> PerSessionCallback for T where T: Fn(Uuid) -> Option<SpIBinder> + Send + Sync + 'static {} + +pub struct RpcServer { + inner: *mut binder_rpc_server_bindgen::ARpcServerTrusty, +} + +/// SAFETY: The opaque handle points to a heap allocation +/// that should be process-wide and not tied to the current thread. +unsafe impl Send for RpcServer {} +/// SAFETY: The underlying C++ RpcServer class is thread-safe. +unsafe impl Sync for RpcServer {} + +impl Drop for RpcServer { + fn drop(&mut self) { + // SAFETY: `ARpcServerTrusty_delete` is the correct destructor to call + // on pointers returned by `ARpcServerTrusty_new`. + unsafe { + binder_rpc_server_bindgen::ARpcServerTrusty_delete(self.inner); + } + } +} + +impl RpcServer { + /// Allocates a new RpcServer object. + pub fn new(service: SpIBinder) -> RpcServer { + Self::new_per_session(move |_uuid| Some(service.clone())) + } + + /// Allocates a new per-session RpcServer object. + /// + /// Per-session objects take a closure that gets called once + /// for every new connection. The closure gets the UUID of + /// the peer and can accept or reject that connection. + pub fn new_per_session<F: PerSessionCallback>(f: F) -> RpcServer { + // SAFETY: Takes ownership of the returned handle, which has correct refcount. + let inner = unsafe { + binder_rpc_server_bindgen::ARpcServerTrusty_newPerSession( + Some(per_session_callback_wrapper::<F>), + Box::into_raw(Box::new(f)).cast(), + Some(per_session_callback_deleter::<F>), + ) + }; + RpcServer { inner } + } +} + +unsafe extern "C" fn per_session_callback_wrapper<F: PerSessionCallback>( + uuid_ptr: *const c_void, + len: size_t, + cb_ptr: *mut c_char, +) -> *mut binder_rpc_server_bindgen::AIBinder { + // SAFETY: This callback should only get called while the RpcServer is alive. + let cb = unsafe { &mut *cb_ptr.cast::<F>() }; + + if len != std::mem::size_of::<Uuid>() { + return ptr::null_mut(); + } + + // SAFETY: On the previous lines we check that we got exactly the right amount of bytes. + let uuid = unsafe { + let mut uuid = std::mem::MaybeUninit::<Uuid>::uninit(); + uuid.as_mut_ptr().copy_from(uuid_ptr.cast(), 1); + uuid.assume_init() + }; + + cb(uuid).map_or_else(ptr::null_mut, |b| { + // Prevent AIBinder_decStrong from being called before AIBinder_toPlatformBinder. + // The per-session callback in C++ is supposed to call AIBinder_decStrong on the + // pointer we return here. + std::mem::ManuallyDrop::new(b).as_native_mut().cast() + }) +} + +unsafe extern "C" fn per_session_callback_deleter<F: PerSessionCallback>(cb: *mut c_char) { + // SAFETY: shared_ptr calls this to delete the pointer we gave it. + // It should only get called once the last shared reference goes away. + unsafe { + drop(Box::<F>::from_raw(cb.cast())); + } +} + +pub struct RpcServerConnection { + ctx: *mut c_void, +} + +impl Drop for RpcServerConnection { + fn drop(&mut self) { + // We do not need to close handle_fd since we do not own it. + unsafe { + binder_rpc_server_bindgen::ARpcServerTrusty_handleChannelCleanup(self.ctx); + } + } +} + +impl UnbufferedService for RpcServer { + type Connection = RpcServerConnection; + + fn on_connect( + &self, + _port: &PortCfg, + handle: &Handle, + peer: &Uuid, + ) -> tipc::Result<ConnectResult<Self::Connection>> { + let mut conn = RpcServerConnection { ctx: std::ptr::null_mut() }; + let rc = unsafe { + binder_rpc_server_bindgen::ARpcServerTrusty_handleConnect( + self.inner, + handle.as_raw_fd(), + peer.as_ptr().cast(), + &mut conn.ctx, + ) + }; + if rc < 0 { + Err(TipcError::from_uapi(rc.into())) + } else { + Ok(ConnectResult::Accept(conn)) + } + } + + fn on_message( + &self, + conn: &Self::Connection, + _handle: &Handle, + buffer: &mut [u8], + ) -> tipc::Result<MessageResult> { + assert!(buffer.is_empty()); + let rc = unsafe { binder_rpc_server_bindgen::ARpcServerTrusty_handleMessage(conn.ctx) }; + if rc < 0 { + Err(TipcError::from_uapi(rc.into())) + } else { + Ok(MessageResult::MaintainConnection) + } + } + + fn on_disconnect(&self, conn: &Self::Connection) { + unsafe { binder_rpc_server_bindgen::ARpcServerTrusty_handleDisconnect(conn.ctx) }; + } +} diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp index 2cea14f631..1f61f1852a 100644 --- a/libs/binder/tests/binderLibTest.cpp +++ b/libs/binder/tests/binderLibTest.cpp @@ -506,10 +506,11 @@ TEST_F(BinderLibTest, Freeze) { // Pass test on devices where BINDER_FREEZE ioctl is not supported int ret = IPCThreadState::self()->freeze(pid, false, 0); - if (ret != 0) { + if (ret == -EINVAL) { GTEST_SKIP(); return; } + EXPECT_EQ(NO_ERROR, ret); EXPECT_EQ(-EAGAIN, IPCThreadState::self()->freeze(pid, true, 0)); diff --git a/libs/binder/tests/unit_fuzzers/Android.bp b/libs/binder/tests/unit_fuzzers/Android.bp index a88158299e..6871cca3c1 100644 --- a/libs/binder/tests/unit_fuzzers/Android.bp +++ b/libs/binder/tests/unit_fuzzers/Android.bp @@ -52,6 +52,18 @@ cc_defaults { enabled: false, }, }, + fuzz_config: { + cc: [ + "smoreland@google.com", + "waghpawan@google.com", + ], + componentid: 32456, + description: "The fuzzer targets the APIs of libbinder", + vector: "local_no_privileges_required", + service_privilege: "privileged", + users: "multi_user", + fuzzed_code_usage: "shipped", + }, } cc_fuzz { diff --git a/libs/binder/trusty/include/binder/ARpcServerTrusty.h b/libs/binder/trusty/include/binder/ARpcServerTrusty.h new file mode 100644 index 0000000000..c82268b47b --- /dev/null +++ b/libs/binder/trusty/include/binder/ARpcServerTrusty.h @@ -0,0 +1,38 @@ +/* + * 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. + */ +#pragma once + +#include <lib/tipc/tipc_srv.h> + +#if defined(__cplusplus) +extern "C" { +#endif + +struct AIBinder; +struct ARpcServerTrusty; + +struct ARpcServerTrusty* ARpcServerTrusty_newPerSession(struct AIBinder* (*)(const void*, size_t, + char*), + char*, void (*)(char*)); +void ARpcServerTrusty_delete(struct ARpcServerTrusty*); +int ARpcServerTrusty_handleConnect(struct ARpcServerTrusty*, handle_t, const struct uuid*, void**); +int ARpcServerTrusty_handleMessage(void*); +void ARpcServerTrusty_handleDisconnect(void*); +void ARpcServerTrusty_handleChannelCleanup(void*); + +#if defined(__cplusplus) +} +#endif diff --git a/libs/binder/trusty/include/binder/RpcServerTrusty.h b/libs/binder/trusty/include/binder/RpcServerTrusty.h index bd1d90f588..fe44ea5e28 100644 --- a/libs/binder/trusty/include/binder/RpcServerTrusty.h +++ b/libs/binder/trusty/include/binder/RpcServerTrusty.h @@ -16,6 +16,7 @@ #pragma once +#include <binder/ARpcServerTrusty.h> #include <binder/IBinder.h> #include <binder/RpcServer.h> #include <binder/RpcSession.h> @@ -100,6 +101,16 @@ private: return rpcServer; } + friend struct ::ARpcServerTrusty; + friend ::ARpcServerTrusty* ::ARpcServerTrusty_newPerSession(::AIBinder* (*)(const void*, size_t, + char*), + char*, void (*)(char*)); + friend void ::ARpcServerTrusty_delete(::ARpcServerTrusty*); + friend int ::ARpcServerTrusty_handleConnect(::ARpcServerTrusty*, handle_t, const uuid*, void**); + friend int ::ARpcServerTrusty_handleMessage(void*); + friend void ::ARpcServerTrusty_handleDisconnect(void*); + friend void ::ARpcServerTrusty_handleChannelCleanup(void*); + // The Rpc-specific context maintained for every open TIPC channel. struct ChannelContext { sp<RpcSession> session; diff --git a/libs/binder/trusty/rust/binder_rpc_server_bindgen/cpp/ARpcServerTrusty.cpp b/libs/binder/trusty/rust/binder_rpc_server_bindgen/cpp/ARpcServerTrusty.cpp new file mode 100644 index 0000000000..451383a90a --- /dev/null +++ b/libs/binder/trusty/rust/binder_rpc_server_bindgen/cpp/ARpcServerTrusty.cpp @@ -0,0 +1,90 @@ +/* + * 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. + */ + +#include <android/binder_libbinder.h> +#include <binder/RpcServer.h> +#include <binder/RpcServerTrusty.h> +#include <binder/RpcSession.h> +#include <binder/RpcTransportTipcTrusty.h> + +using android::RpcServer; +using android::RpcServerTrusty; +using android::RpcSession; +using android::RpcTransportCtxFactoryTipcTrusty; +using android::sp; +using android::wp; + +struct ARpcServerTrusty { + sp<RpcServer> mRpcServer; + + ARpcServerTrusty() = delete; + ARpcServerTrusty(sp<RpcServer> rpcServer) : mRpcServer(std::move(rpcServer)) {} +}; + +ARpcServerTrusty* ARpcServerTrusty_newPerSession(AIBinder* (*cb)(const void*, size_t, char*), + char* cbArg, void (*cbArgDeleter)(char*)) { + std::shared_ptr<char> cbArgSp(cbArg, cbArgDeleter); + + auto rpcTransportCtxFactory = RpcTransportCtxFactoryTipcTrusty::make(); + if (rpcTransportCtxFactory == nullptr) { + return nullptr; + } + + auto ctx = rpcTransportCtxFactory->newServerCtx(); + if (ctx == nullptr) { + return nullptr; + } + + auto rpcServer = RpcServerTrusty::makeRpcServer(std::move(ctx)); + if (rpcServer == nullptr) { + return nullptr; + } + + rpcServer->setPerSessionRootObject( + [cb, cbArgSp](wp<RpcSession> /*session*/, const void* addrPtr, size_t len) { + auto* aib = (*cb)(addrPtr, len, cbArgSp.get()); + auto b = AIBinder_toPlatformBinder(aib); + + // We have a new sp<IBinder> backed by the same binder, so we can + // finally release the AIBinder* from the callback + AIBinder_decStrong(aib); + + return b; + }); + + return new (std::nothrow) ARpcServerTrusty(std::move(rpcServer)); +} + +void ARpcServerTrusty_delete(ARpcServerTrusty* rstr) { + delete rstr; +} + +int ARpcServerTrusty_handleConnect(ARpcServerTrusty* rstr, handle_t chan, const uuid* peer, + void** ctx_p) { + return RpcServerTrusty::handleConnectInternal(rstr->mRpcServer.get(), chan, peer, ctx_p); +} + +int ARpcServerTrusty_handleMessage(void* ctx) { + return RpcServerTrusty::handleMessageInternal(ctx); +} + +void ARpcServerTrusty_handleDisconnect(void* ctx) { + RpcServerTrusty::handleDisconnectInternal(ctx); +} + +void ARpcServerTrusty_handleChannelCleanup(void* ctx) { + RpcServerTrusty::handleChannelCleanup(ctx); +} diff --git a/libs/binder/trusty/rust/binder_rpc_server_bindgen/cpp/rules.mk b/libs/binder/trusty/rust/binder_rpc_server_bindgen/cpp/rules.mk new file mode 100644 index 0000000000..6def6343fa --- /dev/null +++ b/libs/binder/trusty/rust/binder_rpc_server_bindgen/cpp/rules.mk @@ -0,0 +1,29 @@ +# 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. +# + +LOCAL_DIR := $(GET_LOCAL_DIR) +LIBBINDER_DIR := $(LOCAL_DIR)/../../../.. + +MODULE := $(LOCAL_DIR) + +MODULE_SRCS := \ + $(LOCAL_DIR)/ARpcServerTrusty.cpp \ + +MODULE_LIBRARY_DEPS += \ + $(LIBBINDER_DIR)/trusty \ + $(LIBBINDER_DIR)/trusty/ndk \ + trusty/user/base/lib/libstdc++-trusty \ + +include make/library.mk diff --git a/libs/binder/trusty/rust/binder_rpc_server_bindgen/lib.rs b/libs/binder/trusty/rust/binder_rpc_server_bindgen/lib.rs new file mode 100644 index 0000000000..2e8b3ecb03 --- /dev/null +++ b/libs/binder/trusty/rust/binder_rpc_server_bindgen/lib.rs @@ -0,0 +1,24 @@ +/* + * 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. + */ + +//! Generated Rust bindings to binder_rpc_server + +#[allow(bad_style)] +mod sys { + include!(env!("BINDGEN_INC_FILE")); +} + +pub use sys::*; diff --git a/libs/binder/trusty/rust/binder_rpc_server_bindgen/rules.mk b/libs/binder/trusty/rust/binder_rpc_server_bindgen/rules.mk new file mode 100644 index 0000000000..4ee333f5be --- /dev/null +++ b/libs/binder/trusty/rust/binder_rpc_server_bindgen/rules.mk @@ -0,0 +1,37 @@ +# 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. +# + +LOCAL_DIR := $(GET_LOCAL_DIR) +LIBBINDER_DIR := $(LOCAL_DIR)/../../.. + +MODULE := $(LOCAL_DIR) + +MODULE_SRCS := $(LOCAL_DIR)/lib.rs + +MODULE_CRATE_NAME := binder_rpc_server_bindgen + +MODULE_LIBRARY_DEPS += \ + $(LOCAL_DIR)/cpp \ + trusty/user/base/lib/libstdc++-trusty \ + trusty/user/base/lib/trusty-sys \ + +MODULE_BINDGEN_SRC_HEADER := \ + $(LIBBINDER_DIR)/trusty/include/binder/ARpcServerTrusty.h + +MODULE_BINDGEN_FLAGS += \ + --allowlist-type="ARpcServerTrusty" \ + --allowlist-function="ARpcServerTrusty_.*" \ + +include make/library.mk diff --git a/libs/binder/trusty/rust/binder_rpc_test/main.rs b/libs/binder/trusty/rust/binder_rpc_test/main.rs index a71ce2c26e..3c1e784418 100644 --- a/libs/binder/trusty/rust/binder_rpc_test/main.rs +++ b/libs/binder/trusty/rust/binder_rpc_test/main.rs @@ -23,14 +23,21 @@ use trusty_std::ffi::{CString, FallibleCString}; test::init!(); const SERVICE_PORT: &str = "com.android.trusty.binderRpcTestService.V1"; +const RUST_SERVICE_PORT: &str = "com.android.trusty.rust.binderRpcTestService.V1"; -fn get_service() -> Strong<dyn IBinderRpcTest> { - let port = CString::try_new(SERVICE_PORT).expect("Failed to allocate port name"); +fn get_service(port: &str) -> Strong<dyn IBinderRpcTest> { + let port = CString::try_new(port).expect("Failed to allocate port name"); RpcSession::new().setup_trusty_client(port.as_c_str()).expect("Failed to create session") } #[test] fn ping() { - let srv = get_service(); + let srv = get_service(SERVICE_PORT); + assert_eq!(srv.as_binder().ping_binder(), Ok(())); +} + +#[test] +fn ping_rust() { + let srv = get_service(RUST_SERVICE_PORT); assert_eq!(srv.as_binder().ping_binder(), Ok(())); } diff --git a/libs/binder/trusty/rust/binder_rpc_test/service/main.rs b/libs/binder/trusty/rust/binder_rpc_test/service/main.rs new file mode 100644 index 0000000000..b9a86bf240 --- /dev/null +++ b/libs/binder/trusty/rust/binder_rpc_test/service/main.rs @@ -0,0 +1,159 @@ +/* + * 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 binder::{BinderFeatures, Interface, ParcelFileDescriptor, SpIBinder, Status, Strong}; +use binder_rpc_test_aidl::aidl::IBinderRpcCallback::IBinderRpcCallback; +use binder_rpc_test_aidl::aidl::IBinderRpcSession::IBinderRpcSession; +use binder_rpc_test_aidl::aidl::IBinderRpcTest::{BnBinderRpcTest, IBinderRpcTest}; +use rpcbinder::RpcServer; +use std::rc::Rc; +use tipc::{service_dispatcher, wrap_service, Manager, PortCfg}; + +const RUST_SERVICE_PORT: &str = "com.android.trusty.rust.binderRpcTestService.V1"; + +#[derive(Debug, Default)] +struct TestService; + +impl Interface for TestService {} + +impl IBinderRpcTest for TestService { + fn sendString(&self, _: &str) -> Result<(), Status> { + todo!() + } + fn doubleString(&self, _: &str) -> Result<String, Status> { + todo!() + } + fn getClientPort(&self) -> Result<i32, Status> { + todo!() + } + fn countBinders(&self) -> Result<Vec<i32>, Status> { + todo!() + } + fn getNullBinder(&self) -> Result<SpIBinder, Status> { + todo!() + } + fn pingMe(&self, _: &SpIBinder) -> Result<i32, Status> { + todo!() + } + fn repeatBinder(&self, _: Option<&SpIBinder>) -> Result<Option<SpIBinder>, Status> { + todo!() + } + fn holdBinder(&self, _: Option<&SpIBinder>) -> Result<(), Status> { + todo!() + } + fn getHeldBinder(&self) -> Result<Option<SpIBinder>, Status> { + todo!() + } + fn nestMe(&self, _: &Strong<(dyn IBinderRpcTest + 'static)>, _: i32) -> Result<(), Status> { + todo!() + } + fn alwaysGiveMeTheSameBinder(&self) -> Result<SpIBinder, Status> { + todo!() + } + fn openSession(&self, _: &str) -> Result<Strong<(dyn IBinderRpcSession + 'static)>, Status> { + todo!() + } + fn getNumOpenSessions(&self) -> Result<i32, Status> { + todo!() + } + fn lock(&self) -> Result<(), Status> { + todo!() + } + fn unlockInMsAsync(&self, _: i32) -> Result<(), Status> { + todo!() + } + fn lockUnlock(&self) -> Result<(), Status> { + todo!() + } + fn sleepMs(&self, _: i32) -> Result<(), Status> { + todo!() + } + fn sleepMsAsync(&self, _: i32) -> Result<(), Status> { + todo!() + } + fn doCallback( + &self, + _: &Strong<(dyn IBinderRpcCallback + 'static)>, + _: bool, + _: bool, + _: &str, + ) -> Result<(), Status> { + todo!() + } + fn doCallbackAsync( + &self, + _: &Strong<(dyn IBinderRpcCallback + 'static)>, + _: bool, + _: bool, + _: &str, + ) -> Result<(), Status> { + todo!() + } + fn die(&self, _: bool) -> Result<(), Status> { + todo!() + } + fn scheduleShutdown(&self) -> Result<(), Status> { + todo!() + } + fn useKernelBinderCallingId(&self) -> Result<(), Status> { + todo!() + } + fn echoAsFile(&self, _: &str) -> Result<ParcelFileDescriptor, Status> { + todo!() + } + fn concatFiles(&self, _: &[ParcelFileDescriptor]) -> Result<ParcelFileDescriptor, Status> { + todo!() + } + fn blockingSendFdOneway(&self, _: &ParcelFileDescriptor) -> Result<(), Status> { + todo!() + } + fn blockingRecvFd(&self) -> Result<ParcelFileDescriptor, Status> { + todo!() + } + fn blockingSendIntOneway(&self, _: i32) -> Result<(), Status> { + todo!() + } + fn blockingRecvInt(&self) -> Result<i32, Status> { + todo!() + } +} + +wrap_service!(TestRpcServer(RpcServer: UnbufferedService)); + +service_dispatcher! { + enum TestDispatcher { + TestRpcServer, + } +} + +fn main() { + let mut dispatcher = TestDispatcher::<1>::new().expect("Could not create test dispatcher"); + + let service = BnBinderRpcTest::new_binder(TestService::default(), BinderFeatures::default()); + let rpc_server = + TestRpcServer::new(RpcServer::new_per_session(move |_uuid| Some(service.as_binder()))); + + let cfg = PortCfg::new(RUST_SERVICE_PORT) + .expect("Could not create port config") + .allow_ta_connect() + .allow_ns_connect(); + dispatcher.add_service(Rc::new(rpc_server), cfg).expect("Could not add service to dispatcher"); + + Manager::<_, _, 1, 4>::new_with_dispatcher(dispatcher, []) + .expect("Could not create service manager") + .run_event_loop() + .expect("Test event loop failed"); +} diff --git a/libs/binder/trusty/rust/binder_rpc_test/service/manifest.json b/libs/binder/trusty/rust/binder_rpc_test/service/manifest.json new file mode 100644 index 0000000000..121ba112a8 --- /dev/null +++ b/libs/binder/trusty/rust/binder_rpc_test/service/manifest.json @@ -0,0 +1,10 @@ +{ + "uuid": "4741fc65-8b65-4893-ba55-b182c003c8b7", + "app_name": "rust_binder_rpc_test_service", + "min_heap": 16384, + "min_stack": 16384, + "mgmt_flags": { + "non_critical_app": true, + "restart_on_exit": true + } +} diff --git a/libs/binder/trusty/rust/binder_rpc_test/service/rules.mk b/libs/binder/trusty/rust/binder_rpc_test/service/rules.mk new file mode 100644 index 0000000000..1ddc382197 --- /dev/null +++ b/libs/binder/trusty/rust/binder_rpc_test/service/rules.mk @@ -0,0 +1,33 @@ +# 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. +# + +LOCAL_DIR := $(GET_LOCAL_DIR) +LIBBINDER_DIR := $(LOCAL_DIR)/../../../.. + +MODULE := $(LOCAL_DIR) + +MODULE_SRCS := $(LOCAL_DIR)/main.rs + +MODULE_CRATE_NAME := binder_rpc_test_service + +MODULE_LIBRARY_DEPS += \ + $(LIBBINDER_DIR)/trusty/rust \ + $(LIBBINDER_DIR)/trusty/rust/rpcbinder \ + $(LOCAL_DIR)/../aidl \ + trusty/user/base/lib/tipc/rust \ + +MANIFEST := $(LOCAL_DIR)/manifest.json + +include make/trusted_app.mk diff --git a/libs/binder/trusty/rust/rpcbinder/rules.mk b/libs/binder/trusty/rust/rpcbinder/rules.mk index 76f3b9401f..97f5c03cba 100644 --- a/libs/binder/trusty/rust/rpcbinder/rules.mk +++ b/libs/binder/trusty/rust/rpcbinder/rules.mk @@ -28,6 +28,8 @@ MODULE_LIBRARY_DEPS += \ $(LIBBINDER_DIR)/trusty/rust \ $(LIBBINDER_DIR)/trusty/rust/binder_ndk_sys \ $(LIBBINDER_DIR)/trusty/rust/binder_rpc_unstable_bindgen \ + $(LIBBINDER_DIR)/trusty/rust/binder_rpc_server_bindgen \ + external/rust/crates/cfg-if \ external/rust/crates/foreign-types \ trusty/user/base/lib/tipc/rust \ trusty/user/base/lib/trusty-sys \ diff --git a/libs/binder/trusty/usertests-inc.mk b/libs/binder/trusty/usertests-inc.mk index 241e6683e7..833d209012 100644 --- a/libs/binder/trusty/usertests-inc.mk +++ b/libs/binder/trusty/usertests-inc.mk @@ -16,6 +16,7 @@ TRUSTY_USER_TESTS += \ frameworks/native/libs/binder/trusty/binderRpcTest \ frameworks/native/libs/binder/trusty/binderRpcTest/service \ + frameworks/native/libs/binder/trusty/rust/binder_rpc_test/service \ TRUSTY_RUST_USER_TESTS += \ frameworks/native/libs/binder/trusty/rust/binder_rpc_test \ diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h index 818d0350c0..b41fa1dd69 100644 --- a/libs/renderengine/include/renderengine/RenderEngine.h +++ b/libs/renderengine/include/renderengine/RenderEngine.h @@ -33,7 +33,7 @@ #include <memory> /** - * Allows to set RenderEngine backend to GLES (default) or SkiaGL (NOT yet supported). + * Allows to override the RenderEngine backend. */ #define PROPERTY_DEBUG_RENDERENGINE_BACKEND "debug.renderengine.backend" diff --git a/libs/renderengine/skia/AutoBackendTexture.cpp b/libs/renderengine/skia/AutoBackendTexture.cpp index 92fe4c0b47..ee95e59d90 100644 --- a/libs/renderengine/skia/AutoBackendTexture.cpp +++ b/libs/renderengine/skia/AutoBackendTexture.cpp @@ -77,7 +77,7 @@ AutoBackendTexture::AutoBackendTexture(GrDirectContext* context, AHardwareBuffer backendFormat, isOutputBuffer); } else { - LOG_ALWAYS_FATAL("Unexpected backend %d", backend); + LOG_ALWAYS_FATAL("Unexpected backend %u", static_cast<unsigned>(backend)); } mColorType = GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat(desc.format); @@ -145,8 +145,8 @@ void logFatalTexture(const char* msg, const GrBackendTexture& tex, ui::Dataspace "\n\tGrBackendTexture: (%i x %i) hasMipmaps: %i isProtected: %i " "texType: %i\n\t\tVkImageInfo: success: %i fFormat: %i " "fSampleCount: %u fLevelCount: %u colorType %i", - msg, tex.isValid(), dataspace, tex.width(), tex.height(), - tex.hasMipmaps(), tex.isProtected(), + msg, tex.isValid(), static_cast<int32_t>(dataspace), tex.width(), + tex.height(), tex.hasMipmaps(), tex.isProtected(), static_cast<int>(tex.textureType()), retrievedImageInfo, imageInfo.fFormat, imageInfo.fSampleCount, imageInfo.fLevelCount, colorType); diff --git a/services/surfaceflinger/tests/OWNERS b/services/surfaceflinger/tests/OWNERS new file mode 100644 index 0000000000..1878326b0b --- /dev/null +++ b/services/surfaceflinger/tests/OWNERS @@ -0,0 +1,5 @@ +per-file HdrSdrRatioOverlay_test.cpp = set noparent +per-file HdrSdrRatioOverlay_test.cpp = alecmouri@google.com, sallyqi@google.com, jreck@google.com + +per-file Layer* = set noparent +per-file Layer* = pdwilliams@google.com, vishnun@google.com, melodymhsu@google.com diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_NotifyPowerBoostTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_NotifyPowerBoostTest.cpp index 22b72f98e5..f2e2c8a76f 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_NotifyPowerBoostTest.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_NotifyPowerBoostTest.cpp @@ -33,24 +33,45 @@ using aidl::android::hardware::power::Boost; TEST_F(DisplayTransactionTest, notifyPowerBoostNotifiesTouchEvent) { using namespace std::chrono_literals; + std::mutex timerMutex; + std::condition_variable cv; + injectDefaultInternalDisplay([](FakeDisplayDeviceInjector&) {}); - mFlinger.scheduler()->replaceTouchTimer(100); - std::this_thread::sleep_for(10ms); // wait for callback to be triggered + std::unique_lock lock(timerMutex); + bool didReset = false; // keeps track of what the most recent call was + + auto waitForTimerReset = [&] { cv.wait_for(lock, 100ms, [&] { return didReset; }); }; + auto waitForTimerExpired = [&] { cv.wait_for(lock, 100ms, [&] { return !didReset; }); }; + + // Add extra logic to unblock the test when the timer callbacks get called + mFlinger.scheduler()->replaceTouchTimer(10, [&](bool isReset) { + { + std::unique_lock lock(timerMutex); // guarantee we're waiting on the cv + didReset = isReset; + } + cv.notify_one(); // wake the cv + std::unique_lock lock(timerMutex); // guarantee we finished the cv logic + }); + + waitForTimerReset(); EXPECT_TRUE(mFlinger.scheduler()->isTouchActive()); // Starting timer activates touch - std::this_thread::sleep_for(110ms); // wait for reset touch timer to expire and trigger callback - EXPECT_FALSE(mFlinger.scheduler()->isTouchActive()); + waitForTimerExpired(); + EXPECT_FALSE(mFlinger.scheduler()->isTouchActive()); // Stopping timer deactivates touch EXPECT_EQ(NO_ERROR, mFlinger.notifyPowerBoost(static_cast<int32_t>(Boost::CAMERA_SHOT))); - std::this_thread::sleep_for(10ms); // wait for callback to maybe be triggered - EXPECT_FALSE(mFlinger.scheduler()->isTouchActive()); - std::this_thread::sleep_for(110ms); // wait for reset touch timer to expire and trigger callback + EXPECT_FALSE(mFlinger.scheduler()->isTouchActive()); + // Wait for the timer to start just in case + waitForTimerReset(); + EXPECT_FALSE(mFlinger.scheduler()->isTouchActive()); + // Wait for the timer to stop, again just in case + waitForTimerExpired(); EXPECT_FALSE(mFlinger.scheduler()->isTouchActive()); EXPECT_EQ(NO_ERROR, mFlinger.notifyPowerBoost(static_cast<int32_t>(Boost::INTERACTION))); - std::this_thread::sleep_for(10ms); // wait for callback to be triggered. + waitForTimerReset(); EXPECT_TRUE(mFlinger.scheduler()->isTouchActive()); } diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h index 2a1b88e6fa..c0255d3e98 100644 --- a/services/surfaceflinger/tests/unittests/TestableScheduler.h +++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h @@ -136,14 +136,25 @@ public: return mLayerHistory.mActiveLayerInfos.size(); } - void replaceTouchTimer(int64_t millis) { + void replaceTouchTimer(int64_t millis, + std::function<void(bool isReset)>&& testCallback = nullptr) { if (mTouchTimer) { mTouchTimer.reset(); } mTouchTimer.emplace( "Testable Touch timer", std::chrono::milliseconds(millis), - [this] { touchTimerCallback(TimerState::Reset); }, - [this] { touchTimerCallback(TimerState::Expired); }); + [this, testCallback] { + touchTimerCallback(TimerState::Reset); + if (testCallback != nullptr) { + testCallback(true); + } + }, + [this, testCallback] { + touchTimerCallback(TimerState::Expired); + if (testCallback != nullptr) { + testCallback(false); + } + }); mTouchTimer->start(); } |