blob: a66859520368dbd50c1781a1f4e8ab1338482bed [file] [log] [blame]
// Copyright 2023 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use crate::model::{
events::synthesizer::ComponentManagerEventSynthesisProvider,
hooks::{CapabilityReceiver, Event, EventPayload},
};
use async_trait::async_trait;
use fidl::endpoints::DiscoverableProtocolMarker;
use fidl_fuchsia_inspect::InspectSinkMarker;
use fuchsia_async::TaskGroup;
use fuchsia_inspect::Inspector;
use fuchsia_sync::Mutex;
use inspect_runtime::{publish, PublishOptions};
use moniker::Moniker;
use routing::event::EventFilter;
use sandbox::Message;
/// A struct for providing CapabilityRequested events carrying a channel for
/// `fuchsia.inspect.InspectSink`.
pub struct InspectSinkProvider {
/// This keeps track of living servers for `fuchsia.inspect.Tree`. If archivist restarts,
/// the existing servers will eventually die and a new one will be inserted here when
/// `ComponentManagerEventSynthesisProvider::provide` is triggered on reconnect.
inspect_tree_server_tasks: Mutex<TaskGroup>,
inspector: Inspector,
}
impl InspectSinkProvider {
pub fn new(inspector: Inspector) -> Self {
Self { inspect_tree_server_tasks: Mutex::new(TaskGroup::new()), inspector }
}
pub fn inspector(&self) -> &Inspector {
&self.inspector
}
}
#[async_trait]
impl ComponentManagerEventSynthesisProvider for InspectSinkProvider {
fn provide(&self, filter: &EventFilter) -> Option<Event> {
if !filter.contains("name", vec![InspectSinkMarker::PROTOCOL_NAME.into()]) {
return None;
}
let (client, server) = fidl::endpoints::create_endpoints();
let Some(server_task) =
publish(&self.inspector, PublishOptions::default().on_inspect_sink_client(client))
else {
return None;
};
self.inspect_tree_server_tasks.lock().add(server_task);
// this value is irrelevant, archivist won't do anything with it but it is part of
// the protocol
let source_moniker = Moniker::try_from("parent").unwrap();
let (receiver, sender) = CapabilityReceiver::new();
let _ = sender.send(Message { channel: server.into_channel() });
Some(Event::new_builtin(EventPayload::CapabilityRequested {
source_moniker,
name: InspectSinkMarker::PROTOCOL_NAME.into(),
receiver,
}))
}
}