1use crate::info_iterator::{CompositeInfoIterator, DeviceInfoIterator, DriverHostInfoIterator};
6use driver_manager_core::DriverRunner;
7use driver_manager_node::Node;
8use driver_manager_shutdown::RemovalSet;
9use fdd::ManagerRequest::*;
10use fidl::endpoints::{DiscoverableProtocolMarker, Responder, ServerEnd};
11use fidl_fuchsia_component_decl as fdecl;
12use fidl_fuchsia_driver_development as fdd;
13use fidl_fuchsia_driver_framework as fdf;
14use fidl_fuchsia_driver_host as fdh;
15use fidl_fuchsia_driver_index as fdi;
16use fuchsia_async as fasync;
17use fuchsia_component::client::connect_to_protocol;
18use fuchsia_component::server::{ServiceFs, ServiceObjLocal};
19use futures::prelude::*;
20use log::{error, warn};
21use std::cell::RefCell;
22use std::collections::{HashMap, HashSet, VecDeque};
23use std::rc::{Rc, Weak};
24
25pub struct DriverDevelopmentService {
26 driver_runner: Rc<DriverRunner>,
27 test_nodes: RefCell<HashMap<String, Weak<Node>>>,
28 scope: fasync::Scope,
29}
30
31impl DriverDevelopmentService {
32 pub fn new(driver_runner: Rc<DriverRunner>) -> Self {
33 let scope = fasync::Scope::new_with_name("driver_development_service");
34 Self { driver_runner, test_nodes: RefCell::new(HashMap::new()), scope }
35 }
36
37 pub fn publish(self: &Rc<Self>, fs: &mut ServiceFs<ServiceObjLocal<'_, ()>>) {
38 let this = self.clone();
39 fs.dir("svc").add_fidl_service(move |stream: fdd::ManagerRequestStream| {
40 let this_clone = this.clone();
41 this.scope.spawn_local(async move {
42 if let Err(e) = this_clone.serve(stream).await {
43 warn!("Failed to serve DriverDevelopmentService: {}", e);
44 }
45 });
46 });
47 }
48
49 pub async fn serve(
50 self: Rc<Self>,
51 mut stream: fdd::ManagerRequestStream,
52 ) -> Result<(), fidl::Error> {
53 while let Some(request) = stream.try_next().await? {
54 match request {
55 GetNodeInfo { node_filter, exact_match, iterator, .. } => {
56 self.get_node_info(node_filter, exact_match, iterator).await;
57 }
58 GetCompositeInfo { iterator, .. } => {
59 self.get_composite_info(iterator);
60 }
61 GetDriverInfo { driver_filter, iterator, .. } => {
62 self.get_driver_info(driver_filter, iterator);
63 }
64 GetCompositeNodeSpecs { name_filter, iterator, .. } => {
65 self.get_composite_node_specs(name_filter, iterator);
66 }
67 AddTestNode { args, responder } => {
68 self.add_test_node(args, responder).await;
69 }
70 RemoveTestNode { name, responder } => {
71 self.remove_test_node(name, responder);
72 }
73 BindAllUnboundNodes { responder } => {
74 self.bind_all_unbound_nodes(responder).await;
75 }
76 BindAllUnboundNodes2 { responder } => {
77 self.bind_all_unbound_nodes2(responder).await;
78 }
79 WaitForBootup { responder } => {
80 self.wait_for_bootup(responder).await;
81 }
82 GetDriverHostInfo { iterator, .. } => {
83 self.get_driver_host_info(iterator).await;
84 }
85 RestartDriverHosts { driver_url, rematch_flags, responder } => {
86 self.restart_driver_hosts(driver_url, rematch_flags, responder).await;
87 }
88 DisableDriver { driver_url, package_hash, responder } => {
89 self.disable_driver(driver_url, package_hash, responder).await;
90 }
91 EnableDriver { driver_url, package_hash, responder } => {
92 self.enable_driver(driver_url, package_hash, responder).await;
93 }
94 RebindCompositesWithDriver { driver_url, responder } => {
95 self.rebind_composites_with_driver(driver_url, responder).await;
96 }
97 RestartWithDictionary { moniker, dictionary, responder } => {
98 self.restart_with_dictionary(moniker, dictionary, responder).await;
99 }
100 _ => {}
101 }
102 }
103 Ok(())
104 }
105
106 async fn get_node_info(
107 &self,
108 node_filter: Vec<String>,
109 exact_match: bool,
110 iterator: ServerEnd<fdd::NodeInfoIteratorMarker>,
111 ) {
112 let mut device_infos = vec![];
113 let mut unique_nodes = HashSet::new();
114 let mut remaining_nodes = VecDeque::new();
115 remaining_nodes.push_back(self.driver_runner.root_node());
116
117 while let Some(node) = remaining_nodes.pop_front() {
118 let node_ptr: *const _ = Rc::as_ptr(&node);
119 if !unique_nodes.insert(node_ptr) {
120 continue;
121 }
122
123 for child in node.children() {
124 remaining_nodes.push_back(child);
125 }
126
127 let moniker = node.make_component_moniker();
128 if !node_filter.is_empty() {
129 let found = node_filter.iter().any(|filter| {
130 if exact_match { &moniker == filter } else { moniker.contains(filter) }
131 });
132 if !found {
133 continue;
134 }
135 }
136
137 match create_device_info(&node).await {
138 Ok(info) => device_infos.push(info),
139 Err(_) => return, }
141 }
142
143 let iterator_stream = iterator.into_stream();
144 let device_info_iterator = DeviceInfoIterator::new(device_infos);
145 self.scope.spawn_local(async move {
146 if let Err(e) = device_info_iterator.serve(iterator_stream).await {
147 warn!("DeviceInfoIterator server failed: {}", e);
148 }
149 });
150 }
151
152 fn get_composite_info(&self, iterator: ServerEnd<fdd::CompositeInfoIteratorMarker>) {
153 let list = self.driver_runner.get_composite_list_info();
154 let iterator_stream = iterator.into_stream();
155 let composite_info_iterator = CompositeInfoIterator::new(list);
156 self.scope.spawn_local(async move {
157 if let Err(e) = composite_info_iterator.serve(iterator_stream).await {
158 warn!("CompositeInfoIterator server failed: {}", e);
159 }
160 });
161 }
162
163 fn get_driver_info(
164 &self,
165 driver_filter: Vec<String>,
166 iterator: ServerEnd<fdd::DriverInfoIteratorMarker>,
167 ) {
168 let driver_index_client = match connect_to_protocol::<fdi::DevelopmentManagerMarker>() {
169 Ok(proxy) => proxy,
170 Err(e) => {
171 error!(
172 "Failed to connect to service '{}': {}",
173 fdi::DevelopmentManagerMarker::PROTOCOL_NAME,
174 e
175 );
176 iterator.close_with_epitaph(zx::Status::UNAVAILABLE).ok();
177 return;
178 }
179 };
180
181 if let Err(e) = driver_index_client.get_driver_info(&driver_filter, iterator) {
182 error!("Failed to call DriverIndex::GetDriverInfo: {}", e);
183 }
184 }
185
186 fn get_composite_node_specs(
187 &self,
188 name_filter: Option<String>,
189 iterator: ServerEnd<fdd::CompositeNodeSpecIteratorMarker>,
190 ) {
191 let driver_index_client = match connect_to_protocol::<fdi::DevelopmentManagerMarker>() {
192 Ok(proxy) => proxy,
193 Err(e) => {
194 error!(
195 "Failed to connect to service '{}': {}",
196 fdi::DevelopmentManagerMarker::PROTOCOL_NAME,
197 e
198 );
199 iterator.close_with_epitaph(zx::Status::UNAVAILABLE).ok();
200 return;
201 }
202 };
203
204 if let Err(e) =
205 driver_index_client.get_composite_node_specs(name_filter.as_deref(), iterator)
206 {
207 error!("Failed to call DriverIndex::GetCompositeNodeSpecs: {}", e);
208 }
209 }
210
211 async fn add_test_node(
212 &self,
213 args: fdd::TestNodeAddArgs,
214 responder: fdd::ManagerAddTestNodeResponder,
215 ) {
216 let name = if let Some(name) = args.name {
217 name
218 } else {
219 let _ = responder.send(Err(fdf::NodeError::NameMissing));
220 return;
221 };
222
223 let add_args = fdf::NodeAddArgs {
224 name: Some(name.clone()),
225 properties2: args.properties,
226 ..Default::default()
227 };
228
229 let result = self.driver_runner.root_node().add_child(add_args, None, None).await;
230
231 match result {
232 Ok(node) => {
233 self.test_nodes.borrow_mut().insert(name, Rc::downgrade(&node));
234 let _ = responder.send(Ok(()));
235 }
236 Err(e) => {
237 let _ = responder.send(Err(e));
238 }
239 }
240 }
241
242 fn remove_test_node(&self, name: String, responder: fdd::ManagerRemoveTestNodeResponder) {
243 let mut test_nodes = self.test_nodes.borrow_mut();
244 if !test_nodes.contains_key(&name) {
245 let _ = responder.send(Err(zx::Status::NOT_FOUND.into_raw()));
246 return;
247 }
248
249 if let Some(node_weak) = test_nodes.get(&name)
250 && let Some(node) = node_weak.upgrade()
251 {
252 node.remove(RemovalSet::All, None);
253 }
254
255 test_nodes.remove(&name);
256 let _ = responder.send(Ok(()));
257 }
258
259 async fn bind_all_unbound_nodes(&self, responder: fdd::ManagerBindAllUnboundNodesResponder) {
260 let result = self.driver_runner.bind_manager.try_bind_all_available().await;
261 let _ = responder.send(Ok(&result));
262 }
263
264 async fn bind_all_unbound_nodes2(&self, responder: fdd::ManagerBindAllUnboundNodes2Responder) {
265 let result = self.driver_runner.bind_manager.try_bind_all_available().await;
266 let _ = responder.send(Ok(&result));
267 }
268
269 async fn wait_for_bootup(&self, responder: fdd::ManagerWaitForBootupResponder) {
270 self.driver_runner.bootup_tracker.wait_for_bootup().await;
271 let _ = responder.send();
272 }
273
274 async fn get_driver_host_info(&self, iterator: ServerEnd<fdd::DriverHostInfoIteratorMarker>) {
275 let mut driver_host_to_drivers: HashMap<zx::Koid, HashSet<String>> = HashMap::new();
276 let mut unique_nodes = HashSet::new();
277 let mut remaining_nodes = VecDeque::new();
278 remaining_nodes.push_back(self.driver_runner.root_node());
279
280 while let Some(node) = remaining_nodes.pop_front() {
281 let node_ptr: *const _ = Rc::as_ptr(&node);
282 if !unique_nodes.insert(node_ptr) {
283 continue;
284 }
285
286 for child in node.children() {
287 remaining_nodes.push_back(child);
288 }
289
290 if node.is_bound()
291 && let Some(host) = node.driver_host()
292 && let Ok(koid) = host.get_process_koid().await
293 {
294 driver_host_to_drivers.entry(koid).or_default().insert(node.driver_url());
295 }
296 }
297
298 let mut infos = vec![];
299 for host in self.driver_runner.driver_hosts() {
300 let process_info = match host.get_process_info_internal().await {
301 Ok(info) => info,
302 Err(_) => continue,
303 };
304
305 let threads = process_info
306 .threads
307 .into_iter()
308 .map(|t| fdd::ThreadInfo {
309 koid: Some(t.koid),
310 name: Some(t.name),
311 scheduler_role: (!t.scheduler_role.is_empty()).then_some(t.scheduler_role),
312 ..Default::default()
313 })
314 .collect();
315
316 let dispatchers = process_info
317 .dispatchers
318 .into_iter()
319 .map(|d| {
320 let state = match d.state {
321 fdh::DispatcherState::Running => Some(fdd::DispatcherState::Running),
322 fdh::DispatcherState::ShuttingDown => {
323 Some(fdd::DispatcherState::ShuttingDown)
324 }
325 fdh::DispatcherState::Shutdown => Some(fdd::DispatcherState::Shutdown),
326 fdh::DispatcherState::Destroyed => Some(fdd::DispatcherState::Destroyed),
327 _ => None,
328 };
329 let queued_tasks = d
330 .queued_tasks
331 .into_iter()
332 .map(|t| fdd::QueuedTaskInfo {
333 ptr: Some(t.ptr),
334 handler: Some(t.handler),
335 initiating_dispatcher: Some(t.initiating_dispatcher),
336 initiating_dispatcher_name: if t.initiating_dispatcher_name.is_empty() {
337 None
338 } else {
339 Some(t.initiating_dispatcher_name)
340 },
341 initiating_driver: Some(t.initiating_driver),
342 initiating_driver_url: if t.initiating_driver_url.is_empty() {
343 None
344 } else {
345 Some(t.initiating_driver_url)
346 },
347 ..Default::default()
348 })
349 .collect();
350 let non_inlined = d.debug_stats.non_inlined;
351 let debug_stats = fdd::DispatcherDebugStats {
352 num_total_requests: Some(d.debug_stats.num_total_requests),
353 num_inlined_requests: Some(d.debug_stats.num_inlined_requests),
354 non_inlined: Some(fdd::NonInlinedRequestStats {
355 allow_sync_calls: Some(non_inlined.allow_sync_calls),
356 parallel_dispatch: Some(non_inlined.parallel_dispatch),
357 task: Some(non_inlined.task),
358 unknown_thread: Some(non_inlined.unknown_thread),
359 reentrant: Some(non_inlined.reentrant),
360 channel_wait_not_yet_registered: Some(
361 non_inlined.channel_wait_not_yet_registered,
362 ),
363 no_thread_migration: Some(non_inlined.no_thread_migration),
364 ..Default::default()
365 }),
366 ..Default::default()
367 };
368 fdd::DispatcherInfo {
369 driver: Some(d.driver),
370 name: Some(d.name),
371 options: Some(d.options),
372 scheduler_role: Some(d.scheduler_role),
373 dispatcher_ptr: Some(d.dispatcher_ptr),
374 driver_ptr: Some(d.driver_ptr),
375 synchronized: Some(d.synchronized),
376 allow_sync_calls: Some(d.allow_sync_calls),
377 state,
378 destroy_context: if d.destroy_context.is_empty() {
379 None
380 } else {
381 Some(d.destroy_context)
382 },
383 destroy_user_initiated: if d.has_destroy_user_initiated {
384 Some(d.destroy_user_initiated)
385 } else {
386 None
387 },
388 debug_stats: Some(debug_stats),
389 queued_tasks: Some(queued_tasks),
390 num_queued_tasks: Some(d.num_queued_tasks),
391 ..Default::default()
392 }
393 })
394 .collect();
395
396 let mut drivers = vec![];
397 if let Some(d) = driver_host_to_drivers.get(&process_info.process_koid) {
398 drivers = d.iter().cloned().collect();
399 drivers.sort();
400 }
401
402 infos.push(fdd::DriverHostInfo {
403 process_koid: Some(process_info.process_koid.raw_koid()),
404 name: Some(host.name_for_colocation().to_string()),
405 threads: Some(threads),
406 dispatchers: Some(dispatchers),
407 drivers: Some(drivers),
408 ..Default::default()
409 });
410 }
411
412 let iterator_stream = iterator.into_stream();
413 let driver_host_info_iterator = DriverHostInfoIterator::new(infos);
414 self.scope.spawn_local(async move {
415 if let Err(e) = driver_host_info_iterator.serve(iterator_stream).await {
416 warn!("DriverHostInfoIterator server failed: {}", e);
417 }
418 });
419 }
420
421 async fn restart_driver_hosts(
422 &self,
423 driver_url: String,
424 rematch_flags: fdd::RestartRematchFlags,
425 responder: fdd::ManagerRestartDriverHostsResponder,
426 ) {
427 let result = self
428 .driver_runner
429 .restart_nodes_colocated_with_driver_url(&driver_url, rematch_flags)
430 .await;
431 match result {
432 Ok(count) => {
433 let _ = responder.send(Ok(count));
434 }
435 Err(status) => {
436 let _ = responder.send(Err(status.into_raw()));
437 }
438 }
439 }
440
441 async fn disable_driver(
442 &self,
443 driver_url: String,
444 package_hash: Option<String>,
445 responder: fdd::ManagerDisableDriverResponder,
446 ) {
447 let driver_index_client = match connect_to_protocol::<fdi::DevelopmentManagerMarker>() {
448 Ok(proxy) => proxy,
449 Err(e) => {
450 error!(
451 "Failed to connect to service '{}': {}",
452 fdi::DevelopmentManagerMarker::PROTOCOL_NAME,
453 e
454 );
455 responder.control_handle().shutdown_with_epitaph(zx::Status::UNAVAILABLE);
456 return;
457 }
458 };
459
460 match driver_index_client.disable_driver(&driver_url, package_hash.as_deref()).await {
461 Ok(result) => {
462 let _ = responder.send(result);
463 }
464 Err(e) => {
465 error!("Failed to call DriverIndex::DisableDriver: {}", e);
466 let epitaph = match e {
467 fidl::Error::ClientChannelClosed { epitaph, .. } => epitaph,
468 _ => zx::Status::INTERNAL.into(),
469 };
470 responder.control_handle().shutdown_with_epitaph(epitaph);
471 }
472 }
473 }
474
475 async fn enable_driver(
476 &self,
477 driver_url: String,
478 package_hash: Option<String>,
479 responder: fdd::ManagerEnableDriverResponder,
480 ) {
481 let driver_index_client = match connect_to_protocol::<fdi::DevelopmentManagerMarker>() {
482 Ok(proxy) => proxy,
483 Err(e) => {
484 error!(
485 "Failed to connect to service '{}': {}",
486 fdi::DevelopmentManagerMarker::PROTOCOL_NAME,
487 e
488 );
489 responder.control_handle().shutdown_with_epitaph(zx::Status::UNAVAILABLE);
490 return;
491 }
492 };
493
494 match driver_index_client.enable_driver(&driver_url, package_hash.as_deref()).await {
495 Ok(result) => {
496 let _ = responder.send(result);
497 }
498 Err(e) => {
499 error!("Failed to call DriverIndex::EnableDriver: {}", e);
500 let epitaph = match e {
501 fidl::Error::ClientChannelClosed { epitaph, .. } => epitaph,
502 _ => zx::Status::INTERNAL.into(),
503 };
504 responder.control_handle().shutdown_with_epitaph(epitaph);
505 }
506 }
507 }
508
509 async fn rebind_composites_with_driver(
510 &self,
511 driver_url: String,
512 responder: fdd::ManagerRebindCompositesWithDriverResponder,
513 ) {
514 let driver_index_client = match connect_to_protocol::<fdi::DevelopmentManagerMarker>() {
515 Ok(proxy) => proxy,
516 Err(e) => {
517 error!(
518 "Failed to connect to service '{}': {}",
519 fdi::DevelopmentManagerMarker::PROTOCOL_NAME,
520 e
521 );
522 responder.control_handle().shutdown_with_epitaph(zx::Status::UNAVAILABLE);
523 return;
524 }
525 };
526
527 match driver_index_client.rebind_composites_with_driver(&driver_url).await {
528 Ok(Ok(())) => {
529 let count = self.driver_runner.rebind_composites_with_driver(&driver_url).await;
531 let _ = responder.send(Ok(count));
532 }
533 Ok(Err(status)) => {
534 error!(
535 "DriverIndex::RebindCompositesWithDriver failed: {}",
536 zx::Status::err_from_raw(status)
537 );
538 let _ = responder.send(Err(status));
539 }
540 Err(e) => {
541 error!("Failed to call DriverIndex::RebindCompositesWithDriver: {}", e);
542 let status = match e {
543 fidl::Error::ClientChannelClosed { epitaph, .. } => match epitaph.into() {
544 Err(s) => s,
545 Ok(()) => zx::Status::PEER_CLOSED,
546 },
547 _ => zx::Status::INTERNAL,
548 };
549 let _ = responder.send(Err(status.into_raw()));
550 }
551 }
552 }
553
554 async fn restart_with_dictionary(
555 &self,
556 moniker: String,
557 dictionary: fidl_fuchsia_component_sandbox::DictionaryRef,
558 responder: fdd::ManagerRestartWithDictionaryResponder,
559 ) {
560 let (endpoint0, endpoint1) = zx::EventPair::create();
561 self.driver_runner.restart_with_dictionary(moniker, dictionary, endpoint1).await;
562 let _ = responder.send(Ok(endpoint0));
563 }
564}
565
566async fn create_device_info(node: &Rc<Node>) -> Result<fdd::NodeInfo, zx::Status> {
567 let children = node.children();
568 let child_ids: Vec<u64> = children.iter().map(|child| Rc::as_ptr(child) as u64).collect();
569
570 let parents = node.parents();
571 let parent_ids: Vec<u64> = parents
572 .iter()
573 .filter_map(|parent| parent.upgrade())
574 .map(|parent| Rc::as_ptr(&parent) as u64)
575 .collect();
576
577 let driver_host_koid = if node.as_ref().is_bound() {
578 match node.driver_host().as_ref() {
579 Some(dh) => Some(dh.get_process_koid().await.unwrap().raw_koid()),
580 None => None,
581 }
582 } else {
583 None
584 };
585
586 let offers = node.offers();
587 let offer_list: Vec<fdecl::Offer> = offers
588 .iter()
589 .map(|o| o.into())
590 .filter_map(|offer| match offer {
591 fdf::Offer::DriverTransport(d) => Some(d),
592 fdf::Offer::ZirconTransport(z) => Some(z),
593 fdf::Offer::DictionaryOffer(d) => Some(d),
594 _ => None,
595 })
596 .collect();
597
598 let node_property_list = if node.is_composite() {
599 None
600 } else {
601 node.get_node_properties(None).filter(|properties| !properties.is_empty())
602 };
603
604 Ok(fdd::NodeInfo {
605 id: Some(Rc::as_ptr(node) as u64),
606 moniker: Some(node.make_component_moniker()),
607 bound_driver_url: Some(node.driver_url()),
608 quarantined: Some(node.is_quarantined()),
609 is_running: Some(node.is_driver_running()),
610 child_ids: if child_ids.is_empty() { None } else { Some(child_ids) },
611 parent_ids: if parent_ids.is_empty() { None } else { Some(parent_ids) },
612 driver_host_koid,
613 offer_list: if offer_list.is_empty() { None } else { Some(offer_list) },
614 node_property_list,
615 bus_topology: Some(node.get_bus_topology()),
616 ..Default::default()
617 })
618}