blob: a6afd806b0cb57d891ce8d02a93a366d7d76700d [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/dbus/cec_service_client.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "chromeos/dbus/fake_cec_service_client.h"
#include "dbus/bus.h"
#include "dbus/message.h"
#include "dbus/object_proxy.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
namespace chromeos {
namespace {
// Translates a power state from a D-Bus response to the types exposed by
// CecServiceClient.
CecServiceClient::PowerState ConvertDBusPowerState(int32_t power_state) {
switch (power_state) {
case cecservice::kTvPowerStatusError:
return CecServiceClient::PowerState::kError;
case cecservice::kTvPowerStatusAdapterNotConfigured:
return CecServiceClient::PowerState::kAdapterNotConfigured;
case cecservice::kTvPowerStatusNoTv:
return CecServiceClient::PowerState::kNoDevice;
case cecservice::kTvPowerStatusOn:
return CecServiceClient::PowerState::kOn;
case cecservice::kTvPowerStatusStandBy:
return CecServiceClient::PowerState::kStandBy;
case cecservice::kTvPowerStatusToOn:
return CecServiceClient::PowerState::kTransitioningToOn;
case cecservice::kTvPowerStatusToStandBy:
return CecServiceClient::PowerState::kTransitioningToStandBy;
case cecservice::kTvPowerStatusUnknown:
return CecServiceClient::PowerState::kUnknown;
default:
NOTREACHED() << "Received unknown state " << power_state;
return CecServiceClient::PowerState::kUnknown;
}
}
void OnGetTvsPowerStatus(CecServiceClient::PowerStateCallback callback,
dbus::Response* response) {
if (!response) {
LOG(ERROR) << "QueryDisplayCecPowerState call failed, no response";
std::move(callback).Run({});
return;
}
dbus::MessageReader reader(response);
dbus::MessageReader array_reader(nullptr);
if (!reader.PopArray(&array_reader)) {
LOG(ERROR) << "Unable to read back array for QueryDisplayCecPowerState";
std::move(callback).Run({});
return;
}
std::vector<CecServiceClient::PowerState> result;
while (array_reader.HasMoreData()) {
int32_t low_level_power_state = -1;
if (!array_reader.PopInt32(&low_level_power_state)) {
LOG(ERROR) << "Unable to pop state for QueryDisplayCecPowerState";
std::move(callback).Run({});
return;
}
result.push_back(ConvertDBusPowerState(low_level_power_state));
}
std::move(callback).Run(result);
}
// Real implementation of CecServiceClient.
class CecServiceClientImpl : public CecServiceClient {
public:
CecServiceClientImpl() = default;
~CecServiceClientImpl() override = default;
void SendStandBy() override {
dbus::MethodCall method_call(cecservice::kCecServiceInterface,
cecservice::kSendStandByToAllDevicesMethod);
cec_service_proxy_->CallMethod(&method_call,
dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
base::DoNothing());
}
void SendWakeUp() override {
dbus::MethodCall method_call(cecservice::kCecServiceInterface,
cecservice::kSendWakeUpToAllDevicesMethod);
cec_service_proxy_->CallMethod(&method_call,
dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
base::DoNothing());
}
void QueryDisplayCecPowerState(PowerStateCallback callback) override {
dbus::MethodCall query_method(cecservice::kCecServiceInterface,
cecservice::kGetTvsPowerStatus);
cec_service_proxy_->CallMethod(
&query_method, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
base::BindOnce(&OnGetTvsPowerStatus, std::move(callback)));
}
protected:
void Init(dbus::Bus* bus) override {
cec_service_proxy_ =
bus->GetObjectProxy(cecservice::kCecServiceName,
dbus::ObjectPath(cecservice::kCecServicePath));
}
private:
scoped_refptr<dbus::ObjectProxy> cec_service_proxy_;
DISALLOW_COPY_AND_ASSIGN(CecServiceClientImpl);
};
} // namespace
////////////////////////////////////////////////////////////////////////////////
// CecServiceClient
CecServiceClient::CecServiceClient() = default;
CecServiceClient::~CecServiceClient() = default;
// static
std::unique_ptr<CecServiceClient> CecServiceClient::Create(
DBusClientImplementationType type) {
if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
return std::make_unique<CecServiceClientImpl>();
DCHECK_EQ(FAKE_DBUS_CLIENT_IMPLEMENTATION, type);
return std::make_unique<FakeCecServiceClient>();
}
} // namespace chromeos