Commit 5d1b216b authored by Felix Ekblom's avatar Felix Ekblom Committed by Commit Bot

Add power state query method to CecServiceClient

The new method will offer a crude way to query about the power state of
connected HDMI CEC capable displays.

BUG=b:78171027

Change-Id: Ic37abea8f300d1d22a80368acbd3f129cc5e0187
Reviewed-on: https://chromium-review.googlesource.com/1042575Reviewed-by: default avatarDan Erat <derat@chromium.org>
Reviewed-by: default avatarToni Barzic <tbarzic@chromium.org>
Commit-Queue: Felix Ekblom <felixe@chromium.org>
Cr-Commit-Position: refs/heads/master@{#556727}
parent 25f7b20e
......@@ -6,6 +6,7 @@
#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"
......@@ -20,6 +21,64 @@ 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:
......@@ -43,6 +102,14 @@ class CecServiceClientImpl : public CecServiceClient {
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_ =
......
......@@ -6,6 +6,7 @@
#define CHROMEOS_DBUS_CEC_SERVICE_CLIENT_H_
#include <memory>
#include <vector>
#include "base/macros.h"
#include "chromeos/dbus/dbus_client.h"
......@@ -25,6 +26,29 @@ class CHROMEOS_EXPORT CecServiceClient : public DBusClient {
public:
~CecServiceClient() override;
enum class PowerState {
// There was an error when querying the display.
kError,
// The kernel adapter is not configured (no EDID set).
kAdapterNotConfigured,
// No response on the CEC bus (the connection was not ACKed).
kNoDevice,
// The display is on.
kOn,
// The display is in standby.
kStandBy,
// The display is transitioning from standby to a powered on state. It's not
// guaranteed that any output is visible on the display at this stage.
kTransitioningToOn,
// The display is transitioning into standby mode.
kTransitioningToStandBy,
// A power status was read from the display but its value is unknown.
kUnknown,
};
using PowerStateCallback =
base::OnceCallback<void(const std::vector<PowerState>&)>;
// For normal usage, access the singleton via DBusThreadManager::Get().
static std::unique_ptr<CecServiceClient> Create(
DBusClientImplementationType type);
......@@ -39,6 +63,11 @@ class CHROMEOS_EXPORT CecServiceClient : public DBusClient {
// displays going into stand-by is made.
virtual void SendWakeUp() = 0;
// Queries all HDMI CEC capable displays for their current power state. The
// effects of calling the methods above should be observable through this
// inspection method.
virtual void QueryDisplayCecPowerState(PowerStateCallback callback) = 0;
protected:
CecServiceClient();
......
......@@ -4,6 +4,8 @@
#include "chromeos/dbus/fake_cec_service_client.h"
#include "base/bind.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chromeos/dbus/dbus_method_call_status.h"
namespace chromeos {
......@@ -13,24 +15,18 @@ FakeCecServiceClient::~FakeCecServiceClient() = default;
void FakeCecServiceClient::SendStandBy() {
stand_by_call_count_++;
current_state_ = kStandBy;
last_set_state_ = kStandBy;
}
void FakeCecServiceClient::SendWakeUp() {
wake_up_call_count_++;
current_state_ = kAwake;
last_set_state_ = kAwake;
}
int FakeCecServiceClient::stand_by_call_count() {
return stand_by_call_count_;
}
int FakeCecServiceClient::wake_up_call_count() {
return wake_up_call_count_;
}
FakeCecServiceClient::CurrentState FakeCecServiceClient::current_state() {
return current_state_;
void FakeCecServiceClient::QueryDisplayCecPowerState(
CecServiceClient::PowerStateCallback callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), tv_power_states_));
}
void FakeCecServiceClient::Init(dbus::Bus* bus) {}
......
......@@ -5,6 +5,8 @@
#ifndef CHROMEOS_DBUS_FAKE_CEC_SERVICE_CLIENT_H_
#define CHROMEOS_DBUS_FAKE_CEC_SERVICE_CLIENT_H_
#include <vector>
#include "base/macros.h"
#include "chromeos/dbus/cec_service_client.h"
......@@ -20,11 +22,20 @@ class CHROMEOS_EXPORT FakeCecServiceClient : public CecServiceClient {
// CecServiceClient
void SendStandBy() override;
void SendWakeUp() override;
void QueryDisplayCecPowerState(
CecServiceClient::PowerStateCallback callback) override;
int stand_by_call_count() const { return stand_by_call_count_; }
int wake_up_call_count() const { return wake_up_call_count_; }
int stand_by_call_count();
int wake_up_call_count();
CurrentState last_set_state() const { return last_set_state_; }
CurrentState current_state();
void set_tv_power_states(const std::vector<PowerState>& power_states) {
tv_power_states_ = power_states;
}
const std::vector<PowerState>& tv_power_states() const {
return tv_power_states_;
}
protected:
void Init(dbus::Bus* bus) override;
......@@ -32,7 +43,9 @@ class CHROMEOS_EXPORT FakeCecServiceClient : public CecServiceClient {
private:
int stand_by_call_count_ = 0;
int wake_up_call_count_ = 0;
CurrentState current_state_ = kUndefined;
CurrentState last_set_state_ = kUndefined;
std::vector<PowerState> tv_power_states_;
DISALLOW_COPY_AND_ASSIGN(FakeCecServiceClient);
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment