blob: ed89eed885174de2ad75ff513dd1f5a03e41dcd9 [file] [log] [blame]
// Copyright 2018 The Chromium 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 "chromeos/services/machine_learning/public/cpp/service_connection.h"
#include "base/no_destructor.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/machine_learning_client.h"
#include "chromeos/services/machine_learning/public/mojom/interface.mojom.h"
#include "mojo/public/cpp/platform/platform_channel.h"
#include "mojo/public/cpp/system/invitation.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
namespace chromeos {
namespace machine_learning {
/* static */
ServiceConnection* ServiceConnection::GetInstance() {
static base::NoDestructor<ServiceConnection> service_connection;
return service_connection.get();
}
void ServiceConnection::BindModelProvider(mojom::ModelProviderRequest request) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
BindMachineLearningServiceIfNeeded();
machine_learning_service_->GetModelProvider(std::move(request));
}
void ServiceConnection::BindMachineLearningServiceIfNeeded() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (machine_learning_service_) {
return;
}
mojo::PlatformChannel platform_channel;
// Prepare a Mojo invitation to send through |platform_channel|.
mojo::OutgoingInvitation invitation;
// Include an initial Mojo pipe in the invitation.
mojo::ScopedMessagePipeHandle pipe =
invitation.AttachMessagePipe(ml::kBootstrapMojoConnectionChannelToken);
mojo::OutgoingInvitation::Send(std::move(invitation),
base::kNullProcessHandle,
platform_channel.TakeLocalEndpoint());
// Bind our end of |pipe| to our MachineLearningServicePtr. The daemon should
// bind its end to a MachineLearningService implementation.
machine_learning_service_.Bind(
machine_learning::mojom::MachineLearningServicePtrInfo(std::move(pipe),
0u /* version */));
machine_learning_service_.set_connection_error_handler(base::BindOnce(
&ServiceConnection::OnConnectionError, base::Unretained(this)));
// Send the file descriptor for the other end of |platform_channel| to the
// ML service daemon over D-Bus.
DBusThreadManager::Get()->GetMachineLearningClient()->BootstrapMojoConnection(
platform_channel.TakeRemoteEndpoint().TakePlatformHandle().TakeFD(),
base::BindOnce(&ServiceConnection::OnBootstrapMojoConnectionResponse,
base::Unretained(this)));
}
ServiceConnection::ServiceConnection() {
DETACH_FROM_SEQUENCE(sequence_checker_);
}
ServiceConnection::~ServiceConnection() {}
void ServiceConnection::OnConnectionError() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// Connection errors are not expected so log a warning.
LOG(WARNING) << "ML Service Mojo connection closed";
machine_learning_service_.reset();
}
void ServiceConnection::OnBootstrapMojoConnectionResponse(const bool success) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!success) {
LOG(WARNING) << "BootstrapMojoConnection D-Bus call failed";
machine_learning_service_.reset();
}
}
} // namespace machine_learning
} // namespace chromeos