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