blob: 0944d82399f6a56a42cb9fae26762d0c5befae33 [file] [log] [blame]
// Copyright 2019 The Fuchsia 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 <fidl/fuchsia.hardware.backlight/cpp/wire.h>
#include <lib/component/incoming/cpp/protocol.h>
#include <unistd.h>
#include <array>
#include <filesystem>
#include <vector>
#include <zxtest/zxtest.h>
namespace backlight {
namespace {
namespace FidlBacklight = fuchsia_hardware_backlight;
class BacklightDevice {
public:
explicit BacklightDevice(fidl::ClientEnd<FidlBacklight::Device> client_end)
: client_{std::move(client_end)} {
if (GetBrightnessNormalized(&orig_brightness_) != ZX_OK) {
printf("Error getting original brightness. Defaulting to 1.0\n");
orig_brightness_ = 1.0;
}
printf("Brightness at the start of the test: %f\n", orig_brightness_);
}
~BacklightDevice() {
printf("Restoring original brightness...\n");
if (SetBrightnessNormalized(orig_brightness_) != ZX_OK) {
printf("Error setting brightness to %f\n", orig_brightness_);
}
}
zx_status_t GetBrightnessNormalized(double* brightness) {
auto response = client_->GetStateNormalized();
zx_status_t status = response.ok() ? (response->is_error() ? response->error_value() : ZX_OK)
: response.status();
if (status != ZX_OK) {
return status;
}
*brightness = response->value()->state.brightness;
return status;
}
zx_status_t SetBrightnessNormalized(double brightness) {
FidlBacklight::wire::State state = {.backlight_on = brightness > 0, .brightness = brightness};
printf("Setting brightness to: %f\n", brightness);
auto response = client_->SetStateNormalized(state);
zx_status_t status = response.ok() ? (response->is_error() ? response->error_value() : ZX_OK)
: response.status();
return status;
}
zx_status_t GetBrightnessAbsolute(double* brightness) {
auto response = client_->GetStateAbsolute();
zx_status_t status = response.ok() ? (response->is_error() ? response->error_value() : ZX_OK)
: response.status();
if (status != ZX_OK) {
return status;
}
*brightness = response->value()->state.brightness;
return status;
}
zx_status_t SetBrightnessAbsolute(double brightness) {
FidlBacklight::wire::State state = {.backlight_on = brightness > 0, .brightness = brightness};
printf("Setting brightness to: %f nits\n", brightness);
auto response = client_->SetStateAbsolute(state);
zx_status_t status = response.ok() ? (response->is_error() ? response->error_value() : ZX_OK)
: response.status();
return status;
}
zx_status_t GetMaxAbsoluteBrightness(double* brightness) {
auto response = client_->GetMaxAbsoluteBrightness();
zx_status_t status = response.ok() ? (response->is_error() ? response->error_value() : ZX_OK)
: response.status();
if (status == ZX_OK) {
*brightness = response->value()->max_brightness;
}
return status;
}
private:
fidl::WireSyncClient<FidlBacklight::Device> client_;
double orig_brightness_;
};
class BacklightTest : public zxtest::Test {
public:
void SetUp() override {
constexpr char kDevicePath[] = "/dev/class/backlight/";
if (std::filesystem::exists(kDevicePath)) {
for (const auto& entry : std::filesystem::directory_iterator(kDevicePath)) {
printf("Found backlight device: %s\n", entry.path().c_str());
zx::result client_end = component::Connect<FidlBacklight::Device>(entry.path().c_str());
ASSERT_OK(client_end);
devices_.push_back(std::make_unique<BacklightDevice>(std::move(client_end.value())));
}
}
if (devices_.empty()) {
printf("No backlight devices found. Exiting...\n");
}
}
static double Approx(double val) { return round(val * 100.0) / 100.0; }
static void TestBrightnessNormalized(std::unique_ptr<BacklightDevice>& dev) {
std::array<double, 9> brightness_values = {0.0, 0.25, 0.5, 0.75, 1.0, 0.75, 0.5, 0.25, 0.0};
double brightness;
for (auto brt : brightness_values) {
EXPECT_OK(dev->SetBrightnessNormalized(brt));
EXPECT_OK(dev->GetBrightnessNormalized(&brightness));
EXPECT_EQ(Approx(brightness), brt);
SleepIfDelayEnabled();
}
}
static void TestBrightnessAbsolute(std::unique_ptr<BacklightDevice>& dev) {
double brightness, max_brightness;
auto status = dev->GetMaxAbsoluteBrightness(&max_brightness);
if (status == ZX_OK) {
EXPECT_GT(max_brightness, 0);
std::array<double, 9> brightness_values = {0.0, 0.25, 0.5, 0.75, 1.0, 0.75, 0.5, 0.25, 0.0};
double brightness;
for (auto brt : brightness_values) {
EXPECT_OK(dev->SetBrightnessAbsolute(brt * max_brightness));
EXPECT_OK(dev->GetBrightnessAbsolute(&brightness));
EXPECT_EQ(Approx(brightness), brt * max_brightness);
SleepIfDelayEnabled();
}
} else {
EXPECT_EQ(dev->SetBrightnessAbsolute(0), ZX_ERR_NOT_SUPPORTED);
EXPECT_EQ(dev->GetBrightnessAbsolute(&brightness), ZX_ERR_NOT_SUPPORTED);
}
}
void TestAllDevices() {
for (auto& dev : devices_) {
TestBrightnessNormalized(dev);
TestBrightnessAbsolute(dev);
}
}
static void RunWithDelays() { delayEnabled_ = true; }
static void SleepIfDelayEnabled() {
if (delayEnabled_) {
sleep(1);
}
}
private:
std::vector<std::unique_ptr<BacklightDevice>> devices_;
static bool delayEnabled_;
};
bool backlight::BacklightTest::delayEnabled_ = false;
TEST_F(BacklightTest, VaryBrightness) { TestAllDevices(); }
} // namespace
} // namespace backlight
int main(int argc, char** argv) {
int opt;
while ((opt = getopt(argc, argv, "dh")) != -1) {
switch (opt) {
case 'd':
backlight::BacklightTest::RunWithDelays();
argc--;
break;
case 'h':
default:
printf("Usage: runtests --names backlight-test [-- <options>]\n\n");
printf(
" Valid options are:\n"
" -d : By default the test runs without any delays between brightness changes.\n"
" Pass the -d argument to space the brightness changes one second apart,\n"
" so that they are visually perceptible on the screen.\n"
" -h : Print this usage text.\n\n");
return 0;
}
}
return zxtest::RunAllTests(argc, argv);
}