Skip to main content

driver_manager_core/
lib.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 driver_manager_node::Node;
6use driver_manager_types::Collection;
7use fidl::endpoints::ClientEnd;
8use futures::channel::{mpsc, oneshot};
9use log::warn;
10use std::collections::{HashSet, VecDeque};
11use std::rc::{Rc, Weak};
12use {fidl_fuchsia_driver_framework as fdf, fidl_fuchsia_ldsvc as fldsvc};
13
14mod bootup_tracker;
15mod driver_host_runner;
16mod driver_runner;
17mod memory_attribution;
18mod offer_injection;
19mod runner;
20mod trait_impls;
21
22pub use driver_runner::*;
23pub use offer_injection::*;
24
25// A helper struct to implement the bridge traits. It holds a weak reference to the DriverRunner
26// to avoid reference cycles.
27pub(crate) struct DriverRunnerBridge(Weak<DriverRunner>);
28
29pub(crate) type LoaderServiceFactory =
30    mpsc::UnboundedSender<oneshot::Sender<Result<ClientEnd<fldsvc::LoaderMarker>, zx::Status>>>;
31
32pub(crate) async fn perform_bfs<F>(starting_node: Rc<Node>, mut visitor: F)
33where
34    F: AsyncFnMut(&Rc<Node>) -> bool,
35{
36    let mut visited: HashSet<*const Node> = HashSet::new();
37    let mut node_queue = VecDeque::new();
38
39    visited.insert(Rc::as_ptr(&starting_node));
40    node_queue.push_back(starting_node);
41
42    while let Some(current) = node_queue.pop_front() {
43        let visit_children = visitor(&current).await;
44        if !visit_children {
45            continue;
46        }
47
48        for child in current.children() {
49            let Some(primary_parent) = child.get_primary_parent() else {
50                continue;
51            };
52            if !Rc::ptr_eq(&primary_parent, &current) {
53                continue;
54            }
55
56            if visited.insert(Rc::as_ptr(&child)) {
57                node_queue.push_back(child);
58            }
59        }
60    }
61}
62
63pub(crate) fn to_collection(node: &Node, package_type: fdf::DriverPackageType) -> Collection {
64    let collection = to_collection_internal(package_type);
65    get_highest_ranking_collection(node, collection)
66}
67
68fn to_collection_internal(package_type: fdf::DriverPackageType) -> Collection {
69    match package_type {
70        fdf::DriverPackageType::Boot => Collection::Boot,
71        fdf::DriverPackageType::Base => Collection::Package,
72        fdf::DriverPackageType::Cached | fdf::DriverPackageType::Universe => {
73            Collection::FullPackage
74        }
75        _ => Collection::None,
76    }
77}
78
79fn get_highest_ranking_collection(node: &Node, mut collection: Collection) -> Collection {
80    let mut ancestors = std::collections::VecDeque::new();
81    for parent in node.parents() {
82        ancestors.push_back(parent);
83    }
84
85    while let Some(ancestor_weak) = ancestors.pop_front() {
86        if let Some(ancestor) = ancestor_weak.upgrade() {
87            let ancestor_collection = ancestor.collection();
88            if ancestor_collection == Collection::None {
89                for parent in ancestor.parents() {
90                    ancestors.push_back(parent);
91                }
92            } else if ancestor_collection > collection {
93                collection = ancestor_collection;
94            }
95        } else {
96            warn!("Ancestor node released");
97        }
98    }
99    collection
100}