Loading system/gd/rust/facade/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ rust_library { "libgrpcio", "libprotobuf", "libtokio", "libgddi", ], host_supported: true, } Loading system/gd/rust/facade/src/lib.rs +36 −19 Original line number Diff line number Diff line Loading @@ -14,20 +14,31 @@ use rootservice::*; use rootservice_grpc::{create_root_facade, RootFacade}; use bt_hal::facade::HciHalFacadeService; use bt_hal::rootcanal_hal::{RootcanalConfig, RootcanalHal}; use bt_hal::hal_facade_module; use bt_hal::rootcanal_hal::RootcanalConfig; use bt_hci::facade::HciLayerFacadeService; use bt_hci::Hci; use bt_hci::hci_module; use tokio::runtime::Runtime; use tokio::sync::mpsc::{channel, Sender}; use tokio::sync::oneshot; use gddi::{module, Registry, RegistryBuilder}; use grpcio::*; use std::sync::Arc; use futures::executor::block_on; module! { stack_module, submodules { hal_facade_module, hci_module, } } /// Bluetooth testing root facade service #[derive(Clone)] pub struct RootFacadeService { Loading Loading @@ -94,13 +105,29 @@ impl FacadeServiceManager { fn create(rt: Arc<Runtime>, grpc_port: u16, rootcanal_port: Option<u16>) -> Self { let (tx, mut rx) = channel::<LifecycleCommand>(1); let local_rt = rt.clone(); local_rt.spawn(async move { rt.spawn(async move { let mut server: Option<Server> = None; while let Some(cmd) = rx.recv().await { match cmd { LifecycleCommand::Start { req, done } => { server = Some(Self::start_internal(&rt, req, grpc_port, rootcanal_port).await); let registry = { let mut builder = RegistryBuilder::new(); builder.register_module(stack_module); if rootcanal_port.is_some() { builder.register_module(bt_hal::rootcanal_hal_module); } Arc::new(builder.build()) }; registry.inject(local_rt.clone()).await; if let Some(rc_port) = rootcanal_port { registry .inject(RootcanalConfig::new(rc_port, "127.0.0.1")) .await; } server = Some(Self::start_internal(®istry, req, grpc_port).await); done.send(()).unwrap(); } LifecycleCommand::Stop { done } => { Loading Loading @@ -135,30 +162,20 @@ impl FacadeServiceManager { Ok(()) } // TODO this is messy and needs to be overhauled to support bringing up the stack to partial // layers. Will be cleaned up soon. async fn start_internal( rt: &Arc<Runtime>, registry: &Arc<Registry>, req: StartStackRequest, grpc_port: u16, rootcanal_port: Option<u16>, ) -> Server { let hal_exports = RootcanalHal::start( RootcanalConfig::new(rootcanal_port.unwrap(), "127.0.0.1"), Arc::clone(&rt), ) .await .unwrap(); let mut services = Vec::new(); match req.get_module_under_test() { BluetoothModule::HAL => { services.push(HciHalFacadeService::create(hal_exports, Arc::clone(&rt))); services.push(registry.get::<HciHalFacadeService>().await.create_grpc()); } BluetoothModule::HCI => { let hci_exports = Hci::start(hal_exports, Arc::clone(&rt)); services.push(HciLayerFacadeService::create(hci_exports, Arc::clone(&rt))); services.push(registry.get::<HciLayerFacadeService>().await.create_grpc()); } _ => unimplemented!() _ => unimplemented!(), } FacadeServiceManager::start_server(services, grpc_port) Loading system/gd/rust/gddi-macros/src/lib.rs +4 −4 Original line number Diff line number Diff line Loading @@ -28,7 +28,7 @@ pub fn provides(_attr: TokenStream, item: TokenStream) -> TokenStream { let emitted_code = quote! { // Injecting wrapper fn #injected_ident(registry: std::sync::Arc<gddi::Registry>) -> std::pin::Pin<Box<dyn std::future::Future<Output = Box<dyn std::any::Any>>>> { fn #injected_ident(registry: std::sync::Arc<gddi::Registry>) -> std::pin::Pin<gddi::ProviderFutureBox> { Box::pin(async move { // Create a local variable for each argument, to ensure they get generated in a // deterministic order (compiler complains otherwise) Loading Loading @@ -139,11 +139,11 @@ pub fn module(item: TokenStream) -> TokenStream { let submodule_idents = module.submodules.iter(); let emitted_code = quote! { #[doc(hidden)] pub fn #init_ident(registry: &mut gddi::Registry) { pub fn #init_ident(builder: &mut gddi::RegistryBuilder) { // Register all providers on this module #(registry.register_provider::<#types>(Box::new(#provider_idents));)* #(builder.register_provider::<#types>(Box::new(#provider_idents));)* // Register all submodules on this module #(registry.register_module(#submodule_idents);)* #(builder.register_module(#submodule_idents);)* } }; emitted_code.into() Loading system/gd/rust/gddi/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -5,4 +5,5 @@ rust_library { host_supported: true, edition: "2018", proc_macros: ["libgddi_macros"], rustlibs: ["libtokio"], } system/gd/rust/gddi/src/lib.rs +62 −16 Original line number Diff line number Diff line Loading @@ -8,27 +8,41 @@ use std::future::Future; use std::pin::Pin; use std::sync::Arc; use tokio::sync::Mutex; pub use gddi_macros::{module, provides}; type InstanceBox = Box<dyn Any + Send + Sync>; /// A box around a future for a provider that is safe to send between threads pub type ProviderFutureBox = Box<dyn Future<Output = Box<dyn Any>> + Send + Sync>; type ProviderFnBox = Box<dyn Fn(Arc<Registry>) -> Pin<ProviderFutureBox> + Send + Sync>; /// Builder for Registry pub struct RegistryBuilder { providers: HashMap<TypeId, Provider>, } /// Keeps track of central injection state pub struct Registry { providers: HashMap<TypeId, Provider>, providers: Arc<Mutex<HashMap<TypeId, Provider>>>, instances: Arc<Mutex<HashMap<TypeId, InstanceBox>>>, } #[derive(Clone)] struct Provider { f: Box<dyn Fn(Arc<Registry>) -> Pin<Box<dyn Future<Output = Box<dyn Any>>>>>, f: Arc<ProviderFnBox>, } impl Default for Registry { impl Default for RegistryBuilder { fn default() -> Self { Self::new() } } impl Registry { /// Creates a new registry impl RegistryBuilder { /// Creates a new RegistryBuilder pub fn new() -> Self { Registry { RegistryBuilder { providers: HashMap::new(), } } Loading @@ -36,23 +50,55 @@ impl Registry { /// Registers a module with this registry pub fn register_module<F>(&mut self, init: F) where F: Fn(&mut Registry), F: Fn(&mut Self), { init(self); } /// Registers a provider function with this registry pub fn register_provider<T: 'static>( &mut self, f: Box<dyn Fn(Arc<Registry>) -> Pin<Box<dyn Future<Output = Box<dyn Any>>>>>, ) { self.providers.insert(TypeId::of::<T>(), Provider { f }); pub fn register_provider<T: 'static>(&mut self, f: ProviderFnBox) { self.providers .insert(TypeId::of::<T>(), Provider { f: Arc::new(f) }); } /// Construct the Registry from this builder pub fn build(self) -> Registry { Registry { providers: Arc::new(Mutex::new(self.providers)), instances: Arc::new(Mutex::new(HashMap::new())), } } } impl Registry { /// Gets an instance of a type, implicitly starting any dependencies if necessary pub async fn get<T: 'static + Clone>(self: &Arc<Self>) -> T { let provider = &self.providers[&TypeId::of::<T>()]; pub async fn get<T: 'static + Clone + Send + Sync>(self: &Arc<Self>) -> T { let typeid = TypeId::of::<T>(); { let instances = self.instances.lock().await; if let Some(value) = instances.get(&typeid) { return value .downcast_ref::<T>() .expect("was not correct type") .clone(); } } let casted = { let provider = { self.providers.lock().await[&typeid].clone() }; let result = (provider.f)(self.clone()).await; *result.downcast::<T>().expect("was not correct type") (*result.downcast::<T>().expect("was not correct type")).clone() }; let mut instances = self.instances.lock().await; instances.insert(typeid, Box::new(casted.clone())); casted } /// Inject an already created instance of T. Useful for config. pub async fn inject<T: 'static + Clone + Send + Sync>(self: &Arc<Self>, obj: T) { let mut instances = self.instances.lock().await; instances.insert(TypeId::of::<T>(), Box::new(obj)); } } Loading
system/gd/rust/facade/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ rust_library { "libgrpcio", "libprotobuf", "libtokio", "libgddi", ], host_supported: true, } Loading
system/gd/rust/facade/src/lib.rs +36 −19 Original line number Diff line number Diff line Loading @@ -14,20 +14,31 @@ use rootservice::*; use rootservice_grpc::{create_root_facade, RootFacade}; use bt_hal::facade::HciHalFacadeService; use bt_hal::rootcanal_hal::{RootcanalConfig, RootcanalHal}; use bt_hal::hal_facade_module; use bt_hal::rootcanal_hal::RootcanalConfig; use bt_hci::facade::HciLayerFacadeService; use bt_hci::Hci; use bt_hci::hci_module; use tokio::runtime::Runtime; use tokio::sync::mpsc::{channel, Sender}; use tokio::sync::oneshot; use gddi::{module, Registry, RegistryBuilder}; use grpcio::*; use std::sync::Arc; use futures::executor::block_on; module! { stack_module, submodules { hal_facade_module, hci_module, } } /// Bluetooth testing root facade service #[derive(Clone)] pub struct RootFacadeService { Loading Loading @@ -94,13 +105,29 @@ impl FacadeServiceManager { fn create(rt: Arc<Runtime>, grpc_port: u16, rootcanal_port: Option<u16>) -> Self { let (tx, mut rx) = channel::<LifecycleCommand>(1); let local_rt = rt.clone(); local_rt.spawn(async move { rt.spawn(async move { let mut server: Option<Server> = None; while let Some(cmd) = rx.recv().await { match cmd { LifecycleCommand::Start { req, done } => { server = Some(Self::start_internal(&rt, req, grpc_port, rootcanal_port).await); let registry = { let mut builder = RegistryBuilder::new(); builder.register_module(stack_module); if rootcanal_port.is_some() { builder.register_module(bt_hal::rootcanal_hal_module); } Arc::new(builder.build()) }; registry.inject(local_rt.clone()).await; if let Some(rc_port) = rootcanal_port { registry .inject(RootcanalConfig::new(rc_port, "127.0.0.1")) .await; } server = Some(Self::start_internal(®istry, req, grpc_port).await); done.send(()).unwrap(); } LifecycleCommand::Stop { done } => { Loading Loading @@ -135,30 +162,20 @@ impl FacadeServiceManager { Ok(()) } // TODO this is messy and needs to be overhauled to support bringing up the stack to partial // layers. Will be cleaned up soon. async fn start_internal( rt: &Arc<Runtime>, registry: &Arc<Registry>, req: StartStackRequest, grpc_port: u16, rootcanal_port: Option<u16>, ) -> Server { let hal_exports = RootcanalHal::start( RootcanalConfig::new(rootcanal_port.unwrap(), "127.0.0.1"), Arc::clone(&rt), ) .await .unwrap(); let mut services = Vec::new(); match req.get_module_under_test() { BluetoothModule::HAL => { services.push(HciHalFacadeService::create(hal_exports, Arc::clone(&rt))); services.push(registry.get::<HciHalFacadeService>().await.create_grpc()); } BluetoothModule::HCI => { let hci_exports = Hci::start(hal_exports, Arc::clone(&rt)); services.push(HciLayerFacadeService::create(hci_exports, Arc::clone(&rt))); services.push(registry.get::<HciLayerFacadeService>().await.create_grpc()); } _ => unimplemented!() _ => unimplemented!(), } FacadeServiceManager::start_server(services, grpc_port) Loading
system/gd/rust/gddi-macros/src/lib.rs +4 −4 Original line number Diff line number Diff line Loading @@ -28,7 +28,7 @@ pub fn provides(_attr: TokenStream, item: TokenStream) -> TokenStream { let emitted_code = quote! { // Injecting wrapper fn #injected_ident(registry: std::sync::Arc<gddi::Registry>) -> std::pin::Pin<Box<dyn std::future::Future<Output = Box<dyn std::any::Any>>>> { fn #injected_ident(registry: std::sync::Arc<gddi::Registry>) -> std::pin::Pin<gddi::ProviderFutureBox> { Box::pin(async move { // Create a local variable for each argument, to ensure they get generated in a // deterministic order (compiler complains otherwise) Loading Loading @@ -139,11 +139,11 @@ pub fn module(item: TokenStream) -> TokenStream { let submodule_idents = module.submodules.iter(); let emitted_code = quote! { #[doc(hidden)] pub fn #init_ident(registry: &mut gddi::Registry) { pub fn #init_ident(builder: &mut gddi::RegistryBuilder) { // Register all providers on this module #(registry.register_provider::<#types>(Box::new(#provider_idents));)* #(builder.register_provider::<#types>(Box::new(#provider_idents));)* // Register all submodules on this module #(registry.register_module(#submodule_idents);)* #(builder.register_module(#submodule_idents);)* } }; emitted_code.into() Loading
system/gd/rust/gddi/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -5,4 +5,5 @@ rust_library { host_supported: true, edition: "2018", proc_macros: ["libgddi_macros"], rustlibs: ["libtokio"], }
system/gd/rust/gddi/src/lib.rs +62 −16 Original line number Diff line number Diff line Loading @@ -8,27 +8,41 @@ use std::future::Future; use std::pin::Pin; use std::sync::Arc; use tokio::sync::Mutex; pub use gddi_macros::{module, provides}; type InstanceBox = Box<dyn Any + Send + Sync>; /// A box around a future for a provider that is safe to send between threads pub type ProviderFutureBox = Box<dyn Future<Output = Box<dyn Any>> + Send + Sync>; type ProviderFnBox = Box<dyn Fn(Arc<Registry>) -> Pin<ProviderFutureBox> + Send + Sync>; /// Builder for Registry pub struct RegistryBuilder { providers: HashMap<TypeId, Provider>, } /// Keeps track of central injection state pub struct Registry { providers: HashMap<TypeId, Provider>, providers: Arc<Mutex<HashMap<TypeId, Provider>>>, instances: Arc<Mutex<HashMap<TypeId, InstanceBox>>>, } #[derive(Clone)] struct Provider { f: Box<dyn Fn(Arc<Registry>) -> Pin<Box<dyn Future<Output = Box<dyn Any>>>>>, f: Arc<ProviderFnBox>, } impl Default for Registry { impl Default for RegistryBuilder { fn default() -> Self { Self::new() } } impl Registry { /// Creates a new registry impl RegistryBuilder { /// Creates a new RegistryBuilder pub fn new() -> Self { Registry { RegistryBuilder { providers: HashMap::new(), } } Loading @@ -36,23 +50,55 @@ impl Registry { /// Registers a module with this registry pub fn register_module<F>(&mut self, init: F) where F: Fn(&mut Registry), F: Fn(&mut Self), { init(self); } /// Registers a provider function with this registry pub fn register_provider<T: 'static>( &mut self, f: Box<dyn Fn(Arc<Registry>) -> Pin<Box<dyn Future<Output = Box<dyn Any>>>>>, ) { self.providers.insert(TypeId::of::<T>(), Provider { f }); pub fn register_provider<T: 'static>(&mut self, f: ProviderFnBox) { self.providers .insert(TypeId::of::<T>(), Provider { f: Arc::new(f) }); } /// Construct the Registry from this builder pub fn build(self) -> Registry { Registry { providers: Arc::new(Mutex::new(self.providers)), instances: Arc::new(Mutex::new(HashMap::new())), } } } impl Registry { /// Gets an instance of a type, implicitly starting any dependencies if necessary pub async fn get<T: 'static + Clone>(self: &Arc<Self>) -> T { let provider = &self.providers[&TypeId::of::<T>()]; pub async fn get<T: 'static + Clone + Send + Sync>(self: &Arc<Self>) -> T { let typeid = TypeId::of::<T>(); { let instances = self.instances.lock().await; if let Some(value) = instances.get(&typeid) { return value .downcast_ref::<T>() .expect("was not correct type") .clone(); } } let casted = { let provider = { self.providers.lock().await[&typeid].clone() }; let result = (provider.f)(self.clone()).await; *result.downcast::<T>().expect("was not correct type") (*result.downcast::<T>().expect("was not correct type")).clone() }; let mut instances = self.instances.lock().await; instances.insert(typeid, Box::new(casted.clone())); casted } /// Inject an already created instance of T. Useful for config. pub async fn inject<T: 'static + Clone + Send + Sync>(self: &Arc<Self>, obj: T) { let mut instances = self.instances.lock().await; instances.insert(TypeId::of::<T>(), Box::new(obj)); } }