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