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