blob: 941d0b6ff4d78ffca0069ef1632dc101237940c0 [file] [log] [blame]
// 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_