| // Copyright 2020 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. |
| |
| #ifndef SRC_DEVICES_BIN_DRIVER_MANAGER_V2_DRIVER_RUNNER_H_ |
| #define SRC_DEVICES_BIN_DRIVER_MANAGER_V2_DRIVER_RUNNER_H_ |
| |
| #include <fidl/fuchsia.component/cpp/wire.h> |
| #include <fidl/fuchsia.driver.development/cpp/wire.h> |
| #include <fidl/fuchsia.driver.host/cpp/wire.h> |
| #include <fidl/fuchsia.driver.index/cpp/wire.h> |
| #include <lib/async/cpp/wait.h> |
| #include <lib/fidl/llcpp/client.h> |
| #include <lib/fidl/llcpp/wire_messaging.h> |
| #include <lib/fit/function.h> |
| #include <lib/fpromise/promise.h> |
| #include <lib/inspect/cpp/inspect.h> |
| #include <lib/zircon-internal/thread_annotations.h> |
| #include <lib/zx/status.h> |
| |
| #include <list> |
| #include <unordered_map> |
| |
| #include <fbl/intrusive_double_list.h> |
| |
| #include "src/devices/bin/driver_manager/v2/composite_assembler.h" |
| #include "src/devices/bin/driver_manager/v2/driver_component.h" |
| #include "src/devices/bin/driver_manager/v2/driver_host.h" |
| #include "src/devices/bin/driver_manager/v2/node.h" |
| #include "src/lib/storage/vfs/cpp/pseudo_dir.h" |
| |
| // Note, all of the logic here assumes we are operating on a single-threaded |
| // dispatcher. It is not safe to use a multi-threaded dispatcher with this code. |
| |
| namespace dfv2 { |
| |
| class DriverRunner : public fidl::WireServer<fuchsia_component_runner::ComponentRunner>, |
| public DriverBinder { |
| public: |
| DriverRunner(fidl::ClientEnd<fuchsia_component::Realm> realm, |
| fidl::ClientEnd<fuchsia_driver_index::DriverIndex> driver_index, |
| inspect::Inspector& inspector, async_dispatcher_t* dispatcher); |
| |
| fpromise::promise<inspect::Inspector> Inspect() const; |
| size_t NumOrphanedNodes() const; |
| zx::status<> PublishComponentRunner(const fbl::RefPtr<fs::PseudoDir>& svc_dir); |
| zx::status<> StartRootDriver(std::string_view url); |
| std::shared_ptr<const Node> root_node() const; |
| // This function schedules a callback to attempt to bind all orphaned nodes against |
| // the base drivers. |
| void ScheduleBaseDriversBinding(); |
| // Goes through the orphan list and attempts the bind them again. Sends nodes that are still |
| // orphaned back to the orphan list. Tracks the result of the bindings and then when finished |
| // uses the result_callback to report the results. |
| void TryBindAllOrphans(NodeBindingInfoResultCallback result_callback); |
| |
| private: |
| using CompositeArgs = std::vector<std::weak_ptr<Node>>; |
| using DriverUrl = std::string; |
| using CompositeArgsIterator = std::unordered_multimap<DriverUrl, CompositeArgs>::iterator; |
| |
| // fidl::WireServer<fuchsia_component_runner::ComponentRunner> |
| void Start(StartRequestView request, StartCompleter::Sync& completer) override; |
| // DriverBinder |
| // Attempt to bind `node`. |
| // A nullptr for result_tracker is acceptable if the caller doesn't intend to |
| // track the results. |
| void Bind(Node& node, std::shared_ptr<BindResultTracker> result_tracker) override; |
| |
| // Create a composite node. Returns a `Node` that is owned by its parents. |
| zx::status<Node*> CreateCompositeNode( |
| Node& node, const fuchsia_driver_index::wire::MatchedCompositeInfo& matched_driver); |
| // Adds `matched_driver` to an existing set of composite arguments, or creates |
| // a new set of composite arguments. Returns an iterator to the set of |
| // composite arguments. |
| zx::status<CompositeArgsIterator> AddToCompositeArgs( |
| const std::string& name, |
| const fuchsia_driver_index::wire::MatchedCompositeInfo& matched_driver); |
| zx::status<> StartDriver(Node& node, std::string_view url, |
| fuchsia_driver_index::DriverPackageType package_type); |
| |
| zx::status<std::unique_ptr<DriverHostComponent>> StartDriverHost(); |
| // The untracked version of TryBindAllOrphans. |
| void TryBindAllOrphansUntracked(); |
| |
| struct CreateComponentOpts { |
| const Node* node = nullptr; |
| zx::handle token; |
| fidl::ServerEnd<fuchsia_io::Directory> exposed_dir; |
| }; |
| zx::status<> CreateComponent(std::string name, Collection collection, std::string url, |
| CreateComponentOpts opts); |
| |
| uint64_t next_driver_host_id_ = 0; |
| fidl::WireClient<fuchsia_component::Realm> realm_; |
| fidl::WireClient<fuchsia_driver_index::DriverIndex> driver_index_; |
| async_dispatcher_t* const dispatcher_; |
| std::shared_ptr<Node> root_node_; |
| |
| CompositeDeviceManager composite_device_manager_; |
| |
| std::unordered_map<zx_koid_t, Node&> driver_args_; |
| std::unordered_multimap<DriverUrl, CompositeArgs> composite_args_; |
| fbl::DoublyLinkedList<std::unique_ptr<DriverHostComponent>> driver_hosts_; |
| |
| // Orphaned nodes are nodes that have failed to bind to a driver, either |
| // because no matching driver could be found, or because the matching driver |
| // failed to start. |
| std::vector<std::weak_ptr<Node>> orphaned_nodes_; |
| }; |
| |
| } // namespace dfv2 |
| |
| #endif // SRC_DEVICES_BIN_DRIVER_MANAGER_V2_DRIVER_RUNNER_H_ |