blob: 0d3f27c036896824854e0582d5f96dfcf1416815 [file]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromeos/ash/services/orca/orca_library.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/scoped_native_library.h"
#include "base/types/expected.h"
#include "chromeos/ash/services/orca/public/cpp/orca_entry.h"
#include "mojo/public/c/system/thunks.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
namespace ash::orca {
namespace {
base::FilePath GetDefaultOrcaLibraryPath() {
// A relative path is fine because base::ScopedNativeLibrary will look for the
// library in an architecture-dependent system path.
return base::FilePath("libimedecoder.so");
}
logging::LogSeverity ConvertLogSeverity(OrcaLogSeverity severity) {
switch (severity) {
case OrcaLogSeverity::ORCA_LOG_SEVERITY_WARNING:
return logging::LOGGING_WARNING;
case OrcaLogSeverity::ORCA_LOG_SEVERITY_ERROR:
return logging::LOGGING_ERROR;
}
NOTREACHED();
}
void DefaultLogSink(logging::LogSeverity severity, std::string_view message) {
switch (severity) {
case logging::LOGGING_WARNING:
LOG(WARNING) << message;
break;
case logging::LOGGING_ERROR:
LOG(ERROR) << message;
break;
default:
NOTREACHED();
}
}
std::unique_ptr<OrcaLogger> CreateOrcaLogger(OrcaLibrary::LogSink* log_sink) {
auto logger = std::make_unique<OrcaLogger>();
logger->user_data = reinterpret_cast<void*>(log_sink),
logger->log = [](OrcaLogger* self, OrcaLogSeverity severity,
const char* message) {
reinterpret_cast<OrcaLibrary::LogSink*>(self->user_data)
->Run(ConvertLogSeverity(severity), message);
};
return logger;
}
} // namespace
OrcaLibrary::OrcaLibrary() : OrcaLibrary(GetDefaultOrcaLibraryPath()) {}
OrcaLibrary::OrcaLibrary(const base::FilePath& library_path)
: OrcaLibrary(library_path, base::BindRepeating(DefaultLogSink)) {}
OrcaLibrary::OrcaLibrary(const base::FilePath& library_path, LogSink log_sink)
: library_path_(library_path),
log_sink_(std::move(log_sink)),
orca_logger_(CreateOrcaLogger(&log_sink_)) {}
OrcaLibrary::~OrcaLibrary() {
if (!library_.is_valid()) {
return;
}
if (auto* reset_function = reinterpret_cast<decltype(OrcaResetService)*>(
library_.GetFunctionPointer("OrcaResetService"))) {
reset_function();
}
}
base::expected<void, OrcaLibrary::BindError> OrcaLibrary::BindReceiver(
mojo::PendingReceiver<mojom::OrcaService> receiver) {
library_ = base::ScopedNativeLibrary(library_path_);
if (!library_.is_valid()) {
return base::unexpected(BindError{
.code = BindErrorCode::kLoadFailed,
.message = library_.GetError()->ToString(),
});
}
auto* bind_function = reinterpret_cast<decltype(OrcaBindServiceV2)*>(
library_.GetFunctionPointer("OrcaBindServiceV2"));
if (!bind_function) {
return base::unexpected(
BindError{.code = BindErrorCode::kGetFunctionPointerFailed});
}
const MojoSystemThunks2* mojo_thunks = MojoEmbedderGetSystemThunks2();
const MojoHandle receiver_handle = receiver.PassPipe().release().value();
if (OrcaBindServiceStatus code =
bind_function(mojo_thunks, receiver_handle, orca_logger_.get());
code != OrcaBindServiceStatus::ORCA_BIND_SERVICE_STATUS_OK) {
return base::unexpected(BindError{.code = BindErrorCode::kBindFailed});
}
return base::ok();
}
} // namespace ash::orca