1use crate::node::{Node, NodePropertyEntry};
6use crate::node_manager::NodeManager;
7use crate::shutdown::NodeBridge;
8use crate::types::{NodeDictionary, NodeState, NodeTypeVariant};
9use driver_manager_devfs::DevfsDevice;
10use driver_manager_shutdown::{NodeShutdownCoordinator, ShutdownIntent};
11use driver_manager_types::{Collection, NodeOffer, OfferTransport};
12use futures::channel::oneshot;
13use std::cell::RefCell;
14use std::rc::{Rc, Weak};
15use {
16 fidl_fuchsia_component_decl as fdecl, fidl_fuchsia_driver_framework as fdf,
17 fuchsia_async as fasync,
18};
19
20impl Node {
21 pub fn new_composite(
22 name: &str,
23 parents: Vec<Weak<Node>>,
24 parents_names: Vec<String>,
25 primary_index: u32,
26 node_manager: Box<dyn NodeManager>,
27 ) -> Rc<Self> {
28 let initial_host = parents[primary_index as usize].upgrade().and_then(|p| p.driver_host());
29
30 Rc::new_cyclic(|weak_self| {
31 let bridge = Box::new(NodeBridge::new(weak_self.clone()));
32 let enable_test_shutdown_delays = node_manager.is_test_shutdown_delay_enabled();
33 let shutdown_test_rng = node_manager.get_shutdown_test_rng();
34 Self {
35 name: name.to_string(),
36 node_manager,
37 core: RefCell::new(crate::node::NodeCore {
38 collection: Collection::None,
39 driver_package_type: fdf::DriverPackageType::Base,
40 node_type: NodeTypeVariant::Composite {
41 parents,
42 parents_names,
43 primary_index,
44 },
45 children: Vec::new(),
46 properties: Vec::new(),
47 symbols: Vec::new(),
48 offers: Vec::new(),
49 bus_info: None,
50 dictionary: NodeDictionary::None,
51 }),
52 state: RefCell::new(NodeState::Unbound),
53 devfs: RefCell::new(crate::node::NodeDevfs {
54 device: DevfsDevice::new(),
55 protocol_connector: None,
56 controller_allowlist_passthrough: None,
57 }),
58 shutdown: RefCell::new(crate::node::NodeShutdown {
59 remove_complete_callback: None,
60 unbinding_children_completers: Vec::new(),
61 should_destroy_driver_component: false,
62 }),
63 binding: RefCell::new(crate::node::NodeBinding {
64 node_controller: None,
65 pending_bind_completer: None,
66 bind_error: None,
67 wait_for_driver_completer: None,
68 restart_driver_url_suffix: None,
69 composite_rebind_completer: None,
70 }),
71 component: RefCell::new(None),
72 driver_host: RefCell::new(crate::node::NodeDriverHost {
73 host: initial_host,
74 name_for_colocation: String::new(),
75 restart_on_crash: false,
76 }),
77 node_shutdown_coordinator: RefCell::new(NodeShutdownCoordinator::new(
78 bridge,
79 enable_test_shutdown_delays,
80 shutdown_test_rng,
81 )),
82 can_multibind_composites: true,
83 weak_self: weak_self.clone(),
84 scope: fasync::Scope::new_with_name(format!("node:{name}")),
85 }
86 })
87 }
88
89 pub fn create_composite_offer(
90 offer: &NodeOffer,
91 parents_name: &str,
92 primary_parent: bool,
93 ) -> NodeOffer {
94 let is_default_offer = |name: &str| name == "default";
95
96 let mut new_instance_count = offer.renamed_instances.len();
97 if primary_parent {
98 new_instance_count += offer
99 .renamed_instances
100 .iter()
101 .filter(|instance| is_default_offer(&instance.target_name))
102 .count();
103 }
104
105 let mut new_mappings = Vec::with_capacity(new_instance_count);
106 for instance in &offer.renamed_instances {
107 let target_name = &instance.target_name;
108 if !is_default_offer(target_name) {
109 new_mappings.push(instance.clone());
110 continue;
111 }
112
113 if primary_parent {
114 new_mappings.push(instance.clone());
115 }
116
117 new_mappings.push(fdecl::NameMapping {
118 source_name: instance.source_name.clone(),
119 target_name: parents_name.to_string(),
120 });
121 }
122
123 let mut new_filter_count = offer.source_instance_filter.len();
124 if primary_parent {
125 new_filter_count += offer
126 .source_instance_filter
127 .iter()
128 .filter(|filter| is_default_offer(filter))
129 .count();
130 }
131
132 let mut new_filters = Vec::with_capacity(new_filter_count);
133 for filter in &offer.source_instance_filter {
134 if !is_default_offer(filter) {
135 new_filters.push(filter.clone());
136 continue;
137 }
138
139 if primary_parent {
140 new_filters.push("default".to_string());
141 }
142
143 new_filters.push(parents_name.to_string());
144 }
145
146 NodeOffer {
147 source_name: offer.source_name.clone(),
148 source_collection: offer.source_collection,
149 transport: offer.transport.clone(),
150 service_name: offer.service_name.clone(),
151 source_instance_filter: new_filters,
152 renamed_instances: new_mappings,
153 dir_connector: offer.dir_connector.clone(),
154 }
155 }
156
157 pub fn create_composite_node(
158 node_name: &str,
159 parents: Vec<Weak<Node>>,
160 parents_names: Vec<String>,
161 parent_properties: &[NodePropertyEntry],
162 node_manager: Box<dyn NodeManager>,
163 driver_host_name_for_colocation: String,
164 primary_index: u32,
165 ) -> Result<Rc<Self>, zx::Status> {
166 if parents.is_empty() {
167 return Err(zx::Status::INVALID_ARGS);
168 }
169 if parents.len() != parent_properties.len() {
170 return Err(zx::Status::INVALID_ARGS);
171 }
172 if primary_index as usize >= parents.len() {
173 return Err(zx::Status::OUT_OF_RANGE);
174 }
175
176 let mut has_dictionary_offer = false;
177
178 let mut offers = vec![];
179 for (i, parent) in parents.iter().enumerate() {
180 let parent = parent.upgrade().expect("parent should be alive");
181 for offer in parent.offers().iter() {
182 let new_offer = Self::create_composite_offer(
183 offer,
184 &parents_names[i],
185 i == primary_index as usize,
186 );
187
188 if matches!(new_offer.transport, OfferTransport::Dictionary) {
189 has_dictionary_offer = true;
190 }
191
192 offers.push(new_offer);
193 }
194 }
195
196 let composite =
197 Self::new_composite(node_name, parents, parents_names, primary_index, node_manager);
198
199 composite.set_driver_host_name_for_colocation(&driver_host_name_for_colocation);
200
201 Self::set_composite_parent_properties(&composite, parent_properties);
202
203 let primary_parent = composite.get_primary_parent().expect("primary parent should exist");
204 let symbols = primary_parent.symbols();
205 composite.set_symbols(symbols);
206
207 if let NodeDictionary::Subtree(d) = primary_parent.dictionary() {
209 if has_dictionary_offer {
210 panic!("Cannot use dictionary offers on node");
211 }
212
213 composite.set_subtree_dictionary(d);
214 }
215
216 composite.set_offers(offers);
217
218 composite.add_to_parents();
219
220 let primary_parent_device = primary_parent.device();
221 let topological = primary_parent_device.topological.as_ref().unwrap_or_else(|| {
222 panic!(
223 "Missing topological devfs node for primary parent: {}",
224 composite.make_topological_path(false)
225 )
226 });
227
228 let devfs_device = topological.add_child(
230 &composite.name,
231 None,
232 composite.create_devfs_passthrough(None, None, true, "".to_string()),
233 )?;
234 composite.set_device(devfs_device);
235
236 Ok(composite)
237 }
238
239 pub fn set_composite_parent_properties(&self, parent_properties: &[NodePropertyEntry]) {
240 self.clear_properties();
241 self.set_properties(parent_properties.to_vec());
242 let primary_index = if let NodeTypeVariant::Composite { primary_index, .. } = &*self.node_type() {
243 Some(*primary_index)
244 } else {
245 None
246 };
247 if let Some(primary_index) = primary_index {
248 let default_properties = &parent_properties[primary_index as usize].properties;
249 self.push_property(NodePropertyEntry {
250 name: "default".to_string(),
251 properties: default_properties.to_vec(),
252 });
253 }
254 }
255
256 pub fn remove_composite_node_for_rebind(
257 self: &Rc<Self>,
258 completer: oneshot::Sender<Result<(), zx::Status>>,
259 ) {
260 if let Err(completer) = self.set_composite_rebind_completer(completer) {
261 let _ = completer.send(Err(zx::Status::ALREADY_EXISTS));
262 return;
263 }
264
265 self.get_shutdown_coordinator().set_shutdown_intent(ShutdownIntent::RebindComposite);
266 self.remove(driver_manager_shutdown::RemovalSet::All, None);
267 }
268}