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    fn is_test_shutdown_delay_enabled(&self) -> bool {
120        if let Some(runner) = self.0.upgrade() { runner.enable_test_shutdown_delays } else { false }
121    }
122
123    fn get_shutdown_test_rng(&self) -> Weak<RefCell<StdRng>> {
124        if let Some(runner) = self.0.upgrade() {
125            Rc::downgrade(&runner.shutdown_test_rng)
126        } else {
127            Weak::new()
128        }
129    }
130
131    async fn wait_for_bootup(&self) {
132        if let Some(runner) = self.0.upgrade() {
133            runner.bootup_tracker.wait_for_bootup().await;
134        }
135    }
136
137    fn get_dictionary_util(&self) -> Result<Rc<DictionaryUtil>, zx::Status> {
138        if let Some(runner) = self.0.upgrade() {
139            Ok(runner.dictionary_util.clone())
140        } else {
141            Err(zx::Status::UNAVAILABLE)
142        }
143    }
144
145    fn memory_attributor(&self) -> Option<Rc<dyn driver_manager_node::MemoryAttributor>> {
146        let runner = self.0.upgrade()?;
147        Some(runner.memory_attributor.clone())
148    }
149}
150
151#[async_trait(?Send)]
152impl BindManagerBridge for DriverRunnerBridge {
153    fn box_clone(&self) -> Box<dyn BindManagerBridge> {
154        Box::new(Self(self.0.clone()))
155    }
156
157    fn on_binding_state_changed(&self) {
158        if let Some(runner) = self.0.upgrade() {
159            runner.bootup_tracker.notify_binding_changed();
160        }
161    }
162
163    async fn request_match_from_driver_index(
164        &self,
165        args: fidl_fuchsia_driver_index::MatchDriverArgs,
166    ) -> fidl::Result<fdi::MatchDriverResult> {
167        if let Some(runner) = self.0.upgrade() {
168            match runner.driver_index.match_driver(&args).await {
169                Ok(Ok(result)) => Ok(result),
170                Ok(Err(e)) => Err(fidl::Error::ClientChannelClosed {
171                    status: zx::Status::from_raw(e),
172                    protocol_name: fdi::DriverIndexMarker::PROTOCOL_NAME,
173                    epitaph: None,
174                }),
175                Err(e) => Err(e),
176            }
177        } else {
178            Err(fidl::Error::ClientChannelClosed {
179                status: zx::Status::UNAVAILABLE,
180                protocol_name: fdi::DriverIndexMarker::PROTOCOL_NAME,
181                epitaph: None,
182            })
183        }
184    }
185
186    async fn start_driver(
187        &self,
188        node: &Rc<Node>,
189        driver_info: fidl_fuchsia_driver_framework::DriverInfo,
190    ) -> Result<String, zx::Status> {
191        if let Some(runner) = self.0.upgrade() {
192            let url = driver_info.url.clone().ok_or(zx::Status::INVALID_ARGS)?;
193            let package_type = driver_info.package_type.unwrap_or(fdf::DriverPackageType::Base);
194
195            let node_clone = node.clone();
196            let url_clone = url.clone();
197            let runner_clone = runner.clone();
198
199            // Schedule the start logic to run later, this is because the bind manager reports
200            // matching success/failure after calling this function, so we don't want it to report
201            // on actual driver start results, as we report that inside start_driver.
202            runner.scope.spawn_local(async move {
203                let _ = runner_clone.start_driver(&node_clone, &url_clone, package_type).await;
204            });
205            Ok(url)
206        } else {
207            Err(zx::Status::UNAVAILABLE)
208        }
209    }
210
211    fn bind_to_parent_spec(
212        &self,
213        parents: &[fdf::CompositeParent],
214        node: Weak<Node>,
215        enable_multibind: bool,
216    ) -> Result<BindSpecResult, zx::Status> {
217        if let Some(runner) = self.0.upgrade() {
218            runner.composite_node_spec_manager.bind_parent_spec(parents, node, enable_multibind)
219        } else {
220            Err(zx::Status::UNAVAILABLE)
221        }
222    }
223}
224
225#[async_trait(?Send)]
226impl CompositeManagerBridge for DriverRunnerBridge {
227    fn box_clone(&self) -> Box<dyn CompositeManagerBridge> {
228        Box::new(Self(self.0.clone()))
229    }
230
231    async fn bind_nodes_for_composite_node_spec(&self) {
232        if let Some(runner) = self.0.upgrade() {
233            let _ = runner.bind_manager.try_bind_all_available().await;
234        }
235    }
236
237    async fn add_spec_to_driver_index(
238        &self,
239        spec: fidl_fuchsia_driver_framework::CompositeNodeSpec,
240    ) -> Result<(), zx::Status> {
241        if let Some(runner) = self.0.upgrade() {
242            runner
243                .driver_index
244                .add_composite_node_spec(&spec)
245                .await
246                .map_err(|_| zx::Status::INTERNAL)?
247                .map_err(zx::Status::from_raw)
248        } else {
249            Err(zx::Status::INTERNAL)
250        }
251    }
252
253    async fn request_rebind_from_driver_index(
254        &self,
255        spec: String,
256        driver_url_suffix: Option<String>,
257    ) -> Result<(), zx::Status> {
258        if let Some(runner) = self.0.upgrade() {
259            runner
260                .driver_index
261                .rebind_composite_node_spec(&spec, driver_url_suffix.as_deref())
262                .await
263                .map_err(|_| zx::Status::INTERNAL)?
264                .map_err(zx::Status::from_raw)
265        } else {
266            Err(zx::Status::INTERNAL)
267        }
268    }
269}