Skip to main content

driver_manager_core/
trait_impls.rs

1// Copyright 2026 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::{DriverRunner, DriverRunnerBridge};
6use async_trait::async_trait;
7use driver_manager_bind::{BindManagerBridge, BindSpecResult};
8use driver_manager_composite::CompositeManagerBridge;
9use driver_manager_driver_host::DriverHost;
10use driver_manager_node::{Node, NodeManager};
11use driver_manager_shutdown::{NodeRemover, RemovalSet};
12use driver_manager_types::BindResultTracker;
13use driver_manager_utils::DictionaryUtil;
14use fidl::endpoints::DiscoverableProtocolMarker;
15use futures::channel::oneshot;
16use log::info;
17use rand::rngs::StdRng;
18use std::cell::RefCell;
19use std::rc::{Rc, Weak};
20use {fidl_fuchsia_driver_framework as fdf, fidl_fuchsia_driver_index as fdi};
21
22#[async_trait(?Send)]
23impl NodeRemover for DriverRunner {
24    async fn shutdown_all_drivers(&self) {
25        info!("Driver Runner invokes shutdown all drivers");
26        let (tx, rx) = oneshot::channel();
27        self.removal_tracker.borrow_mut().set_all_callback(tx);
28        self.root_node.remove(RemovalSet::All, Some(Rc::downgrade(&self.removal_tracker)));
29        self.removal_tracker.borrow_mut().finish_enumeration(Rc::downgrade(&self.removal_tracker));
30        let _ = rx.await;
31    }
32
33    async fn shutdown_pkg_drivers(&self) {
34        let (tx, rx) = oneshot::channel();
35        self.removal_tracker.borrow_mut().set_pkg_callback(tx);
36        self.root_node.remove(RemovalSet::Package, Some(Rc::downgrade(&self.removal_tracker)));
37        self.removal_tracker.borrow_mut().finish_enumeration(Rc::downgrade(&self.removal_tracker));
38        let _ = rx.await;
39    }
40
41    fn set_on_removal_timeout_callback(&self, callback: Box<dyn Fn()>) {
42        self.removal_tracker.borrow_mut().set_on_removal_timeout_callback(callback);
43    }
44}
45
46#[async_trait(?Send)]
47impl NodeManager for DriverRunnerBridge {
48    fn clone_box(&self) -> Box<dyn NodeManager> {
49        Box::new(DriverRunnerBridge(self.0.clone()))
50    }
51
52    fn bind(&self, node: &Rc<Node>, tracker: Rc<RefCell<BindResultTracker>>) {
53        if let Some(runner) = self.0.upgrade() {
54            runner.bind_manager.bind(node, "", tracker);
55        }
56    }
57
58    fn bind_to_url(
59        &self,
60        node: &Rc<Node>,
61        driver_url_suffix: &str,
62        tracker: Rc<RefCell<BindResultTracker>>,
63    ) {
64        if let Some(runner) = self.0.upgrade() {
65            runner.bind_manager.bind(node, driver_url_suffix, tracker);
66        }
67    }
68
69    fn start_driver(
70        &self,
71        node: &Rc<Node>,
72        url: &str,
73        package_type: fdf::DriverPackageType,
74    ) -> Result<(), zx::Status> {
75        if let Some(runner) = self.0.upgrade() {
76            let node_clone = node.clone();
77            let url_clone = url.to_string();
78            let runner_clone = runner.clone();
79
80            // Schedule the start logic to run later, which helps keep the scope under driver runner
81            // as opposed to the node calling this.
82            runner.scope.spawn_local(async move {
83                let _ = runner_clone.start_driver(&node_clone, &url_clone, package_type).await;
84            });
85            Ok(())
86        } else {
87            Err(zx::Status::UNAVAILABLE)
88        }
89    }
90
91    fn get_driver_host(&self, driver_host_name_for_colocation: &str) -> Option<Rc<dyn DriverHost>> {
92        let runner = self.0.upgrade()?;
93        runner.get_driver_host(driver_host_name_for_colocation)
94    }
95
96    async fn create_driver_host(
97        &self,
98        use_next_vdso: bool,
99        driver_host_name_for_colocation: String,
100    ) -> Result<Rc<dyn DriverHost>, zx::Status> {
101        if let Some(runner) = self.0.upgrade() {
102            runner.create_driver_host(use_next_vdso, driver_host_name_for_colocation).await
103        } else {
104            Err(zx::Status::UNAVAILABLE)
105        }
106    }
107
108    async fn create_driver_host_dynamic_linker(
109        &self,
110        driver_host_name_for_colocation: String,
111    ) -> Result<Rc<dyn DriverHost>, zx::Status> {
112        if let Some(runner) = self.0.upgrade() {
113            runner.create_driver_host_dynamic_linker(driver_host_name_for_colocation).await
114        } else {
115            Err(zx::Status::UNAVAILABLE)
116        }
117    }
118
119    async fn destroy_driver_host(
120        &self,
121        driver_host_name_for_colocation: String,
122    ) -> Result<(), zx::Status> {
123        if let Some(runner) = self.0.upgrade() {
124            runner.destroy_driver_host(driver_host_name_for_colocation).await
125        } else {
126            Err(zx::Status::UNAVAILABLE)
127        }
128    }
129
130    fn is_test_shutdown_delay_enabled(&self) -> bool {
131        if let Some(runner) = self.0.upgrade() { runner.enable_test_shutdown_delays } else { false }
132    }
133
134    fn get_shutdown_test_rng(&self) -> Weak<RefCell<StdRng>> {
135        if let Some(runner) = self.0.upgrade() {
136            Rc::downgrade(&runner.shutdown_test_rng)
137        } else {
138            Weak::new()
139        }
140    }
141
142    async fn wait_for_bootup(&self) {
143        if let Some(runner) = self.0.upgrade() {
144            runner.bootup_tracker.wait_for_bootup().await;
145        }
146    }
147
148    fn get_dictionary_util(&self) -> Result<Rc<DictionaryUtil>, zx::Status> {
149        if let Some(runner) = self.0.upgrade() {
150            Ok(runner.dictionary_util.clone())
151        } else {
152            Err(zx::Status::UNAVAILABLE)
153        }
154    }
155
156    fn memory_attributor(&self) -> Option<Rc<dyn driver_manager_node::MemoryAttributor>> {
157        let runner = self.0.upgrade()?;
158        Some(runner.memory_attributor.clone())
159    }
160}
161
162#[async_trait(?Send)]
163impl BindManagerBridge for DriverRunnerBridge {
164    fn box_clone(&self) -> Box<dyn BindManagerBridge> {
165        Box::new(Self(self.0.clone()))
166    }
167
168    fn on_binding_state_changed(&self) {
169        if let Some(runner) = self.0.upgrade() {
170            runner.bootup_tracker.notify_binding_changed();
171        }
172    }
173
174    async fn request_match_from_driver_index(
175        &self,
176        args: fidl_fuchsia_driver_index::MatchDriverArgs,
177    ) -> fidl::Result<fdi::MatchDriverResult> {
178        if let Some(runner) = self.0.upgrade() {
179            match runner.driver_index.match_driver(&args).await {
180                Ok(Ok(result)) => Ok(result),
181                Ok(Err(e)) => Err(fidl::Error::ClientChannelClosed {
182                    status: zx::Status::from_raw(e),
183                    protocol_name: fdi::DriverIndexMarker::PROTOCOL_NAME,
184                    epitaph: None,
185                }),
186                Err(e) => Err(e),
187            }
188        } else {
189            Err(fidl::Error::ClientChannelClosed {
190                status: zx::Status::UNAVAILABLE,
191                protocol_name: fdi::DriverIndexMarker::PROTOCOL_NAME,
192                epitaph: None,
193            })
194        }
195    }
196
197    async fn start_driver(
198        &self,
199        node: &Rc<Node>,
200        driver_info: fidl_fuchsia_driver_framework::DriverInfo,
201    ) -> Result<String, zx::Status> {
202        if let Some(runner) = self.0.upgrade() {
203            let url = driver_info.url.clone().ok_or(zx::Status::INVALID_ARGS)?;
204            let package_type = driver_info.package_type.unwrap_or(fdf::DriverPackageType::Base);
205
206            let node_clone = node.clone();
207            let url_clone = url.clone();
208            let runner_clone = runner.clone();
209
210            // Schedule the start logic to run later, this is because the bind manager reports
211            // matching success/failure after calling this function, so we don't want it to report
212            // on actual driver start results, as we report that inside start_driver.
213            runner.scope.spawn_local(async move {
214                let _ = runner_clone.start_driver(&node_clone, &url_clone, package_type).await;
215            });
216            Ok(url)
217        } else {
218            Err(zx::Status::UNAVAILABLE)
219        }
220    }
221
222    fn bind_to_parent_spec(
223        &self,
224        parents: &[fdf::CompositeParent],
225        node: Weak<Node>,
226        enable_multibind: bool,
227    ) -> Result<BindSpecResult, zx::Status> {
228        if let Some(runner) = self.0.upgrade() {
229            runner.composite_node_spec_manager.bind_parent_spec(parents, node, enable_multibind)
230        } else {
231            Err(zx::Status::UNAVAILABLE)
232        }
233    }
234}
235
236#[async_trait(?Send)]
237impl CompositeManagerBridge for DriverRunnerBridge {
238    fn box_clone(&self) -> Box<dyn CompositeManagerBridge> {
239        Box::new(Self(self.0.clone()))
240    }
241
242    async fn bind_nodes_for_composite_node_spec(&self) {
243        if let Some(runner) = self.0.upgrade() {
244            let _ = runner.bind_manager.try_bind_all_available().await;
245        }
246    }
247
248    async fn add_spec_to_driver_index(
249        &self,
250        spec: fidl_fuchsia_driver_framework::CompositeNodeSpec,
251    ) -> Result<(), zx::Status> {
252        if let Some(runner) = self.0.upgrade() {
253            runner
254                .driver_index
255                .add_composite_node_spec(&spec)
256                .await
257                .map_err(|_| zx::Status::INTERNAL)?
258                .map_err(zx::Status::from_raw)
259        } else {
260            Err(zx::Status::INTERNAL)
261        }
262    }
263
264    async fn request_rebind_from_driver_index(
265        &self,
266        spec: String,
267        driver_url_suffix: Option<String>,
268    ) -> Result<(), zx::Status> {
269        if let Some(runner) = self.0.upgrade() {
270            runner
271                .driver_index
272                .rebind_composite_node_spec(&spec, driver_url_suffix.as_deref())
273                .await
274                .map_err(|_| zx::Status::INTERNAL)?
275                .map_err(zx::Status::from_raw)
276        } else {
277            Err(zx::Status::INTERNAL)
278        }
279    }
280}