blob: cadb1aa2d991e8ea1e64413e00337c1469f255e5 [file] [log] [blame]
// Copyright 2021 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 "codec_isolate.h"
#include <fuchsia/component/cpp/fidl.h>
#include <fuchsia/component/decl/cpp/fidl.h>
#include <inttypes.h>
#include <lib/fit/defer.h>
#include <lib/syslog/cpp/macros.h>
#include <utility>
#include "src/lib/fxl/strings/string_printf.h"
std::string GetCollectionFromIsolate(IsolateType type) {
switch (type) {
case IsolateType::kSw:
return "sw-codecs";
case IsolateType::kMagma:
return "magma-codecs";
default:
return "";
}
}
void ForwardToIsolate(std::string component_url, IsolateType type,
sys::ComponentContext* component_context,
fit::function<void(fuchsia::mediacodec::CodecFactoryPtr)> connect_func,
fit::function<void(void)> failure_func) {
auto failure_defer = fit::defer_callback(std::move(failure_func));
fuchsia::component::decl::Child isolate;
uint64_t rand_num;
zx_cprng_draw(&rand_num, sizeof rand_num);
std::string msg = fxl::StringPrintf("isolate-%" PRIu64 "", rand_num);
isolate.set_name(msg);
isolate.set_url(std::move(component_url));
isolate.set_startup(fuchsia::component::decl::StartupMode::LAZY);
isolate.set_on_terminate(fuchsia::component::decl::OnTerminate::NONE);
fuchsia::component::decl::CollectionRef collection{.name = GetCollectionFromIsolate(type)};
fuchsia::component::RealmPtr realm_svc;
fuchsia::component::CreateChildArgs child_args;
child_args.set_numbered_handles(std::vector<fuchsia::process::HandleInfo>());
component_context->svc()->Connect(realm_svc.NewRequest());
realm_svc.set_error_handler([](zx_status_t err) {
FX_LOGS(WARNING) << "FIDL error using fuchsia.component.Realm protocol: " << err;
});
realm_svc->CreateChild(
collection, std::move(isolate), std::move(child_args),
[collection, realm_svc = std::move(realm_svc), connect_func = std::move(connect_func),
failure_defer = std::move(failure_defer),
msg = std::move(msg)](fuchsia::component::Realm_CreateChild_Result res) mutable {
if (res.is_err()) {
FX_LOGS(WARNING) << "Isolate creation request failed for " << msg;
return;
}
fidl::InterfaceHandle<fuchsia::io::Directory> exposed_dir;
fuchsia::component::decl::ChildRef child = fuchsia::component::decl::ChildRef{
.name = msg,
.collection = collection.name,
};
realm_svc->OpenExposedDir(
child, exposed_dir.NewRequest(),
[realm_svc = std::move(realm_svc), exposed_dir = std::move(exposed_dir),
connect_func = std::move(connect_func), failure_defer = std::move(failure_defer)](
fuchsia::component::Realm_OpenExposedDir_Result res) mutable {
if (res.is_err()) {
FX_LOGS(WARNING) << "OpenExposedDir on isolate failed";
return;
}
fuchsia::mediacodec::CodecFactoryPtr factory_delegate;
auto delegate_req = factory_delegate.NewRequest();
sys::ServiceDirectory child_services(std::move(exposed_dir));
zx_status_t connect_res =
child_services.Connect(std::move(delegate_req),
// TODO(dustingreen): Might be helpful (for debugging
// maybe) to change this name to distinguish these delegate
// CodecFactory(s) from the main CodecFactory service.
fuchsia::mediacodec::CodecFactory::Name_);
if (connect_res == ZX_OK) {
connect_func(std::move(factory_delegate));
failure_defer.cancel();
} else {
FX_LOGS(WARNING) << "Connection to isolate services failed with error code: "
<< connect_res;
}
});
});
}