driver_manager_composite/
composite_node_spec_manager.rs1use crate::{CompositeManagerBridge, CompositeNodeSpec};
6use driver_manager_bind::{BindSpecResult, CompositeNodeAndDriver};
7use driver_manager_node::Node;
8use futures::channel::oneshot;
9use log::{error, warn};
10use std::cell::RefCell;
11use std::collections::HashMap;
12use std::rc::Weak;
13use {
14 fidl_fuchsia_driver_development as fdd, fidl_fuchsia_driver_framework as fdf,
15 fuchsia_async as fasync,
16};
17
18pub struct CompositeNodeSpecManager {
19 bridge: Box<dyn CompositeManagerBridge>,
20 specs: RefCell<HashMap<String, CompositeNodeSpec>>,
21}
22
23impl CompositeNodeSpecManager {
24 pub fn new(bridge: Box<dyn CompositeManagerBridge>) -> Self {
25 Self { bridge, specs: RefCell::new(HashMap::new()) }
26 }
27
28 pub async fn add_spec(
29 &self,
30 fidl_spec: fdf::CompositeNodeSpec,
31 spec: CompositeNodeSpec,
32 ) -> Result<(), fdf::CompositeNodeSpecError> {
33 let name = fidl_spec.name.as_ref().unwrap().clone();
34 if self.specs.borrow().contains_key(&name) {
35 error!("Duplicate composite node spec {}", name);
36 return Err(fdf::CompositeNodeSpecError::AlreadyExists);
37 }
38
39 if let Err(e) = self.bridge.add_spec_to_driver_index(fidl_spec).await {
40 error!("Failed to add composite node spec to driver index: {}", e);
41 return Err(fdf::CompositeNodeSpecError::DriverIndexFailure);
42 }
43
44 self.specs.borrow_mut().insert(name, spec);
45 let bridge = self.bridge.box_clone();
46 fasync::Task::local(async move {
47 bridge.bind_nodes_for_composite_node_spec().await;
48 })
49 .detach();
50 Ok(())
51 }
52
53 pub fn bind_parent_spec(
54 &self,
55 composite_parents: &[fdf::CompositeParent],
56 node_ptr: Weak<Node>,
57 enable_multibind: bool,
58 ) -> Result<BindSpecResult, zx::Status> {
59 if composite_parents.is_empty() {
60 error!("composite_parents needs to contain at least one composite parent.");
61 return Err(zx::Status::INVALID_ARGS);
62 }
63
64 let mut bound_composite_parents = Vec::new();
65 let mut node_and_drivers = Vec::new();
66
67 for composite_parent in composite_parents {
68 let composite = match &composite_parent.composite {
69 Some(c) => c,
70 None => {
71 warn!("CompositeParent missing composite.");
72 continue;
73 }
74 };
75
76 let index = match composite_parent.index {
77 Some(i) => i,
78 None => {
79 warn!("CompositeParent missing index.");
80 continue;
81 }
82 };
83
84 let matched_driver = match &composite.matched_driver {
85 Some(md) => md,
86 None => continue,
87 };
88
89 if matched_driver.composite_driver.is_none() || matched_driver.parent_names.is_none() {
90 warn!("CompositeDriverMatch does not have all needed fields.");
91 continue;
92 }
93
94 let spec_info = match &composite.spec {
95 Some(s) => s,
96 None => {
97 warn!("CompositeInfo missing spec.");
98 continue;
99 }
100 };
101
102 let (name, parents) = match (&spec_info.name, &spec_info.parents, &spec_info.parents2) {
103 (Some(name), Some(parents), None) => (name, parents.len()),
104 (Some(name), None, Some(parents)) => (name, parents.len()),
105 _ => {
106 warn!("CompositeNodeSpec missing name or parents.");
107 continue;
108 }
109 };
110
111 if index as usize >= parents
112 || matched_driver.parent_names.as_ref().unwrap().len() != parents
113 {
114 warn!(
115 "Parent names count does not match the spec parent count or index is out of bounds."
116 );
117 continue;
118 }
119
120 let mut specs = self.specs.borrow_mut();
121 let spec = match specs.get_mut(name) {
122 Some(s) => s,
123 None => {
124 error!("Missing composite node spec {}", name);
125 continue;
126 }
127 };
128
129 match spec.bind_parent(composite_parent.clone(), node_ptr.clone()) {
130 Ok(Some(composite_node)) => {
131 bound_composite_parents.push(composite_parent.clone());
132 if let Some(driver) = &matched_driver.composite_driver {
133 node_and_drivers.push(CompositeNodeAndDriver {
134 driver: driver.clone(),
135 node: composite_node,
136 });
137 }
138 }
139 Ok(None) => {
140 bound_composite_parents.push(composite_parent.clone());
141 }
142 Err(zx::Status::ALREADY_BOUND) => {
143 continue;
144 }
145 Err(e) => {
146 error!("Failed to bind node: {}", e);
147 continue;
148 }
149 }
150
151 if !enable_multibind {
152 break;
153 }
154 }
155
156 if !bound_composite_parents.is_empty() {
157 Ok(BindSpecResult {
158 bound_composite_parents,
159 completed_node_and_drivers: node_and_drivers,
160 })
161 } else {
162 Err(zx::Status::NOT_FOUND)
163 }
164 }
165
166 pub async fn rebind(
167 &self,
168 spec_name: String,
169 restart_driver_url_suffix: Option<String>,
170 ) -> Result<(), zx::Status> {
171 if !self.specs.borrow().contains_key(&spec_name) {
172 warn!("Spec {} is not available for rebind", spec_name);
173 return Err(zx::Status::NOT_FOUND);
174 }
175
176 self.bridge
177 .request_rebind_from_driver_index(spec_name.clone(), restart_driver_url_suffix)
178 .await?;
179
180 self.on_request_rebind_complete(spec_name).await
181 }
182
183 async fn on_request_rebind_complete(&self, spec_name: String) -> Result<(), zx::Status> {
184 let rx = {
185 let mut specs = self.specs.borrow_mut();
186 let spec = specs.get_mut(&spec_name).unwrap();
187
188 let (tx, rx) = oneshot::channel();
189 spec.remove(tx);
190 rx
191 };
192 rx.await.map_err(|_| zx::Status::INTERNAL)??;
193
194 log::debug!("Rebinding composite node spec {}", spec_name);
195 self.bridge.bind_nodes_for_composite_node_spec().await;
196 Ok(())
197 }
198
199 pub fn get_composite_info(&self) -> Vec<fdd::CompositeNodeInfo> {
200 self.specs.borrow().values().map(|spec| spec.get_composite_info()).collect()
201 }
202}