blob: dbc5c18d8b403ffbacbc6e669380afb6d1d4e71d [file] [log] [blame]
// Copyright 2018 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 "device_ctx.h"
#include <fuchsia/hardware/mediacodec/c/fidl.h>
#include <fuchsia/io/cpp/fidl.h>
#include <lib/sync/completion.h>
#include <ddktl/fidl.h>
#include "amlogic-video.h"
#include "macros.h"
#include "sdk/lib/sys/cpp/service_directory.h"
DeviceCtx::DeviceCtx(DriverCtx* driver, zx_device_t* parent)
: DdkDeviceType(parent),
driver_(driver),
codec_admission_control_(driver->shared_fidl_loop()->dispatcher()) {
video_ = std::make_unique<AmlogicVideo>();
video_->SetMetrics(&metrics());
device_fidl_ = std::make_unique<DeviceFidl>(this);
}
DeviceCtx::~DeviceCtx() {
// There are two ways to destroy a fidl::Binding safely:
// * Switch to FIDL thread before Unbind() or ~Binding.
// * async::Loop Quit() + JoinThreads() before Unbind() or ~Binding
//
// For now this code (if implementation needed) will choose the first option
// by destructing DeviceFidl on the FIDL thread. The current way forces this
// thread to wait in this destructor until the shared_fidl_thread() is done
// processing ~DeviceFidl, which means we require that ~DeviceCtx is not
// itself running on the shared_fidl_thread() (or we could check which thread
// here, if we really need to).
//
// This code is only run when we switch between test and production drivers.
sync_completion_t completion;
driver_->PostToSharedFidl([this, &completion]() {
device_fidl_ = nullptr;
sync_completion_signal(&completion);
});
sync_completion_wait(&completion, ZX_TIME_INFINITE);
}
zx_status_t DeviceCtx::Bind() { return DdkAdd("amlogic_video"); }
zx_status_t DeviceCtx::DdkMessage(fidl_incoming_msg_t* msg, fidl_txn_t* txn) {
DdkTransaction ddk_transaction(txn);
llcpp::fuchsia::hardware::mediacodec::Device::Dispatch(this, msg, &ddk_transaction);
return ddk_transaction.Status();
}
void DeviceCtx::GetCodecFactory(zx::channel request, GetCodecFactoryCompleter::Sync& completer) {
device_fidl()->ConnectChannelBoundCodecFactory(std::move(request));
}
void DeviceCtx::SetAuxServiceDirectory(fidl::ClientEnd<llcpp::fuchsia::io::Directory> directory,
SetAuxServiceDirectoryCompleter::Sync& completer) {
driver_->SetAuxServiceDirectory(
fidl::InterfaceHandle<fuchsia::io::Directory>(directory.TakeChannel()));
}
CodecMetrics& DeviceCtx::metrics() { return driver_->metrics(); }