blob: 52a0955bf72348ba10c292feeafb4c03d4f84ec9 [file] [log] [blame]
// Copyright 2014 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 "ash/dbus/display_service_provider.h"
#include <utility>
#include "ash/public/interfaces/ash_display_controller.mojom.h"
#include "ash/public/interfaces/constants.mojom.h"
#include "ash/shell.h"
#include "ash/wm/screen_dimmer.h"
#include "base/bind.h"
#include "base/callback.h"
#include "dbus/message.h"
#include "services/service_manager/public/cpp/connector.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
#include "ui/base/user_activity/user_activity_detector.h"
#include "ui/display/manager/display_configurator.h"
namespace ash {
namespace {
void OnDisplayOwnershipChanged(
const dbus::ExportedObject::ResponseSender& response_sender,
std::unique_ptr<dbus::Response> response,
bool status) {
dbus::MessageWriter writer(response.get());
writer.AppendBool(status);
response_sender.Run(std::move(response));
}
} // namespace
class DisplayServiceProvider::Impl {
public:
Impl() = default;
~Impl() = default;
void SetDimming(bool dimmed);
void TakeDisplayOwnership(base::OnceCallback<void(bool)> callback);
void ReleaseDisplayOwnership(base::OnceCallback<void(bool)> callback);
private:
// Tests may not have a service_manager::Connector. Connect() is called
// whenever ash_display_controller_ is used to lazily connect as needed.
bool Connect();
mojom::AshDisplayControllerPtr ash_display_controller_;
std::unique_ptr<ScreenDimmer> screen_dimmer_;
DISALLOW_COPY_AND_ASSIGN(Impl);
};
bool DisplayServiceProvider::Impl::Connect() {
if (ash_display_controller_)
return true;
Shell::Get()->connector()->BindInterface(mojom::kServiceName,
&ash_display_controller_);
return !!ash_display_controller_;
}
void DisplayServiceProvider::Impl::SetDimming(bool dimmed) {
if (!screen_dimmer_) {
screen_dimmer_ =
std::make_unique<ScreenDimmer>(ScreenDimmer::Container::ROOT);
}
screen_dimmer_->SetDimming(dimmed);
}
void DisplayServiceProvider::Impl::TakeDisplayOwnership(
base::OnceCallback<void(bool)> callback) {
if (!Connect()) {
LOG(ERROR) << "Display Controller not connected";
std::move(callback).Run(false);
return;
}
ash_display_controller_->TakeDisplayControl(std::move(callback));
}
void DisplayServiceProvider::Impl::ReleaseDisplayOwnership(
base::OnceCallback<void(bool)> callback) {
if (!Connect()) {
LOG(ERROR) << "Display Controller not connected";
std::move(callback).Run(false);
return;
}
ash_display_controller_->RelinquishDisplayControl(std::move(callback));
}
DisplayServiceProvider::DisplayServiceProvider()
: impl_(std::make_unique<Impl>()), weak_ptr_factory_(this) {}
DisplayServiceProvider::~DisplayServiceProvider() = default;
void DisplayServiceProvider::Start(
scoped_refptr<dbus::ExportedObject> exported_object) {
exported_object->ExportMethod(
chromeos::kDisplayServiceInterface,
chromeos::kDisplayServiceSetPowerMethod,
base::BindRepeating(&DisplayServiceProvider::SetDisplayPower,
weak_ptr_factory_.GetWeakPtr()),
base::BindRepeating(&DisplayServiceProvider::OnExported,
weak_ptr_factory_.GetWeakPtr()));
exported_object->ExportMethod(
chromeos::kDisplayServiceInterface,
chromeos::kDisplayServiceSetSoftwareDimmingMethod,
base::BindRepeating(&DisplayServiceProvider::SetDisplaySoftwareDimming,
weak_ptr_factory_.GetWeakPtr()),
base::BindRepeating(&DisplayServiceProvider::OnExported,
weak_ptr_factory_.GetWeakPtr()));
exported_object->ExportMethod(
chromeos::kDisplayServiceInterface,
chromeos::kDisplayServiceTakeOwnershipMethod,
base::BindRepeating(&DisplayServiceProvider::TakeDisplayOwnership,
weak_ptr_factory_.GetWeakPtr()),
base::BindRepeating(&DisplayServiceProvider::OnExported,
weak_ptr_factory_.GetWeakPtr()));
exported_object->ExportMethod(
chromeos::kDisplayServiceInterface,
chromeos::kDisplayServiceReleaseOwnershipMethod,
base::BindRepeating(&DisplayServiceProvider::ReleaseDisplayOwnership,
weak_ptr_factory_.GetWeakPtr()),
base::BindRepeating(&DisplayServiceProvider::OnExported,
weak_ptr_factory_.GetWeakPtr()));
}
void DisplayServiceProvider::SetDisplayPower(
dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender) {
dbus::MessageReader reader(method_call);
int int_state = 0;
if (!reader.PopInt32(&int_state)) {
LOG(ERROR) << "Unable to parse request: "
<< chromeos::kDisplayServiceSetPowerMethod;
response_sender.Run(dbus::Response::FromMethodCall(method_call));
return;
}
// Turning displays off when the device becomes idle or on just before
// we suspend may trigger a mouse move, which would then be incorrectly
// reported as user activity. Let the UserActivityDetector
// know so that it can ignore such events.
ui::UserActivityDetector::Get()->OnDisplayPowerChanging();
Shell::Get()->display_configurator()->SetDisplayPower(
static_cast<chromeos::DisplayPowerState>(int_state),
display::DisplayConfigurator::kSetDisplayPowerNoFlags,
base::BindRepeating(
[](dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender,
bool /*status*/) {
response_sender.Run(dbus::Response::FromMethodCall(method_call));
},
method_call, response_sender));
}
void DisplayServiceProvider::SetDisplaySoftwareDimming(
dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender) {
dbus::MessageReader reader(method_call);
bool dimmed = false;
if (reader.PopBool(&dimmed)) {
impl_->SetDimming(dimmed);
} else {
LOG(ERROR) << "Unable to parse request: "
<< chromeos::kDisplayServiceSetSoftwareDimmingMethod;
}
response_sender.Run(dbus::Response::FromMethodCall(method_call));
}
void DisplayServiceProvider::TakeDisplayOwnership(
dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender) {
impl_->TakeDisplayOwnership(base::BindOnce(
&OnDisplayOwnershipChanged, response_sender,
base::Passed(dbus::Response::FromMethodCall(method_call))));
}
void DisplayServiceProvider::ReleaseDisplayOwnership(
dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender) {
impl_->ReleaseDisplayOwnership(base::BindOnce(
&OnDisplayOwnershipChanged, response_sender,
base::Passed(dbus::Response::FromMethodCall(method_call))));
}
void DisplayServiceProvider::OnExported(const std::string& interface_name,
const std::string& method_name,
bool success) {
if (!success)
LOG(ERROR) << "Failed to export " << interface_name << "." << method_name;
}
} // namespace ash