blob: 0220ae58b31fdd171e7a8fcef9b64f70648639b0 [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.
#include "src/ui/lib/display/get_hardware_display_controller.h"
#include <lib/fdio/directory.h>
#include <lib/fpromise/bridge.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/trace/event.h>
#include <zircon/status.h>
#include <memory>
#include "src/lib/files/directory.h"
#include "src/ui/lib/display/hardware_display_controller_provider_impl.h"
namespace ui_display {
fpromise::promise<DisplayControllerHandles> GetHardwareDisplayController(
std::shared_ptr<fuchsia::hardware::display::ProviderPtr> provider) {
// Create the device and interface channels.
zx::channel device_server, device_client;
zx_status_t status = zx::channel::create(0, &device_server, &device_client);
if (status != ZX_OK) {
FX_LOGS(ERROR) << "Failed to create device channel: " << zx_status_get_string(status);
return fpromise::make_ok_promise(DisplayControllerHandles{});
}
zx::channel ctrl_server, ctrl_client;
status = zx::channel::create(0, &ctrl_server, &ctrl_client);
if (status != ZX_OK) {
FX_LOGS(ERROR) << "Failed to create controller channel: " << zx_status_get_string(status);
return fpromise::make_ok_promise(DisplayControllerHandles{});
}
// A reference to |provider| is retained in the closure, to keep the connection open until the
// response is received.
fpromise::bridge<DisplayControllerHandles> dc_handles_bridge;
(*provider)->OpenController(
std::move(device_server),
::fidl::InterfaceRequest<fuchsia::hardware::display::Controller>(std::move(ctrl_server)),
[provider, completer = std::move(dc_handles_bridge.completer),
device_client = std::move(device_client),
ctrl_client = std::move(ctrl_client)](zx_status_t status) mutable {
if (status != ZX_OK) {
FX_LOGS(ERROR) << "GetHardwareDisplayController() provider responded with status: "
<< zx_status_get_string(status);
completer.complete_ok(DisplayControllerHandles{});
return;
}
DisplayControllerHandles handles{
::fidl::InterfaceHandle<fuchsia::hardware::display::Controller>(std::move(ctrl_client)),
std::move(device_client)};
completer.complete_ok(std::move(handles));
});
return dc_handles_bridge.consumer.promise();
}
fpromise::promise<DisplayControllerHandles> GetHardwareDisplayController(
ui_display::HardwareDisplayControllerProviderImpl* hdcp_service_impl) {
TRACE_DURATION("gfx", "GetHardwareDisplayController");
// We check the environment to see if there is any fake display is provided through
// fuchsia.hardware.display.Provider protocol. We connect to fake display if given. Otherwise, we
// fall back to |hdcp_service_impl|.
// TODO(fxbug.dev/73816): Change fake display injection after moving to CFv2.
std::vector<std::string> contents;
files::ReadDirContents("/svc", &contents);
const bool fake_display_is_injected =
std::find(contents.begin(), contents.end(), "fuchsia.hardware.display.Provider") !=
contents.end();
auto provider = std::make_shared<fuchsia::hardware::display::ProviderPtr>();
if (fake_display_is_injected) {
const char* kSvcPath = "/svc/fuchsia.hardware.display.Provider";
zx_status_t status =
fdio_service_connect(kSvcPath, provider->NewRequest().TakeChannel().release());
if (status != ZX_OK) {
FX_LOGS(ERROR) << "GetHardwareDisplayController() failed to connect to " << kSvcPath
<< " with status: " << zx_status_get_string(status)
<< ". Something went wrong in fake-display injection routing.";
return fpromise::make_result_promise<DisplayControllerHandles>(fpromise::error());
}
} else if (hdcp_service_impl) {
hdcp_service_impl->BindDisplayProvider(provider->NewRequest());
} else {
FX_LOGS(ERROR) << "No display provider given.";
return fpromise::make_result_promise<DisplayControllerHandles>(fpromise::error());
}
return GetHardwareDisplayController(std::move(provider));
}
} // namespace ui_display