1use crate::bind_node_set::BindNodeSet;
6use async_trait::async_trait;
7use driver_manager_node::Node;
8use driver_manager_types::{BindResult, BindResultTracker, NodeType};
9use futures::StreamExt;
10use futures::channel::{mpsc, oneshot};
11use log::{error, warn};
12use std::cell::RefCell;
13use std::rc::{Rc, Weak};
14use {
15 fidl_fuchsia_driver_development as fdd, fidl_fuchsia_driver_framework as fdf,
16 fidl_fuchsia_driver_index as fdi, fuchsia_async as fasync,
17};
18
19pub type NodeBindingInfoResultCompleter = oneshot::Sender<Vec<fdd::NodeBindingInfo>>;
20
21pub struct CompositeNodeAndDriver {
22 pub driver: fdf::CompositeDriverInfo,
23 pub node: Weak<Node>,
24}
25
26pub struct BindSpecResult {
27 pub bound_composite_parents: Vec<fdf::CompositeParent>,
28 pub completed_node_and_drivers: Vec<CompositeNodeAndDriver>,
29}
30
31#[derive(Debug)]
32pub struct BindRequest {
33 node_moniker: String,
34 node: Weak<Node>,
35 driver_url_suffix: String,
36 tracker: Rc<RefCell<BindResultTracker>>,
37 composite_only: bool,
38}
39
40#[async_trait(?Send)]
41pub trait BindManagerBridge {
42 fn box_clone(&self) -> Box<dyn BindManagerBridge>;
43 fn on_binding_state_changed(&self);
44 async fn request_match_from_driver_index(
45 &self,
46 args: fdi::MatchDriverArgs,
47 ) -> fidl::Result<fdi::MatchDriverResult>;
48 async fn start_driver(
49 &self,
50 node: &Rc<Node>,
51 driver_info: fdf::DriverInfo,
52 ) -> Result<String, zx::Status>;
53 fn bind_to_parent_spec(
54 &self,
55 parents: &[fdf::CompositeParent],
56 node: Weak<Node>,
57 enable_multibind: bool,
58 ) -> Result<BindSpecResult, zx::Status>;
59}
60
61pub struct BindManager {
62 bridge: Box<dyn BindManagerBridge>,
63 bind_node_set: RefCell<BindNodeSet>,
64 pending_bind_requests: RefCell<Vec<BindRequest>>,
65 pending_orphan_rebind_completers: RefCell<Vec<NodeBindingInfoResultCompleter>>,
66 weak_self: Weak<Self>,
67 scope: fasync::Scope,
68}
69
70#[derive(Clone)]
74pub struct BindManagerHandle(Rc<BindManager>);
75
76impl BindManager {
77 pub fn new(bridge: Box<dyn BindManagerBridge>) -> Rc<Self> {
78 Rc::new_cyclic(|weak_self| {
79 let mut bind_node_set = BindNodeSet::new();
80 let (sender, mut receiver) = mpsc::unbounded();
81 bind_node_set.set_on_bind_state_changed(sender);
82
83 let scope = fasync::Scope::new_with_name("bind_manager");
84 let bridge_clone = bridge.box_clone();
85 scope.spawn_local(async move {
86 while let Some(()) = receiver.next().await {
87 bridge_clone.on_binding_state_changed();
88 }
89 });
90
91 Self {
92 bridge,
93 bind_node_set: RefCell::new(bind_node_set),
94 pending_bind_requests: RefCell::new(Vec::new()),
95 pending_orphan_rebind_completers: RefCell::new(Vec::new()),
96 weak_self: weak_self.clone(),
97 scope,
98 }
99 })
100 }
101
102 pub fn bind(
103 &self,
104 node: &Rc<Node>,
105 driver_url_suffix: &str,
106 tracker: Rc<RefCell<BindResultTracker>>,
107 ) {
108 let request = BindRequest {
109 node_moniker: node.make_component_moniker(),
110 node: Rc::downgrade(node),
111 driver_url_suffix: driver_url_suffix.to_string(),
112 tracker,
113 composite_only: false,
114 };
115
116 if self.bind_node_set.borrow().is_bind_ongoing() {
117 self.pending_bind_requests.borrow_mut().push(request);
118 return;
119 }
120
121 self.bind_node_set.borrow_mut().remove_orphaned_node(&node.make_component_moniker());
122 self.bind_node_set.borrow_mut().start_next_bind_process();
123
124 let weak_self = self.weak_self.clone();
125 self.scope.spawn_local(async move {
126 if let Some(this) = weak_self.upgrade() {
127 this.bind_internal(request).await;
128 this.process_pending_bind_requests();
129 }
130 });
131 }
132
133 pub async fn try_bind_all_available(&self) -> Vec<fdd::NodeBindingInfo> {
134 if self.bind_node_set.borrow().is_bind_ongoing() {
135 let (tx, rx) = oneshot::channel();
136 self.pending_orphan_rebind_completers.borrow_mut().push(tx);
137 return rx.await.unwrap_or_default();
138 }
139
140 if self.bind_node_set.borrow().num_of_available_nodes() == 0 {
141 return vec![];
142 }
143
144 self.bind_node_set.borrow_mut().start_next_bind_process();
145
146 let (tx, rx) = oneshot::channel();
147 let tracker = Rc::new(RefCell::new(BindResultTracker::new(
148 self.bind_node_set.borrow().num_of_available_nodes(),
149 tx,
150 )));
151
152 self.try_bind_all_available_internal(tracker).await;
153 let results = rx.await.unwrap_or_default();
154 self.process_pending_bind_requests();
155 results
156 }
157
158 async fn bind_internal(&self, request: BindRequest) {
159 assert!(self.bind_node_set.borrow().is_bind_ongoing());
160 let node = match request.node.upgrade() {
161 Some(node) => node,
162 None => {
163 warn!("Node was freed before bind request is processed. {}", request.node_moniker);
164 request.tracker.borrow_mut().report_no_bind();
165 return;
166 }
167 };
168
169 let mut args =
170 fdi::MatchDriverArgs { name: Some(node.name().to_string()), ..Default::default() };
171
172 if *node.node_type() == NodeType::Normal
173 && let Some(props) = node.get_node_properties(None)
174 {
175 args.properties = Some(props);
176 }
177
178 if !request.driver_url_suffix.is_empty() {
179 args.driver_url_suffix = Some(request.driver_url_suffix.clone());
180 }
181
182 let result = self.bridge.request_match_from_driver_index(args).await;
183
184 let node = match request.node.upgrade() {
185 Some(node) => node,
186 None => {
187 warn!("Node was freed before it could be bound");
188 request.tracker.borrow_mut().report_no_bind();
189 return;
190 }
191 };
192
193 let bind_result =
194 self.bind_node_to_result(&node, request.composite_only, result, true).await;
195
196 let node_moniker = node.make_component_moniker();
197
198 if !bind_result.is_bound()
199 && !request.composite_only
200 && !self.bind_node_set.borrow().multibind_contains(&node_moniker)
201 {
202 self.bind_node_set.borrow_mut().add_orphaned_node(&node);
203 } else {
204 self.bind_node_set.borrow_mut().remove_orphaned_node(&node_moniker);
205 }
206
207 if bind_result.is_bound() {
208 if let Some(url) = bind_result.driver_url() {
209 request.tracker.borrow_mut().report_successful_bind_driver(&node_moniker, url);
210 } else if let Some(parents) = bind_result.composite_parents() {
211 request
212 .tracker
213 .borrow_mut()
214 .report_successful_bind_composite(&node_moniker, parents);
215 } else {
216 error!("Unknown bind result type for {}.", node_moniker);
217 request.tracker.borrow_mut().report_no_bind();
218 }
219 } else {
220 request.tracker.borrow_mut().report_no_bind();
221 }
222 }
223
224 async fn bind_node_to_result(
225 &self,
226 node: &Rc<Node>,
227 composite_only: bool,
228 result: fidl::Result<fdi::MatchDriverResult>,
229 has_tracker: bool,
230 ) -> BindResult {
231 let matched_driver = match result {
232 Ok(res) => res,
233 Err(e) => {
234 if let fidl::Error::ClientChannelClosed { status, .. } = e {
235 if status != zx::Status::NOT_FOUND || !has_tracker {
236 warn!(
237 "Failed to match Node '{}': {}",
238 node.make_component_moniker(),
239 status
240 );
241 }
242 } else {
243 error!("Failed to call match Node '{}': {}", node.name(), e);
244 }
245 return BindResult::NotBound;
246 }
247 };
248
249 match matched_driver {
250 fdi::MatchDriverResult::Driver(driver_info) => {
251 if composite_only
252 || self
253 .bind_node_set
254 .borrow()
255 .multibind_contains(&node.make_component_moniker())
256 {
257 return BindResult::NotBound;
258 }
259 match self.bridge.start_driver(node, driver_info).await {
260 Ok(url) => BindResult::Driver(url),
261 Err(e) => {
262 error!("Failed to start driver '{}': {}", node.name(), e);
263 BindResult::NotBound
264 }
265 }
266 }
267 fdi::MatchDriverResult::CompositeParents(parents) => {
268 match self.bind_node_to_spec(node, &parents).await {
269 Ok(bound_parents) => BindResult::Composite(bound_parents),
270 Err(_) => BindResult::NotBound,
271 }
272 }
273 _ => {
274 warn!("Unknown MatchDriverResult variant");
275 BindResult::NotBound
276 }
277 }
278 }
279
280 async fn bind_node_to_spec(
281 &self,
282 node: &Rc<Node>,
283 parents: &[fdf::CompositeParent],
284 ) -> Result<Vec<fdf::CompositeParent>, zx::Status> {
285 if node.can_multibind_composites {
286 self.bind_node_set.borrow_mut().add_or_move_multibind_node(node);
287 }
288
289 let result = self.bridge.bind_to_parent_spec(
290 parents,
291 Rc::downgrade(node),
292 node.can_multibind_composites,
293 );
294 if let Err(e) = &result {
295 if *e != zx::Status::NOT_FOUND {
296 error!("Failed to bind node '{}' to any of the matched parent specs.", node.name());
297 }
298 node.on_match_error(*e);
299 return result.map(|_| vec![]);
300 }
301 let result = result?;
302
303 for composite in result.completed_node_and_drivers {
304 let composite_node = composite.node.upgrade().expect("Composite node freed before use");
305 if let Err(e) = self
306 .bridge
307 .start_driver(&composite_node, composite.driver.driver_info.unwrap())
308 .await
309 {
310 error!("Failed to start driver '{}': {}", node.name(), e);
311 }
312 }
313
314 Ok(result.bound_composite_parents)
315 }
316
317 async fn try_bind_all_available_internal(&self, tracker: Rc<RefCell<BindResultTracker>>) {
318 assert!(self.bind_node_set.borrow().is_bind_ongoing());
319 if self.bind_node_set.borrow().num_of_available_nodes() == 0 {
320 return;
321 }
322
323 let multibind_nodes: Vec<_> =
324 self.bind_node_set.borrow().current_multibind_nodes().into_values().collect();
325 for node_weak in multibind_nodes {
326 let request = BindRequest {
327 node_moniker: node_weak.upgrade().unwrap().make_component_moniker(),
328 node: node_weak.clone(),
329 driver_url_suffix: "".to_string(),
330 tracker: tracker.clone(),
331 composite_only: true,
332 };
333 self.bind_internal(request).await;
334 }
335
336 let orphaned_nodes: Vec<_> =
337 self.bind_node_set.borrow().current_orphaned_nodes().into_values().collect();
338 for node_weak in orphaned_nodes {
339 let request = BindRequest {
340 node_moniker: node_weak.upgrade().unwrap().make_component_moniker(),
341 node: node_weak.clone(),
342 driver_url_suffix: "".to_string(),
343 tracker: tracker.clone(),
344 composite_only: false,
345 };
346 self.bind_internal(request).await;
347 }
348 }
349
350 pub fn record_inspect(&self, root: &fuchsia_inspect::Node) {
351 root.record_child("orphan_nodes", |orphans| {
352 let mut i = 0;
353 for (moniker, node_weak) in self.bind_node_set.borrow().current_orphaned_nodes() {
354 if node_weak.upgrade().is_some() {
355 orphans.record_child(format!("orphan-{}", i), |orphan| {
356 orphan.record_string("moniker", moniker);
357 });
358 i += 1;
359 }
360 }
361
362 orphans.record_bool("bind_all_ongoing", self.bind_node_set.borrow().is_bind_ongoing());
363 orphans.record_uint(
364 "pending_bind_requests",
365 self.pending_bind_requests.borrow().len() as u64,
366 );
367 orphans.record_uint(
368 "pending_orphan_rebind_callbacks",
369 self.pending_orphan_rebind_completers.borrow().len() as u64,
370 );
371 });
372 }
373
374 pub fn process_pending_bind_requests(&self) {
375 assert!(self.bind_node_set.borrow().is_bind_ongoing());
376 if self.pending_bind_requests.borrow().is_empty()
377 && self.pending_orphan_rebind_completers.borrow().is_empty()
378 {
379 self.bind_node_set.borrow_mut().end_bind_process();
380 return;
381 }
382
383 for request in self.pending_bind_requests.borrow().iter() {
384 if let Some(node) = request.node.upgrade() {
385 self.bind_node_set
386 .borrow_mut()
387 .remove_orphaned_node(&node.make_component_moniker());
388 }
389 }
390
391 self.bind_node_set.borrow_mut().start_next_bind_process();
392
393 let have_bind_all_orphans_request =
394 !self.pending_orphan_rebind_completers.borrow().is_empty();
395 let bind_tracker_size = if have_bind_all_orphans_request {
396 self.pending_bind_requests.borrow().len()
397 + self.bind_node_set.borrow().num_of_available_nodes()
398 } else {
399 self.pending_bind_requests.borrow().len()
400 };
401
402 if have_bind_all_orphans_request && bind_tracker_size == 0 {
403 for sender in std::mem::take(&mut *self.pending_orphan_rebind_completers.borrow_mut()) {
404 let _ = sender.send(vec![]);
405 }
406 self.bind_node_set.borrow_mut().end_bind_process();
407 return;
408 }
409
410 let (tx, rx) = oneshot::channel::<Vec<fdd::NodeBindingInfo>>();
411 let weak_self = self.weak_self.clone();
412 let completers = std::mem::take(&mut *self.pending_orphan_rebind_completers.borrow_mut());
413 self.scope.spawn_local(async move {
414 let results = rx.await.unwrap_or_default();
415 for completer in completers {
416 let _ = completer.send(results.clone());
417 }
418 if let Some(this) = weak_self.upgrade() {
419 this.process_pending_bind_requests();
420 }
421 });
422
423 let tracker = Rc::new(RefCell::new(BindResultTracker::new(bind_tracker_size, tx)));
424
425 let pending_bind = std::mem::take(&mut *self.pending_bind_requests.borrow_mut());
426 let weak_self = self.weak_self.clone();
427 self.scope.spawn_local(async move {
428 if let Some(this) = weak_self.upgrade() {
429 for request in pending_bind {
430 this.bind_internal(request).await;
431 }
432
433 if have_bind_all_orphans_request {
434 this.try_bind_all_available_internal(tracker).await;
435 }
436 }
437 });
438 }
439}
440
441impl BindManagerHandle {
442 pub fn new(bridge: Box<dyn BindManagerBridge>) -> Self {
443 Self(BindManager::new(bridge))
444 }
445
446 pub fn has_ongoing_bind(&self) -> bool {
447 self.0.bind_node_set.borrow().is_bind_ongoing()
448 }
449
450 pub fn bind(
451 &self,
452 node: &Rc<Node>,
453 driver_url_suffix: &str,
454 tracker: Rc<RefCell<BindResultTracker>>,
455 ) {
456 self.0.bind(node, driver_url_suffix, tracker);
457 }
458
459 pub async fn try_bind_all_available(&self) -> Vec<fdd::NodeBindingInfo> {
460 self.0.try_bind_all_available().await
461 }
462
463 pub fn record_inspect(&self, root: &fuchsia_inspect::Node) {
464 self.0.record_inspect(root);
465 }
466}