| // Copyright (c) 2012 The Chromium OS 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 "power_manager/powerd/policy/internal_backlight_controller.h" |
| |
| #include <cmath> |
| #include <memory> |
| #include <string> |
| |
| #include <base/logging.h> |
| #include <chromeos/dbus/service_constants.h> |
| #include <dbus/message.h> |
| #include <gtest/gtest.h> |
| |
| #include "power_manager/common/clock.h" |
| #include "power_manager/common/fake_prefs.h" |
| #include "power_manager/common/power_constants.h" |
| #include "power_manager/powerd/policy/backlight_controller_observer_stub.h" |
| #include "power_manager/powerd/policy/backlight_controller_test_util.h" |
| #include "power_manager/powerd/system/ambient_light_sensor_stub.h" |
| #include "power_manager/powerd/system/backlight_stub.h" |
| #include "power_manager/powerd/system/dbus_wrapper_stub.h" |
| #include "power_manager/powerd/system/display/display_power_setter_stub.h" |
| #include "power_manager/proto_bindings/backlight.pb.h" |
| #include "power_manager/proto_bindings/policy.pb.h" |
| |
| namespace power_manager { |
| namespace policy { |
| |
| namespace { |
| |
| // Number of ambient light sensor samples that should be supplied in order to |
| // trigger an update to InternalBacklightController's ALS brightness percent. |
| const int kAlsSamplesToTriggerAdjustment = 2; |
| |
| } // namespace |
| |
| class InternalBacklightControllerTest : public ::testing::Test { |
| public: |
| InternalBacklightControllerTest() |
| : backlight_(max_backlight_level_, initial_backlight_level_), |
| light_sensor_(initial_als_lux_) {} |
| |
| protected: |
| // Initializes |dbus_wrapper_| and |controller_| and sends the controller |
| // power source and ambient light events such that it should make its first |
| // adjustment to the backlight brightness. Can be called multiple times within |
| // a test. |
| virtual void Init(PowerSource power_source) { |
| if (default_min_visible_level_ > 0) { |
| prefs_.SetInt64(kMinVisibleBacklightLevelPref, |
| default_min_visible_level_); |
| } |
| prefs_.SetString(kInternalBacklightAlsStepsPref, default_als_steps_); |
| prefs_.SetString(kInternalBacklightNoAlsAcBrightnessPref, |
| default_no_als_ac_brightness_); |
| prefs_.SetString(kInternalBacklightNoAlsBatteryBrightnessPref, |
| default_no_als_battery_brightness_); |
| backlight_.set_max_level(max_backlight_level_); |
| backlight_.set_current_level(initial_backlight_level_); |
| light_sensor_.set_lux(initial_als_lux_); |
| prefs_.SetDouble(kAlsSmoothingConstantPref, 1.0); |
| |
| controller_ = std::make_unique<InternalBacklightController>(); |
| if (!init_time_.is_null()) |
| controller_->clock()->set_current_time_for_testing(init_time_); |
| |
| dbus_wrapper_ = std::make_unique<system::DBusWrapperStub>(); |
| controller_->Init( |
| &backlight_, &prefs_, pass_light_sensor_ ? &light_sensor_ : nullptr, |
| &display_power_setter_, dbus_wrapper_.get(), LidState::OPEN); |
| |
| if (report_initial_power_source_) |
| controller_->HandlePowerSourceChange(power_source); |
| if (pass_light_sensor_ && report_initial_als_reading_) |
| light_sensor_.NotifyObservers(); |
| } |
| |
| // Maps |percent| to a |controller_|-designated level in the range [0, |
| // max_backlight_level_]. |
| int64_t PercentToLevel(double percent) { |
| return controller_->PercentToLevel(percent); |
| } |
| |
| // Returns |controller_|'s current brightness percent. |
| double GetBrightnessPercent() { |
| double percent = -1.0; |
| EXPECT_TRUE(controller_->GetBrightnessPercent(&percent)); |
| return percent; |
| } |
| |
| // Max and initial brightness levels for |backlight_|. |
| int64_t max_backlight_level_ = 1024; |
| int64_t initial_backlight_level_ = 512; |
| |
| // Time that should be used as "now" when |controller_| is initialized. |
| // If unset, the real time will be used. |
| base::TimeTicks init_time_; |
| |
| // Should Init() pass |light_sensor_| to |controller_|? |
| bool pass_light_sensor_ = true; |
| |
| // Initial lux level reported by |light_sensor_|. |
| int initial_als_lux_ = 0; |
| |
| // Should Init() tell |controller_| about an initial ambient light |
| // reading and power source change? |
| bool report_initial_als_reading_ = true; |
| bool report_initial_power_source_ = true; |
| |
| // Default values for prefs. Applied when Init() is called. |
| int64_t default_min_visible_level_ = -1; // Unset if non-positive. |
| std::string default_als_steps_ = "50.0 -1 400\n90.0 100 -1"; |
| std::string default_no_als_ac_brightness_ = "80.0"; |
| std::string default_no_als_battery_brightness_ = "60.0"; |
| |
| FakePrefs prefs_; |
| system::BacklightStub backlight_; |
| system::AmbientLightSensorStub light_sensor_; |
| system::DisplayPowerSetterStub display_power_setter_; |
| std::unique_ptr<system::DBusWrapperStub> dbus_wrapper_; |
| std::unique_ptr<InternalBacklightController> controller_; |
| }; |
| |
| TEST_F(InternalBacklightControllerTest, IncreaseAndDecreaseBrightness) { |
| default_min_visible_level_ = 100; |
| default_als_steps_ = "50.0 -1 -1"; |
| Init(PowerSource::BATTERY); |
| ASSERT_EQ(default_min_visible_level_, |
| PercentToLevel(InternalBacklightController::kMinVisiblePercent)); |
| const int64_t kAlsLevel = PercentToLevel(50.0); |
| EXPECT_EQ(kAlsLevel, backlight_.current_level()); |
| |
| // Check that the first step increases the brightness and emits a signal; |
| // within the loop we'll just ensure that the brightness never decreases. |
| dbus_wrapper_->ClearSentSignals(); |
| test::CallIncreaseScreenBrightness(dbus_wrapper_.get()); |
| EXPECT_GT(backlight_.current_level(), kAlsLevel); |
| test::CheckBrightnessChangedSignal( |
| dbus_wrapper_.get(), 0, kScreenBrightnessChangedSignal, |
| GetBrightnessPercent(), BacklightBrightnessChange_Cause_USER_REQUEST); |
| for (int i = 0; i < InternalBacklightController::kMaxBrightnessSteps; ++i) { |
| int64_t old_level = backlight_.current_level(); |
| test::CallIncreaseScreenBrightness(dbus_wrapper_.get()); |
| EXPECT_GE(backlight_.current_level(), old_level); |
| } |
| EXPECT_EQ(max_backlight_level_, backlight_.current_level()); |
| |
| // A no-op increase should still emit a signal. |
| dbus_wrapper_->ClearSentSignals(); |
| test::CallIncreaseScreenBrightness(dbus_wrapper_.get()); |
| test::CheckBrightnessChangedSignal( |
| dbus_wrapper_.get(), 0, kScreenBrightnessChangedSignal, 100.0, |
| BacklightBrightnessChange_Cause_USER_REQUEST); |
| |
| // Now do the same checks in the opposite direction. The controller |
| // should stop at the minimum visible level if |allow_off| is false. |
| test::CallDecreaseScreenBrightness(dbus_wrapper_.get(), |
| false /* allow_off */); |
| EXPECT_LT(backlight_.current_level(), max_backlight_level_); |
| for (int i = 0; i < InternalBacklightController::kMaxBrightnessSteps; ++i) { |
| int64_t old_level = backlight_.current_level(); |
| test::CallDecreaseScreenBrightness(dbus_wrapper_.get(), |
| false /* allow_off */); |
| EXPECT_LE(backlight_.current_level(), old_level); |
| } |
| EXPECT_EQ(default_min_visible_level_, backlight_.current_level()); |
| |
| // One more request with |allow_off| should go to 0. |
| test::CallDecreaseScreenBrightness(dbus_wrapper_.get(), true /* allow_off */); |
| EXPECT_EQ(0, backlight_.current_level()); |
| EXPECT_EQ(chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON, |
| display_power_setter_.state()); |
| EXPECT_EQ(kFastBacklightTransitionMs, |
| display_power_setter_.delay().InMilliseconds()); |
| |
| // One increase request should raise the brightness to the minimum |
| // visible level, while a second one should increase it above that. |
| test::CallIncreaseScreenBrightness(dbus_wrapper_.get()); |
| EXPECT_EQ(default_min_visible_level_, backlight_.current_level()); |
| EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON, display_power_setter_.state()); |
| EXPECT_EQ(0, display_power_setter_.delay().InMilliseconds()); |
| test::CallIncreaseScreenBrightness(dbus_wrapper_.get()); |
| EXPECT_GT(backlight_.current_level(), default_min_visible_level_); |
| |
| // Start at 3/4 of a step above the middle step. After a decrease request, the |
| // brightness should be snapped to the middle step. |
| const double kStep = 100.0 / InternalBacklightController::kMaxBrightnessSteps; |
| const double kMiddlePercent = |
| kStep * InternalBacklightController::kMaxBrightnessSteps / 2; |
| test::CallSetScreenBrightness( |
| dbus_wrapper_.get(), kMiddlePercent + 0.75 * kStep, |
| SetBacklightBrightnessRequest_Transition_INSTANT, |
| SetBacklightBrightnessRequest_Cause_USER_REQUEST); |
| ASSERT_EQ(PercentToLevel(kMiddlePercent + 0.75 * kStep), |
| backlight_.current_level()); |
| test::CallDecreaseScreenBrightness(dbus_wrapper_.get(), true /* allow_off */); |
| EXPECT_EQ(PercentToLevel(kMiddlePercent), backlight_.current_level()); |
| |
| // Start at 1/4 of a step below the middle step. After an increase request, |
| // the brightness should be snapped to one step above the middle step. |
| test::CallSetScreenBrightness( |
| dbus_wrapper_.get(), kMiddlePercent - 0.25 * kStep, |
| SetBacklightBrightnessRequest_Transition_INSTANT, |
| SetBacklightBrightnessRequest_Cause_USER_REQUEST); |
| ASSERT_EQ(PercentToLevel(kMiddlePercent - 0.25 * kStep), |
| backlight_.current_level()); |
| test::CallIncreaseScreenBrightness(dbus_wrapper_.get()); |
| EXPECT_EQ(PercentToLevel(kMiddlePercent + kStep), backlight_.current_level()); |
| } |
| |
| // Test that InternalBacklightController notifies its observer in response to |
| // brightness changes. |
| TEST_F(InternalBacklightControllerTest, NotifyObserver) { |
| default_min_visible_level_ = 100; |
| default_als_steps_ = "50.0 -1 200\n75.0 100 -1"; |
| Init(PowerSource::BATTERY); |
| EXPECT_EQ(PercentToLevel(50.0), backlight_.current_level()); |
| |
| BacklightControllerObserverStub observer; |
| controller_->AddObserver(&observer); |
| |
| // Send enough ambient light sensor samples to trigger a brightness change. |
| observer.Clear(); |
| int64_t old_level = backlight_.current_level(); |
| light_sensor_.set_lux(300); |
| for (int i = 0; i < kAlsSamplesToTriggerAdjustment; ++i) |
| light_sensor_.NotifyObservers(); |
| ASSERT_NE(old_level, backlight_.current_level()); |
| ASSERT_EQ(1, static_cast<int>(observer.changes().size())); |
| EXPECT_EQ(backlight_.current_level(), |
| PercentToLevel(observer.changes()[0].percent)); |
| EXPECT_EQ(BacklightBrightnessChange_Cause_AMBIENT_LIGHT_CHANGED, |
| observer.changes()[0].cause); |
| EXPECT_EQ(controller_.get(), observer.changes()[0].source); |
| |
| // Increase the brightness and check that the observer is notified. |
| observer.Clear(); |
| test::CallIncreaseScreenBrightness(dbus_wrapper_.get()); |
| ASSERT_EQ(1, static_cast<int>(observer.changes().size())); |
| EXPECT_EQ(backlight_.current_level(), |
| PercentToLevel(observer.changes()[0].percent)); |
| EXPECT_EQ(BacklightBrightnessChange_Cause_USER_REQUEST, |
| observer.changes()[0].cause); |
| EXPECT_EQ(controller_.get(), observer.changes()[0].source); |
| |
| // Decrease the brightness. |
| observer.Clear(); |
| test::CallDecreaseScreenBrightness(dbus_wrapper_.get(), true /* allow_off */); |
| ASSERT_EQ(1, static_cast<int>(observer.changes().size())); |
| EXPECT_EQ(backlight_.current_level(), |
| PercentToLevel(observer.changes()[0].percent)); |
| EXPECT_EQ(BacklightBrightnessChange_Cause_USER_REQUEST, |
| observer.changes()[0].cause); |
| EXPECT_EQ(controller_.get(), observer.changes()[0].source); |
| |
| // Set the brightness to a lower level. |
| observer.Clear(); |
| const double kLowPercent = 40.0; |
| test::CallSetScreenBrightness( |
| dbus_wrapper_.get(), kLowPercent, |
| SetBacklightBrightnessRequest_Transition_INSTANT, |
| SetBacklightBrightnessRequest_Cause_USER_REQUEST); |
| ASSERT_EQ(1, static_cast<int>(observer.changes().size())); |
| EXPECT_EQ(backlight_.current_level(), |
| PercentToLevel(observer.changes()[0].percent)); |
| EXPECT_EQ(BacklightBrightnessChange_Cause_USER_REQUEST, |
| observer.changes()[0].cause); |
| EXPECT_EQ(controller_.get(), observer.changes()[0].source); |
| |
| // Dim the backlight. |
| observer.Clear(); |
| controller_->SetDimmedForInactivity(true); |
| ASSERT_EQ(1, static_cast<int>(observer.changes().size())); |
| EXPECT_EQ(backlight_.current_level(), |
| PercentToLevel(observer.changes()[0].percent)); |
| EXPECT_EQ(BacklightBrightnessChange_Cause_USER_INACTIVITY, |
| observer.changes()[0].cause); |
| EXPECT_EQ(controller_.get(), observer.changes()[0].source); |
| |
| controller_->RemoveObserver(&observer); |
| } |
| |
| // Test the case where the minimum visible backlight level matches the maximum |
| // level exposed by hardware. |
| TEST_F(InternalBacklightControllerTest, MinBrightnessLevelMatchesMax) { |
| default_min_visible_level_ = max_backlight_level_; |
| Init(PowerSource::AC); |
| |
| // Decrease the brightness with allow_off=false. |
| test::CallDecreaseScreenBrightness(dbus_wrapper_.get(), |
| false /* allow_off */); |
| EXPECT_EQ(default_min_visible_level_, backlight_.current_level()); |
| |
| // Decrease again with allow_off=true. |
| test::CallDecreaseScreenBrightness(dbus_wrapper_.get(), true /* allow_off */); |
| EXPECT_EQ(0, backlight_.current_level()); |
| } |
| |
| // Test the saved brightness level before and after suspend. |
| TEST_F(InternalBacklightControllerTest, SuspendBrightnessLevel) { |
| Init(PowerSource::AC); |
| const int64_t initial_level = backlight_.current_level(); |
| |
| // Test suspend and resume. When suspending, the previously-current |
| // brightness level should be saved as the resume level. |
| display_power_setter_.reset_num_power_calls(); |
| controller_->SetSuspended(true); |
| EXPECT_EQ(0, display_power_setter_.num_power_calls()); |
| EXPECT_EQ(0, backlight_.current_level()); |
| EXPECT_EQ(0, backlight_.current_interval().InMilliseconds()); |
| |
| controller_->SetSuspended(false); |
| EXPECT_EQ(initial_level, backlight_.current_level()); |
| EXPECT_EQ(0, backlight_.current_interval().InMilliseconds()); |
| EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON, display_power_setter_.state()); |
| EXPECT_EQ(0, display_power_setter_.delay().InMilliseconds()); |
| |
| // Test idling into suspend state. The backlight should be at 0% after the |
| // display is turned off. |
| controller_->SetDimmedForInactivity(true); |
| EXPECT_LT(backlight_.current_level(), initial_level); |
| |
| // The displays are turned off for the idle-off state. |
| controller_->SetOffForInactivity(true); |
| EXPECT_EQ(0, backlight_.current_level()); |
| EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_OFF, display_power_setter_.state()); |
| |
| // The power manager shouldn't change the display power before |
| // suspending; Chrome will turn the displays on (without any involvement |
| // from powerd) so that they come back up in the correct state after |
| // resuming. |
| display_power_setter_.reset_num_power_calls(); |
| controller_->SetSuspended(true); |
| EXPECT_EQ(0, display_power_setter_.num_power_calls()); |
| EXPECT_EQ(0, backlight_.current_level()); |
| |
| // Test resume. |
| controller_->SetDimmedForInactivity(false); |
| controller_->SetOffForInactivity(false); |
| controller_->SetSuspended(false); |
| EXPECT_EQ(initial_level, backlight_.current_level()); |
| EXPECT_EQ(0, backlight_.current_interval().InMilliseconds()); |
| EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON, display_power_setter_.state()); |
| EXPECT_EQ(0, display_power_setter_.delay().InMilliseconds()); |
| } |
| |
| // Test that we use a linear mapping between brightness levels and percentages |
| // when a small range of levels is exposed by the hardware. |
| TEST_F(InternalBacklightControllerTest, LinearMappingForSmallBacklightRange) { |
| max_backlight_level_ = initial_backlight_level_ = 10; |
| Init(PowerSource::BATTERY); |
| |
| // The minimum visible level should use the bottom brightness step's |
| // percentage, and above it, there should be a linear mapping between levels |
| // and percentages. |
| const double kMinVisiblePercent = |
| InternalBacklightController::kMinVisiblePercent; |
| for (int i = 1; i <= max_backlight_level_; ++i) { |
| double percent = kMinVisiblePercent + (100.0 - kMinVisiblePercent) * |
| (i - 1) / |
| (max_backlight_level_ - 1); |
| EXPECT_EQ(static_cast<int64_t>(i), PercentToLevel(percent)); |
| } |
| } |
| |
| TEST_F(InternalBacklightControllerTest, NonLinearMapping) { |
| // We should use a non-linear mapping that provides more granularity at |
| // the bottom end when a large range is exposed. |
| max_backlight_level_ = initial_backlight_level_ = 1000; |
| Init(PowerSource::BATTERY); |
| |
| EXPECT_EQ(0, PercentToLevel(0.0)); |
| EXPECT_LT(PercentToLevel(50.0), max_backlight_level_ / 2); |
| EXPECT_EQ(max_backlight_level_, PercentToLevel(100.0)); |
| } |
| |
| TEST_F(InternalBacklightControllerTest, AmbientLightTransitions) { |
| initial_backlight_level_ = max_backlight_level_; |
| default_als_steps_ = "50.0 -1 200\n75.0 100 -1"; |
| report_initial_als_reading_ = false; |
| Init(PowerSource::AC); |
| |
| // The controller should leave the initial brightness unchanged before it's |
| // received a reading from the ambient light sensor. |
| EXPECT_EQ(initial_backlight_level_, backlight_.current_level()); |
| EXPECT_EQ(0, controller_->GetNumAmbientLightSensorAdjustments()); |
| |
| // After getting the first reading from the sensor, we should do a slow |
| // transition to the lower level. The initial adjustment doesn't contribute to |
| // the adjustment count. |
| light_sensor_.NotifyObservers(); |
| EXPECT_EQ(PercentToLevel(50.0), backlight_.current_level()); |
| EXPECT_EQ(kSlowBacklightTransitionMs, |
| backlight_.current_interval().InMilliseconds()); |
| EXPECT_EQ(0, controller_->GetNumAmbientLightSensorAdjustments()); |
| |
| // Pass a bunch of higher readings and check that we slowly increase the |
| // brightness. |
| light_sensor_.set_lux(400); |
| for (int i = 0; i < kAlsSamplesToTriggerAdjustment; ++i) |
| light_sensor_.NotifyObservers(); |
| EXPECT_EQ(PercentToLevel(75.0), backlight_.current_level()); |
| EXPECT_EQ(kSlowBacklightTransitionMs, |
| backlight_.current_interval().InMilliseconds()); |
| EXPECT_EQ(1, controller_->GetNumAmbientLightSensorAdjustments()); |
| |
| // Check that the adjustment count is reset when a new session starts. |
| controller_->HandleSessionStateChange(SessionState::STARTED); |
| EXPECT_EQ(0, controller_->GetNumAmbientLightSensorAdjustments()); |
| } |
| |
| TEST_F(InternalBacklightControllerTest, PowerSourceChangeNotReportedAsAmbient) { |
| // Set a single step for ambient-light-controlled brightness levels, using 60% |
| // while on AC and 50% while on battery. |
| initial_backlight_level_ = max_backlight_level_; |
| default_als_steps_ = "60.0 50.0 -1 -1"; |
| Init(PowerSource::AC); |
| ASSERT_EQ(PercentToLevel(60.0), backlight_.current_level()); |
| EXPECT_EQ(0, controller_->GetNumAmbientLightSensorAdjustments()); |
| |
| // The brightness should be updated after switching to battery power, but the |
| // change shouldn't be reported as having been triggered by the ambient light |
| // sensor. |
| controller_->HandlePowerSourceChange(PowerSource::BATTERY); |
| ASSERT_EQ(PercentToLevel(50.0), backlight_.current_level()); |
| EXPECT_EQ(0, controller_->GetNumAmbientLightSensorAdjustments()); |
| } |
| |
| TEST_F(InternalBacklightControllerTest, TurnDisplaysOffWhenShuttingDown) { |
| Init(PowerSource::AC); |
| |
| // When the backlight controller is told that the system is shutting down, it |
| // should turn off all displays. |
| controller_->SetShuttingDown(true); |
| EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_OFF, display_power_setter_.state()); |
| EXPECT_EQ(0, display_power_setter_.delay().InMilliseconds()); |
| |
| // This isn't expected, but if the state changes after we start shutting down, |
| // the displays should be turned back on. |
| controller_->SetShuttingDown(false); |
| EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON, display_power_setter_.state()); |
| EXPECT_EQ(0, display_power_setter_.delay().InMilliseconds()); |
| } |
| |
| // Test that HandlePowerSourceChange() uses the same user-set brightness level |
| // when the computer is plugged and unplugged. |
| TEST_F(InternalBacklightControllerTest, TestPlugAndUnplug) { |
| Init(PowerSource::BATTERY); |
| |
| // A custom level set while using battery power should be used after switching |
| // to AC. |
| const double kFirstPercent = 40.0; |
| test::CallSetScreenBrightness( |
| dbus_wrapper_.get(), kFirstPercent, |
| SetBacklightBrightnessRequest_Transition_INSTANT, |
| SetBacklightBrightnessRequest_Cause_USER_REQUEST); |
| EXPECT_EQ(PercentToLevel(kFirstPercent), backlight_.current_level()); |
| controller_->HandlePowerSourceChange(PowerSource::AC); |
| EXPECT_EQ(PercentToLevel(kFirstPercent), backlight_.current_level()); |
| |
| // Ditto for switching from AC to battery. |
| const double kSecondPercent = 60.0; |
| test::CallSetScreenBrightness( |
| dbus_wrapper_.get(), kSecondPercent, |
| SetBacklightBrightnessRequest_Transition_INSTANT, |
| SetBacklightBrightnessRequest_Cause_USER_REQUEST); |
| EXPECT_EQ(PercentToLevel(kSecondPercent), backlight_.current_level()); |
| controller_->HandlePowerSourceChange(PowerSource::BATTERY); |
| EXPECT_EQ(PercentToLevel(kSecondPercent), backlight_.current_level()); |
| } |
| |
| TEST_F(InternalBacklightControllerTest, TestDimming) { |
| default_als_steps_ = "50.0 -1 200\n75.0 100 -1"; |
| Init(PowerSource::AC); |
| int64_t bottom_als_level = PercentToLevel(50.0); |
| EXPECT_EQ(bottom_als_level, backlight_.current_level()); |
| |
| controller_->SetDimmedForInactivity(true); |
| int64_t dimmed_level = backlight_.current_level(); |
| EXPECT_LT(dimmed_level, bottom_als_level); |
| EXPECT_GT(dimmed_level, 0); |
| EXPECT_EQ(kFastBacklightTransitionMs, |
| backlight_.current_interval().InMilliseconds()); |
| |
| // A second dim request shouldn't change the level. |
| controller_->SetDimmedForInactivity(true); |
| EXPECT_EQ(dimmed_level, backlight_.current_level()); |
| |
| // Ambient light readings shouldn't change the backlight level while it's |
| // dimmed. |
| light_sensor_.set_lux(400); |
| for (int i = 0; i < kAlsSamplesToTriggerAdjustment; ++i) |
| light_sensor_.NotifyObservers(); |
| EXPECT_EQ(dimmed_level, backlight_.current_level()); |
| |
| // After leaving the dimmed state, the updated ALS level should be used. |
| controller_->SetDimmedForInactivity(false); |
| EXPECT_EQ(PercentToLevel(75.0), backlight_.current_level()); |
| EXPECT_EQ(0, backlight_.current_interval().InMilliseconds()); |
| |
| // User requests shouldn't change the brightness while dimmed either. |
| controller_->SetDimmedForInactivity(true); |
| EXPECT_EQ(dimmed_level, backlight_.current_level()); |
| const double kNewUserOffset = 67.0; |
| test::CallSetScreenBrightness( |
| dbus_wrapper_.get(), kNewUserOffset, |
| SetBacklightBrightnessRequest_Transition_INSTANT, |
| SetBacklightBrightnessRequest_Cause_USER_REQUEST); |
| EXPECT_EQ(dimmed_level, backlight_.current_level()); |
| |
| // After leaving the dimmed state, the updated user level should be used. |
| controller_->SetDimmedForInactivity(false); |
| EXPECT_EQ(PercentToLevel(kNewUserOffset), backlight_.current_level()); |
| EXPECT_EQ(0, backlight_.current_interval().InMilliseconds()); |
| |
| // If the brightness is already below the dimmed level, it shouldn't be |
| // changed when dimming is requested. |
| test::CallSetScreenBrightness( |
| dbus_wrapper_.get(), InternalBacklightController::kMinVisiblePercent, |
| SetBacklightBrightnessRequest_Transition_INSTANT, |
| SetBacklightBrightnessRequest_Cause_USER_REQUEST); |
| int64_t new_undimmed_level = backlight_.current_level(); |
| ASSERT_LT(new_undimmed_level, dimmed_level); |
| controller_->SetDimmedForInactivity(true); |
| EXPECT_EQ(new_undimmed_level, backlight_.current_level()); |
| } |
| |
| TEST_F(InternalBacklightControllerTest, UserLevelOverridesAmbientLight) { |
| default_als_steps_ = "50.0 -1 200\n75.0 100 -1"; |
| Init(PowerSource::AC); |
| EXPECT_EQ(PercentToLevel(50.0), backlight_.current_level()); |
| EXPECT_EQ(0, controller_->GetNumAmbientLightSensorAdjustments()); |
| EXPECT_EQ(0, controller_->GetNumUserAdjustments()); |
| |
| const double kUserPercent = 80.0; |
| test::CallSetScreenBrightness( |
| dbus_wrapper_.get(), kUserPercent, |
| SetBacklightBrightnessRequest_Transition_INSTANT, |
| SetBacklightBrightnessRequest_Cause_USER_REQUEST); |
| EXPECT_EQ(PercentToLevel(kUserPercent), backlight_.current_level()); |
| EXPECT_EQ(1, controller_->GetNumUserAdjustments()); |
| |
| // Changes to the ambient light level shouldn't affect the backlight |
| // brightness after the user has manually set it. |
| light_sensor_.set_lux(400); |
| for (int i = 0; i < kAlsSamplesToTriggerAdjustment; ++i) |
| light_sensor_.NotifyObservers(); |
| EXPECT_EQ(PercentToLevel(kUserPercent), backlight_.current_level()); |
| EXPECT_EQ(0, controller_->GetNumAmbientLightSensorAdjustments()); |
| |
| // Starting a new session should reset the user adjustment count. |
| controller_->HandleSessionStateChange(SessionState::STARTED); |
| EXPECT_EQ(0, controller_->GetNumUserAdjustments()); |
| } |
| |
| TEST_F(InternalBacklightControllerTest, DeferInitialAdjustment) { |
| // The brightness level should remain unchanged when the power source and |
| // initial ambient light reading haven't been received. |
| report_initial_power_source_ = false; |
| report_initial_als_reading_ = false; |
| default_als_steps_ = "50.0 -1 -1"; |
| Init(PowerSource::AC); |
| EXPECT_EQ(initial_backlight_level_, backlight_.current_level()); |
| |
| // Send the power source; the level still shouldn't change. |
| controller_->HandlePowerSourceChange(PowerSource::AC); |
| EXPECT_EQ(initial_backlight_level_, backlight_.current_level()); |
| |
| // After the ambient light level is also received, the backlight should |
| // slowly transition to the ALS-derived level. |
| light_sensor_.NotifyObservers(); |
| EXPECT_EQ(PercentToLevel(50.0), backlight_.current_level()); |
| EXPECT_EQ(kSlowBacklightTransitionMs, |
| backlight_.current_interval().InMilliseconds()); |
| } |
| |
| TEST_F(InternalBacklightControllerTest, NoAmbientLightSensor) { |
| pass_light_sensor_ = false; |
| report_initial_power_source_ = false; |
| report_initial_als_reading_ = false; |
| default_no_als_ac_brightness_ = "95.0"; |
| default_no_als_battery_brightness_ = "75.0"; |
| Init(PowerSource::AC); |
| EXPECT_EQ(initial_backlight_level_, backlight_.current_level()); |
| |
| // The brightness percentages from the "no ALS" prefs should be used as |
| // starting points when there's no ALS. |
| controller_->HandlePowerSourceChange(PowerSource::AC); |
| EXPECT_EQ(PercentToLevel(95.0), backlight_.current_level()); |
| |
| controller_->HandlePowerSourceChange(PowerSource::BATTERY); |
| EXPECT_EQ(PercentToLevel(75.0), backlight_.current_level()); |
| } |
| |
| TEST_F(InternalBacklightControllerTest, NoAmbientLightSensorMultipleDefaults) { |
| // Test that different default brightness percentages can be specified for |
| // different maximum luminances (http://crosbug.com/p/28715). |
| pass_light_sensor_ = false; |
| report_initial_als_reading_ = false; |
| default_no_als_ac_brightness_ = "40.0 300\n50.0 400\n30.0"; |
| default_no_als_battery_brightness_ = "35.0 400\n25.0 300\n15.0\n"; |
| |
| Init(PowerSource::AC); |
| EXPECT_EQ(PercentToLevel(30.0), backlight_.current_level()); |
| controller_->HandlePowerSourceChange(PowerSource::BATTERY); |
| EXPECT_EQ(PercentToLevel(15.0), backlight_.current_level()); |
| |
| prefs_.SetInt64(kInternalBacklightMaxNitsPref, 300); |
| Init(PowerSource::AC); |
| EXPECT_EQ(PercentToLevel(40.0), backlight_.current_level()); |
| controller_->HandlePowerSourceChange(PowerSource::BATTERY); |
| EXPECT_EQ(PercentToLevel(25.0), backlight_.current_level()); |
| |
| prefs_.SetInt64(kInternalBacklightMaxNitsPref, 400); |
| Init(PowerSource::AC); |
| EXPECT_EQ(PercentToLevel(50.0), backlight_.current_level()); |
| controller_->HandlePowerSourceChange(PowerSource::BATTERY); |
| EXPECT_EQ(PercentToLevel(35.0), backlight_.current_level()); |
| } |
| |
| TEST_F(InternalBacklightControllerTest, ForceBacklightOnForUserActivity) { |
| // Set the brightness to zero and check that it's increased to the |
| // minimum visible level when the session state changes. |
| Init(PowerSource::AC); |
| const int kMinVisibleLevel = |
| PercentToLevel(InternalBacklightController::kMinVisiblePercent); |
| test::CallSetScreenBrightness( |
| dbus_wrapper_.get(), 0.0, |
| SetBacklightBrightnessRequest_Transition_INSTANT, |
| SetBacklightBrightnessRequest_Cause_USER_REQUEST); |
| ASSERT_EQ(0, backlight_.current_level()); |
| controller_->HandleSessionStateChange(SessionState::STARTED); |
| EXPECT_EQ(kMinVisibleLevel, backlight_.current_level()); |
| |
| // Pressing the power button should also increase the brightness. |
| test::CallSetScreenBrightness( |
| dbus_wrapper_.get(), 0.0, |
| SetBacklightBrightnessRequest_Transition_INSTANT, |
| SetBacklightBrightnessRequest_Cause_USER_REQUEST); |
| ASSERT_EQ(0, backlight_.current_level()); |
| controller_->HandlePowerButtonPress(); |
| EXPECT_EQ(kMinVisibleLevel, backlight_.current_level()); |
| |
| // Same for a wake notification. |
| test::CallSetScreenBrightness( |
| dbus_wrapper_.get(), 0.0, |
| SetBacklightBrightnessRequest_Transition_INSTANT, |
| SetBacklightBrightnessRequest_Cause_USER_REQUEST); |
| ASSERT_EQ(0, backlight_.current_level()); |
| controller_->HandleWakeNotification(); |
| EXPECT_EQ(kMinVisibleLevel, backlight_.current_level()); |
| |
| // Ditto for most user activity. |
| test::CallSetScreenBrightness( |
| dbus_wrapper_.get(), 0.0, |
| SetBacklightBrightnessRequest_Transition_INSTANT, |
| SetBacklightBrightnessRequest_Cause_USER_REQUEST); |
| ASSERT_EQ(0, backlight_.current_level()); |
| controller_->HandleUserActivity(USER_ACTIVITY_OTHER); |
| EXPECT_EQ(kMinVisibleLevel, backlight_.current_level()); |
| EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON, display_power_setter_.state()); |
| |
| // Both the explicit AC and battery brightness should have been updated |
| // (http://crbug.com/507944). |
| controller_->HandlePowerSourceChange(PowerSource::BATTERY); |
| EXPECT_EQ(kMinVisibleLevel, backlight_.current_level()); |
| EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON, display_power_setter_.state()); |
| |
| // User activity corresponding to brightness- or volume-related key presses |
| // shouldn't increase the brightness, though. |
| test::CallSetScreenBrightness( |
| dbus_wrapper_.get(), 0.0, |
| SetBacklightBrightnessRequest_Transition_INSTANT, |
| SetBacklightBrightnessRequest_Cause_USER_REQUEST); |
| ASSERT_EQ(0, backlight_.current_level()); |
| controller_->HandleUserActivity(USER_ACTIVITY_BRIGHTNESS_UP_KEY_PRESS); |
| EXPECT_EQ(0, backlight_.current_level()); |
| controller_->HandleUserActivity(USER_ACTIVITY_BRIGHTNESS_DOWN_KEY_PRESS); |
| EXPECT_EQ(0, backlight_.current_level()); |
| controller_->HandleUserActivity(USER_ACTIVITY_VOLUME_UP_KEY_PRESS); |
| EXPECT_EQ(0, backlight_.current_level()); |
| controller_->HandleUserActivity(USER_ACTIVITY_VOLUME_DOWN_KEY_PRESS); |
| EXPECT_EQ(0, backlight_.current_level()); |
| controller_->HandleUserActivity(USER_ACTIVITY_VOLUME_MUTE_KEY_PRESS); |
| EXPECT_EQ(0, backlight_.current_level()); |
| |
| // Enter presentation mode. The same actions that forced the backlight |
| // on before shouldn't do anything now; turning the panel back on while a |
| // second display is connected would resize the desktop. |
| controller_->HandleDisplayModeChange(DisplayMode::PRESENTATION); |
| ASSERT_EQ(0, backlight_.current_level()); |
| controller_->HandleSessionStateChange(SessionState::STOPPED); |
| EXPECT_EQ(0, backlight_.current_level()); |
| controller_->HandlePowerButtonPress(); |
| EXPECT_EQ(0, backlight_.current_level()); |
| controller_->HandleUserActivity(USER_ACTIVITY_OTHER); |
| EXPECT_EQ(0, backlight_.current_level()); |
| controller_->HandleWakeNotification(); |
| EXPECT_EQ(0, backlight_.current_level()); |
| |
| // The backlight should be turned on after exiting presentation mode. |
| controller_->HandleDisplayModeChange(DisplayMode::NORMAL); |
| EXPECT_EQ(kMinVisibleLevel, backlight_.current_level()); |
| |
| // Send a policy disabling the forcing behavior and check that the brightness |
| // remains at 0 after explicitly setting it to 0. |
| PowerManagementPolicy policy; |
| policy.set_force_nonzero_brightness_for_user_activity(false); |
| controller_->HandlePolicyChange(policy); |
| test::CallSetScreenBrightness( |
| dbus_wrapper_.get(), 0.0, |
| SetBacklightBrightnessRequest_Transition_INSTANT, |
| SetBacklightBrightnessRequest_Cause_USER_REQUEST); |
| ASSERT_EQ(0, backlight_.current_level()); |
| controller_->HandleSessionStateChange(SessionState::STARTED); |
| controller_->HandlePowerButtonPress(); |
| controller_->HandleUserActivity(USER_ACTIVITY_OTHER); |
| controller_->HandleWakeNotification(); |
| EXPECT_EQ(0, backlight_.current_level()); |
| } |
| |
| TEST_F(InternalBacklightControllerTest, DockedMode) { |
| Init(PowerSource::AC); |
| const int64_t initial_level = backlight_.current_level(); |
| ASSERT_GT(initial_level, 0); |
| |
| controller_->HandleLidStateChange(LidState::CLOSED); |
| EXPECT_EQ(chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON, |
| display_power_setter_.state()); |
| EXPECT_EQ(0, display_power_setter_.delay().InMilliseconds()); |
| EXPECT_EQ(0, backlight_.current_level()); |
| |
| // Increasing the brightness or dimming the backlight shouldn't change |
| // the displays' power settings while docked. |
| test::CallIncreaseScreenBrightness(dbus_wrapper_.get()); |
| EXPECT_EQ(chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON, |
| display_power_setter_.state()); |
| EXPECT_EQ(0, backlight_.current_level()); |
| controller_->SetDimmedForInactivity(true); |
| EXPECT_EQ(chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON, |
| display_power_setter_.state()); |
| EXPECT_EQ(0, backlight_.current_level()); |
| |
| // The external display should still be turned off for inactivity. |
| controller_->SetOffForInactivity(true); |
| EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_OFF, display_power_setter_.state()); |
| EXPECT_EQ(0, backlight_.current_level()); |
| controller_->SetOffForInactivity(false); |
| EXPECT_EQ(chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON, |
| display_power_setter_.state()); |
| EXPECT_EQ(0, backlight_.current_level()); |
| |
| // After exiting docked mode, the internal display should be turned back on |
| // and the backlight should be at the dimmed level. |
| controller_->HandleLidStateChange(LidState::OPEN); |
| EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON, display_power_setter_.state()); |
| EXPECT_EQ(0, display_power_setter_.delay().InMilliseconds()); |
| EXPECT_GT(backlight_.current_level(), 0); |
| EXPECT_LT(backlight_.current_level(), initial_level); |
| } |
| |
| TEST_F(InternalBacklightControllerTest, GiveUpOnBrokenAmbientLightSensor) { |
| // Don't report any ambient light readings. As before, the controller |
| // should avoid changing the backlight from its initial brightness. |
| init_time_ = base::TimeTicks::FromInternalValue(1000); |
| report_initial_als_reading_ = false; |
| Init(PowerSource::AC); |
| EXPECT_EQ(initial_backlight_level_, backlight_.current_level()); |
| controller_->HandlePowerSourceChange(PowerSource::AC); |
| EXPECT_EQ(initial_backlight_level_, backlight_.current_level()); |
| |
| // After the timeout has elapsed, state changes (like dimming due to |
| // inactivity) should be honored. |
| const base::TimeTicks kUpdateTime = |
| init_time_ + |
| base::TimeDelta::FromSeconds( |
| InternalBacklightController::kAmbientLightSensorTimeoutSec); |
| controller_->clock()->set_current_time_for_testing(kUpdateTime); |
| controller_->SetDimmedForInactivity(true); |
| EXPECT_LT(backlight_.current_level(), initial_backlight_level_); |
| } |
| |
| TEST_F(InternalBacklightControllerTest, UserAdjustmentBeforeAmbientLight) { |
| report_initial_als_reading_ = false; |
| Init(PowerSource::AC); |
| ASSERT_EQ(initial_backlight_level_, backlight_.current_level()); |
| |
| // Check that a decrease request actually decreases the brightness (i.e. the |
| // initial backlight level, rather than 100%, is used as the starting point |
| // when the ambient light level hasn't been received yet). See |
| // http://crosbug.com/p/22380. |
| test::CallDecreaseScreenBrightness(dbus_wrapper_.get(), true /* allow_off */); |
| EXPECT_LT(backlight_.current_level(), initial_backlight_level_); |
| } |
| |
| TEST_F(InternalBacklightControllerTest, |
| DockedNotificationReceivedBeforeAmbientLight) { |
| // Send a docked-mode request before the first ambient light reading. |
| report_initial_als_reading_ = false; |
| Init(PowerSource::AC); |
| controller_->HandleLidStateChange(LidState::CLOSED); |
| EXPECT_EQ(initial_backlight_level_, backlight_.current_level()); |
| |
| // Check that the system goes into docked mode after an ambient light |
| // reading is received. |
| light_sensor_.NotifyObservers(); |
| EXPECT_EQ(0, backlight_.current_level()); |
| EXPECT_EQ(chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON, |
| display_power_setter_.state()); |
| EXPECT_EQ(0, display_power_setter_.delay().InMilliseconds()); |
| } |
| |
| TEST_F(InternalBacklightControllerTest, BrightnessPolicy) { |
| default_als_steps_ = "50.0 -1 200\n90.0 100 -1"; |
| Init(PowerSource::AC); |
| ASSERT_EQ(PercentToLevel(50.0), backlight_.current_level()); |
| |
| BacklightControllerObserverStub observer; |
| controller_->AddObserver(&observer); |
| |
| // When an AC brightness policy is sent while on AC power, the brightness |
| // should change immediately. |
| PowerManagementPolicy policy; |
| policy.set_ac_brightness_percent(75.0); |
| controller_->HandlePolicyChange(policy); |
| EXPECT_EQ(PercentToLevel(75.0), backlight_.current_level()); |
| EXPECT_EQ(kFastBacklightTransitionMs, |
| backlight_.current_interval().InMilliseconds()); |
| ASSERT_EQ(static_cast<size_t>(1), observer.changes().size()); |
| EXPECT_EQ(BacklightBrightnessChange_Cause_OTHER, observer.changes()[0].cause); |
| EXPECT_EQ(controller_.get(), observer.changes()[0].source); |
| |
| // Passing a battery policy while on AC shouldn't do anything. |
| observer.Clear(); |
| policy.Clear(); |
| policy.set_battery_brightness_percent(43.0); |
| controller_->HandlePolicyChange(policy); |
| EXPECT_EQ(PercentToLevel(75.0), backlight_.current_level()); |
| EXPECT_EQ(static_cast<size_t>(0), observer.changes().size()); |
| |
| // The previously-set brightness should be used after switching to battery. |
| observer.Clear(); |
| controller_->HandlePowerSourceChange(PowerSource::BATTERY); |
| EXPECT_EQ(PercentToLevel(43.0), backlight_.current_level()); |
| ASSERT_EQ(static_cast<size_t>(1), observer.changes().size()); |
| EXPECT_EQ(BacklightBrightnessChange_Cause_EXTERNAL_POWER_DISCONNECTED, |
| observer.changes()[0].cause); |
| EXPECT_EQ(controller_.get(), observer.changes()[0].source); |
| |
| // An empty policy shouldn't do anything. |
| observer.Clear(); |
| policy.Clear(); |
| controller_->HandlePolicyChange(policy); |
| EXPECT_EQ(PercentToLevel(43.0), backlight_.current_level()); |
| EXPECT_EQ(static_cast<size_t>(0), observer.changes().size()); |
| |
| // Ambient light readings shouldn't affect the brightness after it's been set |
| // via a policy. |
| observer.Clear(); |
| light_sensor_.set_lux(400); |
| for (int i = 0; i < kAlsSamplesToTriggerAdjustment; ++i) |
| light_sensor_.NotifyObservers(); |
| EXPECT_EQ(PercentToLevel(43.0), backlight_.current_level()); |
| EXPECT_EQ(static_cast<size_t>(0), observer.changes().size()); |
| |
| // Set the brightness to 0% and check that the actions that usually turn the |
| // screen back on don't do anything. |
| policy.Clear(); |
| policy.set_battery_brightness_percent(0.0); |
| controller_->HandlePolicyChange(policy); |
| EXPECT_EQ(0, backlight_.current_level()); |
| controller_->HandleSessionStateChange(SessionState::STARTED); |
| controller_->HandlePowerButtonPress(); |
| controller_->HandleUserActivity(USER_ACTIVITY_OTHER); |
| controller_->HandleWakeNotification(); |
| EXPECT_EQ(0, backlight_.current_level()); |
| |
| // After sending an empty policy, user activity should increase the |
| // brightness from 0%. |
| policy.Clear(); |
| controller_->HandlePolicyChange(policy); |
| EXPECT_EQ(0, backlight_.current_level()); |
| controller_->HandleUserActivity(USER_ACTIVITY_OTHER); |
| EXPECT_GT(backlight_.current_level(), 0); |
| |
| // Set the brightness to 0% and send an empty policy again. This time check |
| // that a wake notification should increase the brightness from 0%. |
| policy.Clear(); |
| policy.set_battery_brightness_percent(0.0); |
| controller_->HandlePolicyChange(policy); |
| EXPECT_EQ(0, backlight_.current_level()); |
| policy.Clear(); |
| controller_->HandlePolicyChange(policy); |
| EXPECT_EQ(0, backlight_.current_level()); |
| controller_->HandleWakeNotification(); |
| EXPECT_GT(backlight_.current_level(), 0); |
| |
| // After a policy sets the brightness to 0%, the brightness keys should still |
| // work, and after user-triggered adjustments are made, hitting the power |
| // button should turn the backlight on. |
| policy.Clear(); |
| policy.set_battery_brightness_percent(0.0); |
| controller_->HandlePolicyChange(policy); |
| EXPECT_EQ(0, backlight_.current_level()); |
| test::CallIncreaseScreenBrightness(dbus_wrapper_.get()); |
| EXPECT_GT(backlight_.current_level(), 0); |
| test::CallDecreaseScreenBrightness(dbus_wrapper_.get(), true /* allow_off */); |
| EXPECT_EQ(0, backlight_.current_level()); |
| controller_->HandlePowerButtonPress(); |
| EXPECT_GT(backlight_.current_level(), 0); |
| |
| controller_->RemoveObserver(&observer); |
| } |
| |
| TEST_F(InternalBacklightControllerTest, SetPowerOnDisplayServiceStart) { |
| // Init() shouldn't ask Chrome to turn all displays on (maybe Chrome hasn't |
| // started yet). |
| Init(PowerSource::AC); |
| EXPECT_EQ(0, display_power_setter_.num_power_calls()); |
| |
| // After Chrome starts, the controller should turn the displays on. |
| display_power_setter_.reset_num_power_calls(); |
| controller_->HandleDisplayServiceStart(); |
| EXPECT_EQ(1, display_power_setter_.num_power_calls()); |
| EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON, display_power_setter_.state()); |
| EXPECT_EQ(0, display_power_setter_.delay().InMilliseconds()); |
| |
| // Enter docked mode. |
| controller_->HandleLidStateChange(LidState::CLOSED); |
| ASSERT_EQ(chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON, |
| display_power_setter_.state()); |
| |
| // If Chrome restarts, the controller should notify it about the current power |
| // state. |
| display_power_setter_.reset_num_power_calls(); |
| controller_->HandleDisplayServiceStart(); |
| EXPECT_EQ(1, display_power_setter_.num_power_calls()); |
| EXPECT_EQ(chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON, |
| display_power_setter_.state()); |
| } |
| |
| TEST_F(InternalBacklightControllerTest, MinVisibleLevelPrefUndercutsDefault) { |
| // Set the min-visible-level pref below the computed default. |
| int64_t computed_min = static_cast<int64_t>( |
| lround(InternalBacklightController::kDefaultMinVisibleBrightnessFraction * |
| max_backlight_level_)); |
| default_min_visible_level_ = static_cast<int64_t>(computed_min * 0.5); |
| ASSERT_GT(default_min_visible_level_, 0); |
| ASSERT_LT(default_min_visible_level_, computed_min); |
| |
| // Set the brightness to 0%, increase it one step, and confirm that the level |
| // configured by the pref is used instead of the higher computed default. |
| Init(PowerSource::AC); |
| test::CallSetScreenBrightness( |
| dbus_wrapper_.get(), 0.0, |
| SetBacklightBrightnessRequest_Transition_INSTANT, |
| SetBacklightBrightnessRequest_Cause_USER_REQUEST); |
| test::CallIncreaseScreenBrightness(dbus_wrapper_.get()); |
| EXPECT_EQ(default_min_visible_level_, backlight_.current_level()); |
| } |
| |
| TEST_F(InternalBacklightControllerTest, PreemptTransitionForShutdown) { |
| // Start a user-requested transition to 0. |
| Init(PowerSource::AC); |
| test::CallSetScreenBrightness( |
| dbus_wrapper_.get(), 0, SetBacklightBrightnessRequest_Transition_FAST, |
| SetBacklightBrightnessRequest_Cause_USER_REQUEST); |
| EXPECT_EQ(0, backlight_.current_level()); |
| EXPECT_EQ(kFastBacklightTransitionMs, |
| backlight_.current_interval().InMilliseconds()); |
| |
| // Shut the system down and check that the transition is interrupted in favor |
| // of setting the backlight to 0 immediately. |
| backlight_.set_transition_in_progress(true); |
| controller_->SetShuttingDown(true); |
| EXPECT_EQ(0, backlight_.current_level()); |
| EXPECT_EQ(0, backlight_.current_interval().InMilliseconds()); |
| } |
| |
| TEST_F(InternalBacklightControllerTest, SetDisplayPowerBeforeBrightness) { |
| // Tell the backlight and DisplayPowerSetter to use the same clock for |
| // recording calls, and configure the clock to return increasing values. |
| Clock clock; |
| clock.set_current_time_for_testing(base::TimeTicks::FromInternalValue(1000)); |
| clock.set_time_step_for_testing(base::TimeDelta::FromMilliseconds(1)); |
| backlight_.set_clock(&clock); |
| display_power_setter_.set_clock(&clock); |
| |
| Init(PowerSource::AC); |
| |
| // Dim the backlight and then turn the display off. powerd should instruct the |
| // display to turn off before it sets the backlight to zero. |
| controller_->SetDimmedForInactivity(true); |
| const base::TimeTicks dim_time = backlight_.last_set_brightness_level_time(); |
| controller_->SetOffForInactivity(true); |
| const base::TimeTicks off_time = |
| display_power_setter_.last_set_display_power_time(); |
| const base::TimeTicks zero_time = backlight_.last_set_brightness_level_time(); |
| EXPECT_GT(off_time.ToInternalValue(), dim_time.ToInternalValue()); |
| EXPECT_GT(zero_time.ToInternalValue(), off_time.ToInternalValue()); |
| |
| // Suspend and start the resume process. Nothing should change yet since the |
| // display was already (and is still) turned off for inactivity. |
| controller_->SetSuspended(true); |
| controller_->SetSuspended(false); |
| controller_->SetDimmedForInactivity(false); |
| EXPECT_EQ( |
| off_time.ToInternalValue(), |
| display_power_setter_.last_set_display_power_time().ToInternalValue()); |
| EXPECT_EQ(zero_time.ToInternalValue(), |
| backlight_.last_set_brightness_level_time().ToInternalValue()); |
| |
| // Check that the display is turned on before the backlight level is restored. |
| controller_->SetOffForInactivity(false); |
| const base::TimeTicks on_time = |
| display_power_setter_.last_set_display_power_time(); |
| const base::TimeTicks undim_time = |
| backlight_.last_set_brightness_level_time(); |
| EXPECT_GT(on_time.ToInternalValue(), zero_time.ToInternalValue()); |
| EXPECT_GT(undim_time.ToInternalValue(), on_time.ToInternalValue()); |
| |
| backlight_.set_clock(nullptr); |
| display_power_setter_.set_clock(nullptr); |
| } |
| |
| TEST_F(InternalBacklightControllerTest, ForcedOff) { |
| default_als_steps_ = "50.0 -1 200\n75.0 100 -1"; |
| Init(PowerSource::AC); |
| ASSERT_GT(backlight_.current_level(), 0); |
| |
| // When SetForcedOff() is called, both the backlight and display should turn |
| // off immediately. |
| controller_->SetForcedOff(true); |
| EXPECT_EQ(0, backlight_.current_level()); |
| EXPECT_EQ(0, backlight_.current_interval().InMilliseconds()); |
| EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_OFF, display_power_setter_.state()); |
| EXPECT_EQ(0, display_power_setter_.delay().InMilliseconds()); |
| |
| // The screen should stay off even if we would otherwise adjust its brightness |
| // due to a change in ambient light: https://crbug.com/747165 |
| light_sensor_.set_lux(300); |
| for (int i = 0; i < kAlsSamplesToTriggerAdjustment; ++i) |
| light_sensor_.NotifyObservers(); |
| EXPECT_EQ(0, backlight_.current_level()); |
| EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_OFF, display_power_setter_.state()); |
| |
| // While the display is still forced off, also turn it off for inactivity. |
| controller_->SetOffForInactivity(true); |
| EXPECT_EQ(0, backlight_.current_level()); |
| EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_OFF, display_power_setter_.state()); |
| |
| // Stop forcing it off and check that it remains off due to inactivity. |
| controller_->SetForcedOff(false); |
| EXPECT_EQ(0, backlight_.current_level()); |
| EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_OFF, display_power_setter_.state()); |
| |
| // When activity is seen, the backlight and display should be turned on again. |
| controller_->SetOffForInactivity(false); |
| EXPECT_GT(backlight_.current_level(), 0); |
| EXPECT_EQ(0, backlight_.current_interval().InMilliseconds()); |
| } |
| |
| TEST_F(InternalBacklightControllerTest, SetAndGetBrightness) { |
| Init(PowerSource::AC); |
| dbus_wrapper_->ClearSentSignals(); |
| |
| // Set the brightness to a known percent. |
| const double kBrightnessPercent = 55.0; |
| test::CallSetScreenBrightness(dbus_wrapper_.get(), kBrightnessPercent, |
| SetBacklightBrightnessRequest_Transition_FAST, |
| SetBacklightBrightnessRequest_Cause_MODEL); |
| double percent = 0.0; |
| ASSERT_TRUE(controller_->GetBrightnessPercent(&percent)); |
| ASSERT_DOUBLE_EQ(round(kBrightnessPercent), round(percent)); |
| EXPECT_EQ(kFastBacklightTransitionMs, |
| backlight_.current_interval().InMilliseconds()); |
| |
| // A signal should've been emitted with the appropriate cause. |
| test::CheckBrightnessChangedSignal( |
| dbus_wrapper_.get(), 0, kScreenBrightnessChangedSignal, |
| kBrightnessPercent, BacklightBrightnessChange_Cause_MODEL); |
| |
| // Check that the same percent is returned. |
| dbus::MethodCall method_call(kPowerManagerInterface, |
| kGetScreenBrightnessPercentMethod); |
| std::unique_ptr<dbus::Response> response = |
| dbus_wrapper_->CallExportedMethodSync(&method_call); |
| ASSERT_TRUE(response); |
| dbus::MessageReader reader(response.get()); |
| ASSERT_TRUE(reader.PopDouble(&percent)); |
| EXPECT_DOUBLE_EQ(round(kBrightnessPercent), round(percent)); |
| } |
| |
| } // namespace policy |
| } // namespace power_manager |