Skip to main content

driver_manager_node/
binding.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::node::Node;
6use crate::types::NodeState;
7use driver_manager_shutdown::{RemovalSet, ShutdownIntent};
8use driver_manager_types::{BindResultTracker, ShutdownState};
9use futures::channel::oneshot;
10use log::{error, warn};
11use std::cell::RefCell;
12use std::rc::Rc;
13use {fidl_fuchsia_driver_development as fdd, fidl_fuchsia_driver_framework as fdf};
14
15impl Node {
16    pub async fn complete_bind(self: &Rc<Self>, result: Result<(), zx::Status>) {
17        if result.is_err() {
18            warn!("Bind failed for node '{}'", self.make_component_moniker());
19            if self.shutdown_state() == ShutdownState::Running && !self.is_unbound() {
20                warn!("Quarantining node '{}'", self.make_component_moniker());
21                self.quarantine_node().await;
22            } else {
23                self.set_state(NodeState::Unbound);
24            }
25        }
26
27        if self.is_running() {
28            self.on_bind();
29        }
30
31        let completer = self.take_pending_bind_completer();
32        if let Some(completer) = completer {
33            let _ = completer.send(result);
34        }
35
36        if let Err(status) = &result {
37            self.on_start_error(*status);
38        } else {
39            let completer = self.take_wait_for_driver_completer();
40            if let Some(completer) = completer {
41                if let Some(token) = self.token_handle() {
42                    let _ = completer.send(Ok(fdf::DriverResult::DriverStartedNodeToken(token)));
43                } else {
44                    let _ = completer.send(Err(zx::Status::INTERNAL));
45                }
46            }
47        }
48
49        self.node_shutdown_coordinator.borrow_mut().check_node_state();
50    }
51
52    pub(crate) fn wait_for_driver(
53        self: &Rc<Self>,
54        completer: oneshot::Sender<Result<fdf::DriverResult, zx::Status>>,
55    ) {
56        if let Some(token) = self.token_handle() {
57            let _ = completer.send(Ok(fdf::DriverResult::DriverStartedNodeToken(token)));
58            return;
59        }
60
61        if self.has_wait_for_driver_completer() {
62            let _ = completer.send(Err(zx::Status::ALREADY_EXISTS));
63            return;
64        }
65
66        self.set_wait_for_driver_completer(completer);
67
68        let node_clone = self.clone();
69        self.scope.spawn_local(async move {
70            node_clone.node_manager.wait_for_bootup().await;
71            let completer = node_clone.take_wait_for_driver_completer();
72            if let Some(completer) = completer {
73                if let Some(result) = node_clone.bind_error() {
74                    let response = match result {
75                        fdf::DriverResult::MatchError(s) => Ok(fdf::DriverResult::MatchError(s)),
76                        fdf::DriverResult::StartError(s) => Ok(fdf::DriverResult::StartError(s)),
77                        _ => Err(zx::Status::INTERNAL),
78                    };
79                    let _ = completer.send(response);
80                    return;
81                }
82
83                // Re-check running state
84                if let Some(token) = node_clone.token_handle() {
85                    let _ = completer.send(Ok(fdf::DriverResult::DriverStartedNodeToken(token)));
86                    return;
87                }
88
89                let _ = completer.send(Err(zx::Status::INTERNAL));
90            }
91        });
92    }
93
94    pub(crate) async fn bind(self: &Rc<Self>, driver: String) -> Result<(), zx::Status> {
95        self.bind_helper(false, Some(driver)).await
96    }
97
98    pub(crate) async fn bind_helper(
99        self: &Rc<Self>,
100        force_rebind: bool,
101        driver_url_suffix: Option<String>,
102    ) -> Result<(), zx::Status> {
103        if !force_rebind && self.is_bound() {
104            return Err(zx::Status::ALREADY_BOUND);
105        }
106
107        if self.has_pending_bind_completer() {
108            return Err(zx::Status::ALREADY_EXISTS);
109        }
110
111        let (tx, rx) = oneshot::channel();
112        if self.is_bound() {
113            self.restart_node_with_rematch(driver_url_suffix, tx);
114        } else {
115            self.set_pending_bind_completer(tx);
116            let tracker = self.create_bind_result_tracker(false);
117            if let Some(driver_url_suffix) = driver_url_suffix {
118                self.node_manager.bind_to_url(self, &driver_url_suffix, tracker);
119            } else {
120                self.node_manager.bind(self, tracker);
121            }
122        }
123        rx.await.map_err(|_| zx::Status::INTERNAL)?
124    }
125
126    pub(crate) fn create_bind_result_tracker(
127        self: &Rc<Self>,
128        silent: bool,
129    ) -> Rc<RefCell<BindResultTracker>> {
130        let weak_self = Rc::downgrade(self);
131        let (tx, rx) = oneshot::channel::<Vec<fdd::NodeBindingInfo>>();
132        self.scope.spawn_local(async move {
133            let Ok(info) = rx.await else {
134                return;
135            };
136            let Some(self_ptr) = weak_self.upgrade() else {
137                return;
138            };
139            if info.is_empty() {
140                self_ptr.set_state(NodeState::Unbound);
141                self_ptr.on_match_error(zx::Status::NOT_FOUND);
142                if !silent {
143                    self_ptr.complete_bind(Err(zx::Status::NOT_FOUND)).await;
144                }
145            } else if info.len() > 1 {
146                error!("Unexpectedly bound multiple drivers to a single node");
147                self_ptr.on_match_error(zx::Status::BAD_STATE);
148                if !silent {
149                    self_ptr.complete_bind(Err(zx::Status::BAD_STATE)).await;
150                }
151            }
152        });
153
154        Rc::new(RefCell::new(BindResultTracker::new(1, tx)))
155    }
156
157    pub(crate) async fn rebind(self: &Rc<Self>, driver: Option<String>) -> Result<(), zx::Status> {
158        let (tx, rx) = oneshot::channel();
159        self.restart_node_with_rematch(driver, tx);
160        rx.await.map_err(|_| zx::Status::INTERNAL)?
161    }
162
163    pub(crate) async fn unbind_children(self: &Rc<Self>) -> Result<(), zx::Status> {
164        let children = self.children();
165        if children.is_empty() {
166            return Ok(());
167        }
168
169        let rx = {
170            let (tx, rx) = oneshot::channel();
171            self.push_unbinding_children_completer(tx);
172            if self.unbinding_children_completers_len() == 1 {
173                for child in children {
174                    child.remove(RemovalSet::All, None);
175                }
176            }
177            rx
178        };
179        rx.await.map_err(|_| zx::Status::INTERNAL)?
180    }
181
182    pub(crate) fn schedule_unbind(self: &Rc<Self>) {
183        self.remove(RemovalSet::All, None);
184    }
185
186    pub fn restart_node_with_rematch(
187        self: &Rc<Self>,
188        restart_driver_url_suffix: Option<String>,
189        completer: oneshot::Sender<Result<(), zx::Status>>,
190    ) {
191        if self.has_pending_bind_completer() {
192            let _ = completer.send(Err(zx::Status::ALREADY_EXISTS));
193            return;
194        }
195
196        self.set_pending_bind_completer(completer);
197        if let Some(suffix) = restart_driver_url_suffix {
198            self.set_restart_driver_url_suffix(suffix);
199        }
200        self.restart_node();
201    }
202
203    pub fn restart_node(self: &Rc<Self>) {
204        self.node_shutdown_coordinator.borrow_mut().set_shutdown_intent(ShutdownIntent::Restart);
205        self.remove(RemovalSet::All, None);
206    }
207
208    pub(crate) async fn quarantine_node(self: &Rc<Self>) {
209        if !self.quarantine_start() {
210            panic!("QuarantineNode called from unexpected state");
211        }
212
213        self.node_shutdown_coordinator.borrow_mut().set_shutdown_intent(ShutdownIntent::Quarantine);
214        self.remove(RemovalSet::All, None);
215    }
216
217    fn on_bind(&self) {
218        if let Some(node_token) = self.token_handle() {
219            if let Some(controller_ref) = self.node_controller_ref() {
220                let event = fdf::NodeControllerOnBindRequest {
221                    node_token: Some(node_token.duplicate(zx::Rights::SAME_RIGHTS).unwrap()),
222                    ..Default::default()
223                };
224                if let Err(e) = controller_ref.send_on_bind(event) {
225                    error!("Failed to send OnBind event: {}", e);
226                }
227            }
228
229            let koid = self.token_koid().unwrap().raw_koid();
230            if let Some(driver_host) = self.driver_host() {
231                let node_manager = self.node_manager.clone_box();
232                self.scope.spawn_local(async move {
233                    if let Ok(process_koid) = driver_host.get_process_koid().await
234                        && let Some(attributor) = node_manager.memory_attributor()
235                    {
236                        attributor.add_driver(node_token, koid, process_koid);
237                    }
238                });
239            }
240        }
241    }
242}