1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411 |
- // Copyright 2016 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/system/power/power_button_controller.h"
- #include "ash/accessibility/test_accessibility_controller_client.h"
- #include "ash/constants/ash_switches.h"
- #include "ash/display/screen_orientation_controller.h"
- #include "ash/display/screen_orientation_controller_test_api.h"
- #include "ash/media/media_controller_impl.h"
- #include "ash/session/session_controller_impl.h"
- #include "ash/shell.h"
- #include "ash/system/power/power_button_controller_test_api.h"
- #include "ash/system/power/power_button_menu_item_view.h"
- #include "ash/system/power/power_button_menu_view.h"
- #include "ash/system/power/power_button_test_base.h"
- #include "ash/test_media_client.h"
- #include "ash/touch/touch_devices_controller.h"
- #include "ash/wm/lock_state_controller_test_api.h"
- #include "ash/wm/tablet_mode/tablet_mode_controller.h"
- #include "ash/wm/test_session_state_animator.h"
- #include "ash/wm/window_util.h"
- #include "base/command_line.h"
- #include "base/json/json_writer.h"
- #include "base/run_loop.h"
- #include "base/test/simple_test_tick_clock.h"
- #include "chromeos/dbus/power/fake_power_manager_client.h"
- #include "chromeos/dbus/power_manager/suspend.pb.h"
- #include "ui/compositor/scoped_animation_duration_scale_mode.h"
- #include "ui/display/test/display_manager_test_api.h"
- #include "ui/events/event.h"
- #include "ui/events/test/event_generator.h"
- #include "ui/views/widget/widget.h"
- using PowerManagerClient = chromeos::PowerManagerClient;
- namespace ash {
- namespace {
- // A non-zero brightness used for test.
- constexpr double kNonZeroBrightness = 10.;
- // Width of the display.
- constexpr int kDisplayWidth = 2000;
- // Height of the display.
- constexpr int kDisplayHeight = 1200;
- // Power button position offset percentage.
- constexpr double kPowerButtonPercentage = 0.9f;
- // Shorthand for some long constants.
- constexpr power_manager::BacklightBrightnessChange_Cause kUserCause =
- power_manager::BacklightBrightnessChange_Cause_USER_REQUEST;
- constexpr power_manager::BacklightBrightnessChange_Cause kOtherCause =
- power_manager::BacklightBrightnessChange_Cause_OTHER;
- } // namespace
- using PowerButtonPosition = PowerButtonController::PowerButtonPosition;
- class PowerButtonControllerTest : public PowerButtonTestBase {
- public:
- PowerButtonControllerTest() = default;
- PowerButtonControllerTest(const PowerButtonControllerTest&) = delete;
- PowerButtonControllerTest& operator=(const PowerButtonControllerTest&) =
- delete;
- ~PowerButtonControllerTest() override = default;
- void SetUp() override {
- PowerButtonTestBase::SetUp();
- InitPowerButtonControllerMembers(PowerManagerClient::TabletMode::ON);
- SendBrightnessChange(kNonZeroBrightness, kUserCause);
- EXPECT_FALSE(power_manager_client()->backlights_forced_off());
- // Advance a duration longer than |kIgnorePowerButtonAfterResumeDelay| to
- // avoid events being ignored.
- tick_clock_.Advance(
- PowerButtonController::kIgnorePowerButtonAfterResumeDelay +
- base::Milliseconds(2));
- // Run the event loop so that PowerButtonDisplayController can receive the
- // initial backlights-forced-off state.
- base::RunLoop().RunUntilIdle();
- }
- protected:
- void SendBrightnessChange(
- double percent,
- power_manager::BacklightBrightnessChange_Cause cause) {
- power_manager::BacklightBrightnessChange change;
- change.set_percent(percent);
- change.set_cause(cause);
- power_manager_client()->SendScreenBrightnessChanged(change);
- }
- bool GetLockedState() {
- // LockScreen is an async mojo call.
- GetSessionControllerClient()->FlushForTest();
- return Shell::Get()->session_controller()->IsScreenLocked();
- }
- bool GetGlobalTouchscreenEnabled() const {
- return Shell::Get()->touch_devices_controller()->GetTouchscreenEnabled(
- TouchDeviceEnabledSource::GLOBAL);
- }
- // Tapping power button when screen is off will turn the screen on but not
- // showing the menu.
- void TappingPowerButtonWhenScreenIsIdleOff() {
- SendBrightnessChange(0, kUserCause);
- PressPowerButton();
- EXPECT_FALSE(power_manager_client()->backlights_forced_off());
- SendBrightnessChange(kNonZeroBrightness, kUserCause);
- ReleasePowerButton();
- EXPECT_FALSE(power_manager_client()->backlights_forced_off());
- EXPECT_FALSE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
- }
- // Press the power button to show the menu.
- void OpenPowerButtonMenu() {
- PressPowerButton();
- if (Shell::Get()->tablet_mode_controller()->InTabletMode()) {
- EXPECT_TRUE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
- ASSERT_TRUE(power_button_test_api_->TriggerPowerButtonMenuTimeout());
- }
- ReleasePowerButton();
- ASSERT_TRUE(power_button_test_api_->IsMenuOpened());
- }
- // Tap outside of the menu view to dismiss the menu.
- void TapToDismissPowerButtonMenu() {
- gfx::Rect menu_bounds = power_button_test_api_->GetMenuBoundsInScreen();
- gfx::Point point = menu_bounds.bottom_right();
- point.Offset(5, 5);
- GetEventGenerator()->GestureTapAt(point);
- EXPECT_FALSE(power_button_test_api_->IsMenuOpened());
- }
- void PressLockButton() {
- power_button_controller_->OnLockButtonEvent(true, base::TimeTicks::Now());
- }
- void ReleaseLockButton() {
- power_button_controller_->OnLockButtonEvent(false, base::TimeTicks::Now());
- }
- };
- TEST_F(PowerButtonControllerTest, LockScreenIfRequired) {
- Initialize(ButtonType::NORMAL, LoginStatus::USER);
- EnableTabletMode(true);
- SetShouldLockScreenAutomatically(true);
- ASSERT_FALSE(GetLockedState());
- // On User logged in status, power-button-press-release should lock screen if
- // automatic screen-locking was requested.
- PressPowerButton();
- ReleasePowerButton();
- EXPECT_TRUE(GetLockedState());
- // On locked state, power-button-press-release should do nothing.
- PressPowerButton();
- ReleasePowerButton();
- EXPECT_TRUE(GetLockedState());
- // Unlock the sceen.
- UnlockScreen();
- ASSERT_FALSE(GetLockedState());
- // power-button-press-release should not lock the screen if automatic
- // screen-locking wasn't requested.
- SetShouldLockScreenAutomatically(false);
- PressPowerButton();
- ReleasePowerButton();
- EXPECT_FALSE(GetLockedState());
- }
- // Tests tapping the power button of a clamshell device.
- TEST_F(PowerButtonControllerTest, TappingPowerButtonOfClamshell) {
- // Should not turn the screen off when screen is on.
- InitPowerButtonControllerMembers(PowerManagerClient::TabletMode::UNSUPPORTED);
- EXPECT_FALSE(power_manager_client()->backlights_forced_off());
- PressPowerButton();
- power_button_test_api_->SetShowMenuAnimationDone(false);
- // Start the showing power menu animation immediately as pressing the
- // clamshell power button.
- EXPECT_FALSE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
- EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
- ReleasePowerButton();
- EXPECT_FALSE(power_manager_client()->backlights_forced_off());
- // Start the dimissing power menu animation immediately as releasing the
- // clamsehll power button if showing animation hasn't finished.
- EXPECT_FALSE(power_button_test_api_->IsMenuOpened());
- AdvanceClockToAvoidIgnoring();
- // Should turn screen on if screen is off.
- TappingPowerButtonWhenScreenIsIdleOff();
- ASSERT_TRUE(power_button_test_api_->IsMenuOpened());
- AdvanceClockToAvoidIgnoring();
- // Should not start the dismissing menu animation if showing menu animation
- // has finished.
- PressPowerButton();
- // Start the showing power menu animation immediately as pressing the
- // clamshell power button.
- EXPECT_FALSE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
- EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
- power_button_test_api_->SetShowMenuAnimationDone(true);
- ASSERT_TRUE(power_button_test_api_->TriggerPreShutdownTimeout());
- ReleasePowerButton();
- EXPECT_FALSE(power_manager_client()->backlights_forced_off());
- // Power button menu should keep opened if showing animation has finished.
- EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
- // Tapping power button when menu is already shown should keep the screen on
- // and dismiss the power menu.
- AdvanceClockToAvoidIgnoring();
- PressPowerButton();
- ReleasePowerButton();
- EXPECT_FALSE(power_manager_client()->backlights_forced_off());
- EXPECT_FALSE(power_button_test_api_->IsMenuOpened());
- }
- // Tests tapping the power button of a device that has a tablet mode switch.
- TEST_F(PowerButtonControllerTest, TappingPowerButtonOfTablet) {
- EnableTabletMode(true);
- // Should turn screen off if screen is on and power button menu will not be
- // shown.
- PressPowerButton();
- // Showing power menu animation hasn't started as power menu timer is running.
- EXPECT_TRUE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
- EXPECT_FALSE(power_manager_client()->backlights_forced_off());
- EXPECT_FALSE(power_button_test_api_->IsMenuOpened());
- ReleasePowerButton();
- EXPECT_FALSE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
- EXPECT_TRUE(power_manager_client()->backlights_forced_off());
- EXPECT_FALSE(power_button_test_api_->IsMenuOpened());
- // Should turn screen on if screen is off.
- AdvanceClockToAvoidIgnoring();
- TappingPowerButtonWhenScreenIsIdleOff();
- // Showing power menu animation should start until power menu timer is
- // timeout.
- AdvanceClockToAvoidIgnoring();
- PressPowerButton();
- power_button_test_api_->SetShowMenuAnimationDone(false);
- EXPECT_TRUE(power_button_test_api_->TriggerPowerButtonMenuTimeout());
- EXPECT_FALSE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
- EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
- ReleasePowerButton();
- // Showing animation will continue until show the power button menu even
- // release the power button.
- EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
- // Tapping power button when menu is already shown should still turn screen
- // off and dismiss the menu.
- AdvanceClockToAvoidIgnoring();
- PressPowerButton();
- EXPECT_TRUE(power_button_test_api_->PreShutdownTimerIsRunning());
- ReleasePowerButton();
- EXPECT_FALSE(power_button_test_api_->PreShutdownTimerIsRunning());
- EXPECT_TRUE(power_manager_client()->backlights_forced_off());
- EXPECT_FALSE(power_button_test_api_->IsMenuOpened());
- // Should turn screen on if screen is off.
- AdvanceClockToAvoidIgnoring();
- TappingPowerButtonWhenScreenIsIdleOff();
- }
- // Tests that power button taps turn the screen off while in tablet mode but not
- // in laptop mode.
- TEST_F(PowerButtonControllerTest, ModeSpecificPowerButton) {
- // While the device is in tablet mode, tapping the power button should turn
- // the display off (and then back on if pressed a second time).
- EnableTabletMode(true);
- PressPowerButton();
- ReleasePowerButton();
- EXPECT_TRUE(power_manager_client()->backlights_forced_off());
- PressPowerButton();
- ReleasePowerButton();
- EXPECT_FALSE(power_manager_client()->backlights_forced_off());
- // In laptop mode, tapping the power button shouldn't turn the screen off.
- // Instead, we should start showing the power menu animation.
- EnableTabletMode(false);
- AdvanceClockToAvoidIgnoring();
- PressPowerButton();
- EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
- ReleasePowerButton();
- EXPECT_FALSE(power_manager_client()->backlights_forced_off());
- // Tapping power button again in laptop mode when menu is opened should
- // dismiss the menu but keep the screen on.
- EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
- AdvanceClockToAvoidIgnoring();
- PressPowerButton();
- EXPECT_FALSE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
- EXPECT_TRUE(power_button_test_api_->PreShutdownTimerIsRunning());
- ReleasePowerButton();
- EXPECT_FALSE(power_manager_client()->backlights_forced_off());
- EXPECT_FALSE(power_button_test_api_->IsMenuOpened());
- }
- // Tests that when the kForceTabletPowerButton flag is passed (indicating that
- // the device is tablet-like) tapping the power button turns the screen off
- // regardless of what the tablet mode switch reports.
- TEST_F(PowerButtonControllerTest, ForceTabletPowerButton) {
- base::CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kForceTabletPowerButton);
- ResetPowerButtonController();
- PressPowerButton();
- ReleasePowerButton();
- EXPECT_TRUE(power_manager_client()->backlights_forced_off());
- PressPowerButton();
- ReleasePowerButton();
- EXPECT_FALSE(power_manager_client()->backlights_forced_off());
- EnableTabletMode(false);
- AdvanceClockToAvoidIgnoring();
- PressPowerButton();
- ReleasePowerButton();
- EXPECT_TRUE(power_manager_client()->backlights_forced_off());
- PressPowerButton();
- ReleasePowerButton();
- EXPECT_FALSE(power_manager_client()->backlights_forced_off());
- }
- // Tests that release power button after menu is opened but before trigger
- // shutdown will not turn screen off.
- TEST_F(PowerButtonControllerTest, ReleasePowerButtonBeforeTriggerShutdown) {
- EnableTabletMode(true);
- PressPowerButton();
- EXPECT_TRUE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
- EXPECT_FALSE(power_manager_client()->backlights_forced_off());
- ASSERT_TRUE(power_button_test_api_->TriggerPowerButtonMenuTimeout());
- ASSERT_TRUE(power_button_test_api_->TriggerPreShutdownTimeout());
- EXPECT_TRUE(lock_state_test_api_->shutdown_timer_is_running());
- ReleasePowerButton();
- EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
- EXPECT_FALSE(lock_state_test_api_->shutdown_timer_is_running());
- EXPECT_FALSE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
- EXPECT_FALSE(power_manager_client()->backlights_forced_off());
- }
- // Tests that tapping the power button dismisses the menu while in laptop mode.
- TEST_F(PowerButtonControllerTest, HoldPowerButtonWhileMenuShownInLaptopMode) {
- // Hold the power button long enough to show the menu and start the
- // cancellable shutdown animation. The menu should remain open.
- PressPowerButton();
- ASSERT_TRUE(power_button_test_api_->IsMenuOpened());
- power_button_test_api_->SetShowMenuAnimationDone(true);
- ASSERT_TRUE(power_button_test_api_->TriggerPreShutdownTimeout());
- ASSERT_TRUE(lock_state_test_api_->shutdown_timer_is_running());
- ReleasePowerButton();
- EXPECT_FALSE(lock_state_test_api_->shutdown_timer_is_running());
- EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
- // Hold the power button long enough to start the cancellable shutdown
- // animation again. The menu should remain open.
- AdvanceClockToAvoidIgnoring();
- PressPowerButton();
- ASSERT_TRUE(power_button_test_api_->TriggerPreShutdownTimeout());
- ASSERT_TRUE(lock_state_test_api_->shutdown_timer_is_running());
- ReleasePowerButton();
- EXPECT_FALSE(lock_state_test_api_->shutdown_timer_is_running());
- EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
- // This time, just tap the power button (i.e. release it before the
- // cancellable shutdown animation starts). The menu should be dismissed.
- AdvanceClockToAvoidIgnoring();
- PressPowerButton();
- ReleasePowerButton();
- EXPECT_FALSE(power_button_test_api_->IsMenuOpened());
- }
- // Tests press lock button and power button in sequence.
- TEST_F(PowerButtonControllerTest, PressAfterAnotherReleased) {
- // Tap power button after press lock button should still turn screen off.
- Initialize(ButtonType::NORMAL, LoginStatus::USER);
- EnableTabletMode(true);
- PressLockButton();
- ReleaseLockButton();
- EXPECT_FALSE(power_manager_client()->backlights_forced_off());
- PressPowerButton();
- ReleasePowerButton();
- EXPECT_TRUE(power_manager_client()->backlights_forced_off());
- // Press lock button after tap power button should still lock screen.
- PressPowerButton();
- ReleasePowerButton();
- PressLockButton();
- ReleaseLockButton();
- EXPECT_TRUE(lock_state_test_api_->is_animating_lock());
- EXPECT_TRUE(GetLockedState());
- }
- // Tests press lock/power button before release power/lock button.
- TEST_F(PowerButtonControllerTest, PressBeforeAnotherReleased) {
- // Press lock button when power button is still being pressed will be ignored
- // and continue to turn screen off.
- Initialize(ButtonType::NORMAL, LoginStatus::USER);
- EnableTabletMode(true);
- EXPECT_FALSE(power_manager_client()->backlights_forced_off());
- PressPowerButton();
- PressLockButton();
- ReleaseLockButton();
- ReleasePowerButton();
- EXPECT_FALSE(lock_state_test_api_->is_animating_lock());
- EXPECT_FALSE(GetLockedState());
- EXPECT_TRUE(power_manager_client()->backlights_forced_off());
- // Turn the screen on.
- PressPowerButton();
- ReleasePowerButton();
- // Press power button when lock button is still being pressed. The pressing of
- // power button will be ignored and continue to lock screen.
- PressLockButton();
- PressPowerButton();
- ReleasePowerButton();
- ReleaseLockButton();
- EXPECT_TRUE(lock_state_test_api_->is_animating_lock());
- EXPECT_TRUE(GetLockedState());
- EXPECT_FALSE(power_manager_client()->backlights_forced_off());
- }
- // Tests tapping power button when device is suspended without backlights forced
- // off.
- TEST_F(PowerButtonControllerTest,
- TappingPowerButtonWhenSuspendedWithoutBacklightsForcedOff) {
- EnableTabletMode(true);
- power_manager_client()->SendSuspendImminent(
- power_manager::SuspendImminent_Reason_OTHER);
- SendBrightnessChange(0, kUserCause);
- // There is a power button pressed here, but PowerButtonEvent is sent later.
- power_manager_client()->SendSuspendDone();
- SendBrightnessChange(kNonZeroBrightness, kUserCause);
- // Send the power button event after a short delay and check that backlights
- // are not forced off.
- tick_clock_.Advance(base::Milliseconds(500));
- PressPowerButton();
- EXPECT_TRUE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
- ReleasePowerButton();
- EXPECT_FALSE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
- EXPECT_FALSE(power_manager_client()->backlights_forced_off());
- // Send the power button event after a longer delay and check that backlights
- // are forced off.
- tick_clock_.Advance(base::Milliseconds(1600));
- PressPowerButton();
- EXPECT_TRUE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
- ReleasePowerButton();
- SendBrightnessChange(0, kUserCause);
- EXPECT_FALSE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
- EXPECT_TRUE(power_manager_client()->backlights_forced_off());
- }
- // Tests tapping power button when device is suspended with backlights forced
- // off.
- TEST_F(PowerButtonControllerTest,
- TappingPowerButtonWhenSuspendedWithBacklightsForcedOff) {
- EnableTabletMode(true);
- PressPowerButton();
- ReleasePowerButton();
- SendBrightnessChange(0, kUserCause);
- ASSERT_TRUE(power_manager_client()->backlights_forced_off());
- power_manager_client()->SendSuspendImminent(
- power_manager::SuspendImminent_Reason_OTHER);
- // There is a power button pressed here, but PowerButtonEvent is sent later.
- // Because of backlights forced off, resuming system will not restore
- // brightness.
- power_manager_client()->SendSuspendDone();
- // Send the power button event after a short delay and check that backlights
- // are not forced off.
- tick_clock_.Advance(base::Milliseconds(500));
- PressPowerButton();
- SendBrightnessChange(kNonZeroBrightness, kUserCause);
- EXPECT_TRUE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
- ReleasePowerButton();
- EXPECT_FALSE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
- EXPECT_FALSE(power_manager_client()->backlights_forced_off());
- // Send the power button event after a longer delay and check that backlights
- // are forced off.
- tick_clock_.Advance(base::Milliseconds(1600));
- PressPowerButton();
- EXPECT_TRUE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
- ReleasePowerButton();
- SendBrightnessChange(0, kUserCause);
- EXPECT_FALSE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
- EXPECT_TRUE(power_manager_client()->backlights_forced_off());
- }
- // For convertible device working on tablet mode, keyboard/mouse event should
- // not SetBacklightsForcedOff(false) when screen is off.
- TEST_F(PowerButtonControllerTest, ConvertibleOnTabletMode) {
- EnableTabletMode(true);
- PressPowerButton();
- ReleasePowerButton();
- SendBrightnessChange(0, kUserCause);
- ASSERT_TRUE(power_manager_client()->backlights_forced_off());
- PressKey(ui::VKEY_L);
- EXPECT_TRUE(power_manager_client()->backlights_forced_off());
- GenerateMouseMoveEvent();
- EXPECT_TRUE(power_manager_client()->backlights_forced_off());
- }
- // Tests that a single set of power button pressed-and-released operation should
- // cause only one SetBacklightsForcedOff call.
- TEST_F(PowerButtonControllerTest, IgnorePowerOnKeyEvent) {
- ui::KeyEvent power_key_pressed(ui::ET_KEY_PRESSED, ui::VKEY_POWER,
- ui::EF_NONE);
- ui::KeyEvent power_key_released(ui::ET_KEY_RELEASED, ui::VKEY_POWER,
- ui::EF_NONE);
- // There are two |power_key_pressed| events and |power_key_released| events
- // generated for each pressing and releasing, and multiple repeating pressed
- // events depending on holding.
- ASSERT_EQ(0, power_manager_client()->num_set_backlights_forced_off_calls());
- EnableTabletMode(true);
- power_button_test_api_->SendKeyEvent(&power_key_pressed);
- power_button_test_api_->SendKeyEvent(&power_key_pressed);
- PressPowerButton();
- power_button_test_api_->SendKeyEvent(&power_key_pressed);
- power_button_test_api_->SendKeyEvent(&power_key_pressed);
- power_button_test_api_->SendKeyEvent(&power_key_pressed);
- ReleasePowerButton();
- power_button_test_api_->SendKeyEvent(&power_key_released);
- power_button_test_api_->SendKeyEvent(&power_key_released);
- EXPECT_EQ(1, power_manager_client()->num_set_backlights_forced_off_calls());
- }
- // Tests that when the power button is pressed/released in tablet mode,
- // requesting/stopping backlights forced off should update the global
- // touchscreen enabled status.
- TEST_F(PowerButtonControllerTest, DisableTouchscreenWhileForcedOff) {
- // Tests tablet power button.
- EnableTabletMode(true);
- ASSERT_TRUE(GetGlobalTouchscreenEnabled());
- PressPowerButton();
- ReleasePowerButton();
- SendBrightnessChange(0, kUserCause);
- EXPECT_FALSE(GetGlobalTouchscreenEnabled());
- PressPowerButton();
- SendBrightnessChange(kNonZeroBrightness, kUserCause);
- ReleasePowerButton();
- EXPECT_TRUE(GetGlobalTouchscreenEnabled());
- }
- // When the screen is turned off automatically, the touchscreen should also be
- // disabled.
- TEST_F(PowerButtonControllerTest, DisableTouchscreenForInactivity) {
- ASSERT_TRUE(GetGlobalTouchscreenEnabled());
- // Turn screen off for automated change (e.g. user is inactive).
- SendBrightnessChange(0, kOtherCause);
- EXPECT_FALSE(GetGlobalTouchscreenEnabled());
- SendBrightnessChange(kNonZeroBrightness, kUserCause);
- EXPECT_TRUE(GetGlobalTouchscreenEnabled());
- // After decreasing the brightness to zero for a user request, the touchscreen
- // should remain enabled.
- SendBrightnessChange(0, kUserCause);
- EXPECT_TRUE(GetGlobalTouchscreenEnabled());
- }
- // When user switches convertible device between tablet mode and laptop mode,
- // power button may be pressed and held, which may cause unwanted unclean
- // shutdown.
- TEST_F(PowerButtonControllerTest, LeaveTabletModeWhilePressingPowerButton) {
- EnableTabletMode(true);
- PressPowerButton();
- EXPECT_TRUE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
- EnableTabletMode(false);
- EXPECT_FALSE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
- tick_clock_.Advance(base::Milliseconds(1500));
- ReleasePowerButton();
- EXPECT_FALSE(power_manager_client()->backlights_forced_off());
- EXPECT_FALSE(power_button_test_api_->IsMenuOpened());
- }
- // Tests that repeated power button releases are ignored (crbug.com/675291).
- TEST_F(PowerButtonControllerTest, IgnoreRepeatedPowerButtonReleases) {
- // Set backlights forced off for starting point.
- EnableTabletMode(true);
- PressPowerButton();
- ReleasePowerButton();
- SendBrightnessChange(0, kUserCause);
- ASSERT_TRUE(power_manager_client()->backlights_forced_off());
- // Test that a pressing-releasing operation after a short duration, backlights
- // forced off is stopped since we don't drop request for power button pressed.
- tick_clock_.Advance(base::Milliseconds(200));
- PressPowerButton();
- SendBrightnessChange(kNonZeroBrightness, kUserCause);
- ReleasePowerButton();
- EXPECT_FALSE(power_manager_client()->backlights_forced_off());
- // Test that after another short duration, backlights will not be forced off
- // since this immediately following forcing off request needs to be dropped.
- tick_clock_.Advance(base::Milliseconds(200));
- PressPowerButton();
- ReleasePowerButton();
- EXPECT_FALSE(power_manager_client()->backlights_forced_off());
- // Test that after another long duration, backlights should be forced off.
- tick_clock_.Advance(base::Milliseconds(800));
- PressPowerButton();
- ReleasePowerButton();
- SendBrightnessChange(0, kUserCause);
- EXPECT_TRUE(power_manager_client()->backlights_forced_off());
- }
- // Tests that repeated power button releases of clamshell should cancel the
- // ongoing showing menu animation.
- TEST_F(PowerButtonControllerTest,
- ClamshellRepeatedPowerButtonReleasesCancelledAnimation) {
- InitPowerButtonControllerMembers(PowerManagerClient::TabletMode::UNSUPPORTED);
- EnableTabletMode(false);
- // Enable animations so that we can make sure that they occur.
- ui::ScopedAnimationDurationScaleMode regular_animations(
- ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
- PressPowerButton();
- ReleasePowerButton();
- EXPECT_FALSE(power_button_test_api_->IsMenuOpened());
- tick_clock_.Advance(base::Milliseconds(200));
- PressPowerButton();
- ReleasePowerButton();
- // Showing menu animation should be cancelled and menu is not shown.
- EXPECT_FALSE(power_button_test_api_->IsMenuOpened());
- EXPECT_FALSE(power_button_test_api_->PreShutdownTimerIsRunning());
- }
- // Tests that lid closed events stop forcing off backlights.
- TEST_F(PowerButtonControllerTest, LidEventsStopForcingOff) {
- // Pressing/releasing power button to set backlights forced off.
- EnableTabletMode(true);
- PressPowerButton();
- ReleasePowerButton();
- ASSERT_TRUE(power_manager_client()->backlights_forced_off());
- // A lid closed event is received, we should stop forcing off backlights.
- power_manager_client()->SetLidState(PowerManagerClient::LidState::CLOSED,
- tick_clock_.NowTicks());
- EXPECT_FALSE(power_manager_client()->backlights_forced_off());
- }
- // Tests that tablet mode events from powerd stop forcing off backlights.
- TEST_F(PowerButtonControllerTest, TabletModeEventsStopForcingOff) {
- EnableTabletMode(true);
- PressPowerButton();
- ReleasePowerButton();
- ASSERT_TRUE(power_manager_client()->backlights_forced_off());
- power_manager_client()->SetTabletMode(PowerManagerClient::TabletMode::OFF,
- tick_clock_.NowTicks());
- EXPECT_FALSE(power_manager_client()->backlights_forced_off());
- AdvanceClockToAvoidIgnoring();
- PressPowerButton();
- ReleasePowerButton();
- ASSERT_TRUE(power_manager_client()->backlights_forced_off());
- power_manager_client()->SetTabletMode(PowerManagerClient::TabletMode::ON,
- tick_clock_.NowTicks());
- EXPECT_FALSE(power_manager_client()->backlights_forced_off());
- }
- // Tests that with system reboot, the global touchscreen enabled status should
- // be synced with new backlights forced off state from powerd.
- TEST_F(PowerButtonControllerTest, SyncTouchscreenEnabled) {
- Shell::Get()->touch_devices_controller()->SetTouchscreenEnabled(
- false, TouchDeviceEnabledSource::GLOBAL);
- ASSERT_FALSE(GetGlobalTouchscreenEnabled());
- // Simulate system reboot by resetting backlights forced off state in powerd
- // and PowerButtonController.
- power_manager_client()->SetBacklightsForcedOff(false);
- ResetPowerButtonController();
- SetTabletModeSwitchState(PowerManagerClient::TabletMode::ON);
- // Run the event loop for PowerButtonDisplayController to get backlight state
- // and check that the global touchscreen status is correct.
- base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(power_manager_client()->backlights_forced_off());
- EXPECT_TRUE(GetGlobalTouchscreenEnabled());
- }
- // Tests that when backlights get forced off due to tablet power button, media
- // sessions should be suspended.
- TEST_F(PowerButtonControllerTest, SuspendMediaSessions) {
- TestMediaClient client;
- Shell::Get()->media_controller()->SetClient(&client);
- ASSERT_FALSE(client.media_sessions_suspended());
- EnableTabletMode(true);
- PressPowerButton();
- ReleasePowerButton();
- // Run the event loop for PowerButtonDisplayController to get backlight state.
- base::RunLoop().RunUntilIdle();
- ASSERT_TRUE(power_manager_client()->backlights_forced_off());
- EXPECT_TRUE(client.media_sessions_suspended());
- }
- // Tests that when system is suspended with backlights forced off, and then
- // system resumes due to power button pressed without power button event fired
- // (crbug.com/735291), that we stop forcing off backlights.
- TEST_F(PowerButtonControllerTest, SuspendDoneStopsForcingOff) {
- EnableTabletMode(true);
- PressPowerButton();
- ReleasePowerButton();
- SendBrightnessChange(0, kUserCause);
- ASSERT_TRUE(power_manager_client()->backlights_forced_off());
- // Simulate an edge case that system resumes because of tablet power button
- // pressed, but power button event is not delivered.
- power_manager_client()->SendSuspendDone();
- EXPECT_FALSE(power_manager_client()->backlights_forced_off());
- }
- // Tests that during the interval that the display is turning on, tablet power
- // button should not set display off (crbug.com/735225).
- TEST_F(PowerButtonControllerTest, IgnoreForcingOffWhenDisplayIsTurningOn) {
- EnableTabletMode(true);
- PressPowerButton();
- ReleasePowerButton();
- SendBrightnessChange(0, kUserCause);
- ASSERT_TRUE(power_manager_client()->backlights_forced_off());
- // Simiulate the backlight no longer being forced off due to a key event
- // (which we need to briefly leave tablet mode to receive). Chrome will
- // receive a brightness changed signal, but the display may still be off.
- EnableTabletMode(false);
- PressKey(ui::VKEY_L);
- SendBrightnessChange(kNonZeroBrightness, kUserCause);
- EXPECT_FALSE(power_manager_client()->backlights_forced_off());
- // Since display could still be off, ignore additional button presses.
- tick_clock_.Advance(PowerButtonController::kScreenStateChangeDelay -
- base::Milliseconds(1));
- EnableTabletMode(true);
- PressPowerButton();
- ReleasePowerButton();
- EXPECT_FALSE(power_manager_client()->backlights_forced_off());
- // After waiting long enough, we should be able to force the display off.
- AdvanceClockToAvoidIgnoring();
- PressPowerButton();
- ReleasePowerButton();
- SendBrightnessChange(0, kUserCause);
- EXPECT_TRUE(power_manager_client()->backlights_forced_off());
- }
- // Tests that a11y alert is sent on tablet power button induced screen state
- // change.
- TEST_F(PowerButtonControllerTest, A11yAlert) {
- TestAccessibilityControllerClient a11y_client;
- EnableTabletMode(true);
- PressPowerButton();
- ReleasePowerButton();
- SendBrightnessChange(0, kUserCause);
- EXPECT_EQ(AccessibilityAlert::SCREEN_OFF, a11y_client.last_a11y_alert());
- PressPowerButton();
- SendBrightnessChange(kNonZeroBrightness, kUserCause);
- EXPECT_EQ(AccessibilityAlert::SCREEN_ON, a11y_client.last_a11y_alert());
- ReleasePowerButton();
- }
- // Tests that tap outside of the menu bounds should dismiss the menu.
- TEST_F(PowerButtonControllerTest, TapToDismissMenu) {
- OpenPowerButtonMenu();
- TapToDismissPowerButtonMenu();
- }
- // Test that mouse click outside of the menu bounds should dismiss the menu.
- TEST_F(PowerButtonControllerTest, MouseClickToDismissMenu) {
- OpenPowerButtonMenu();
- gfx::Rect menu_bounds = power_button_test_api_->GetMenuBoundsInScreen();
- ui::test::EventGenerator* generator = GetEventGenerator();
- generator->MoveMouseTo(gfx::Point(menu_bounds.x() - 5, menu_bounds.y() - 5));
- generator->ClickLeftButton();
- generator->ReleaseLeftButton();
- EXPECT_FALSE(power_button_test_api_->IsMenuOpened());
- }
- // Tests the menu items according to the login and screen locked status.
- TEST_F(PowerButtonControllerTest, MenuItemsToLoginAndLockedStatus) {
- // Should have feedback but not sign out and lock screen items if there is no
- // user signed in.
- ClearLogin();
- Shell::Get()->UpdateAfterLoginStatusChange(LoginStatus::NOT_LOGGED_IN);
- OpenPowerButtonMenu();
- EXPECT_FALSE(power_button_test_api_->MenuHasSignOutItem());
- EXPECT_FALSE(power_button_test_api_->MenuHasLockScreenItem());
- EXPECT_TRUE(power_button_test_api_->MenuHasFeedbackItem());
- TapToDismissPowerButtonMenu();
- // Should have sign out and feedback items if in guest mode (or, generally,
- // if screen locking is disabled).
- ClearLogin();
- Initialize(ButtonType::NORMAL, LoginStatus::GUEST);
- OpenPowerButtonMenu();
- EXPECT_FALSE(GetLockedState());
- EXPECT_TRUE(power_button_test_api_->MenuHasSignOutItem());
- EXPECT_FALSE(power_button_test_api_->MenuHasLockScreenItem());
- EXPECT_TRUE(power_button_test_api_->MenuHasFeedbackItem());
- TapToDismissPowerButtonMenu();
- // Should have sign out, lock screen and feedback items if user is logged in
- // and screen is unlocked.
- ClearLogin();
- CreateUserSessions(1);
- OpenPowerButtonMenu();
- EXPECT_FALSE(GetLockedState());
- EXPECT_TRUE(power_button_test_api_->MenuHasSignOutItem());
- EXPECT_TRUE(power_button_test_api_->MenuHasLockScreenItem());
- EXPECT_TRUE(power_button_test_api_->MenuHasFeedbackItem());
- TapToDismissPowerButtonMenu();
- // Should have sign out but not lock screen and feedback items if user is
- // logged in but screen is locked.
- LockScreen();
- EXPECT_TRUE(GetLockedState());
- OpenPowerButtonMenu();
- EXPECT_TRUE(power_button_test_api_->MenuHasSignOutItem());
- EXPECT_FALSE(power_button_test_api_->MenuHasLockScreenItem());
- EXPECT_FALSE(power_button_test_api_->MenuHasFeedbackItem());
- }
- // Tests long-pressing the power button when the menu is open.
- TEST_F(PowerButtonControllerTest, LongPressButtonWhenMenuIsOpened) {
- OpenPowerButtonMenu();
- AdvanceClockToAvoidIgnoring();
- // Long pressing the power button when menu is opened should not dismiss the
- // menu but trigger the pre-shutdown animation instead. Menu should stay
- // opened if releasing the button can cancel the animation.
- PressPowerButton();
- EXPECT_FALSE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
- ASSERT_TRUE(power_button_test_api_->TriggerPreShutdownTimeout());
- EXPECT_TRUE(lock_state_test_api_->shutdown_timer_is_running());
- ReleasePowerButton();
- EXPECT_FALSE(lock_state_test_api_->shutdown_timer_is_running());
- EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
- // Change focus to 'sign out'
- PressKey(ui::VKEY_TAB);
- EXPECT_TRUE(power_button_test_api_->GetPowerButtonMenuView()
- ->sign_out_item_for_test()
- ->HasFocus());
- // Long press when menu is opened with focus on 'sign out' item will change
- // the focus to 'power off' after starting the pre-shutdown animation.
- PressPowerButton();
- ASSERT_TRUE(power_button_test_api_->TriggerPreShutdownTimeout());
- EXPECT_TRUE(lock_state_test_api_->shutdown_timer_is_running());
- EXPECT_TRUE(power_button_test_api_->GetPowerButtonMenuView()
- ->power_off_item_for_test()
- ->HasFocus());
- ReleasePowerButton();
- }
- // Tests that switches between laptop mode and tablet mode should dismiss the
- // opened menu.
- TEST_F(PowerButtonControllerTest, EnterOrLeaveTabletModeDismissMenu) {
- OpenPowerButtonMenu();
- EnableTabletMode(true);
- EXPECT_FALSE(power_button_test_api_->IsMenuOpened());
- OpenPowerButtonMenu();
- EnableTabletMode(false);
- EXPECT_FALSE(power_button_test_api_->IsMenuOpened());
- }
- // Tests that screen changes to idle off will dismiss the opened menu.
- TEST_F(PowerButtonControllerTest, DismissMenuWhenScreenIsIdleOff) {
- OpenPowerButtonMenu();
- // Mock screen idle off.
- SendBrightnessChange(0, kUserCause);
- EXPECT_FALSE(power_button_test_api_->IsMenuOpened());
- }
- // Tests that tapping the power button should dimiss the opened menu.
- TEST_F(PowerButtonControllerTest, TappingPowerButtonWhenMenuIsOpened) {
- EnableTabletMode(true);
- OpenPowerButtonMenu();
- // Tapping the power button when menu is opened will dismiss the menu.
- AdvanceClockToAvoidIgnoring();
- PressPowerButton();
- ReleasePowerButton();
- SendBrightnessChange(0, kUserCause);
- EXPECT_TRUE(power_manager_client()->backlights_forced_off());
- EXPECT_FALSE(power_button_test_api_->IsMenuOpened());
- // Long press the power button when backlights are off will show the menu.
- PressPowerButton();
- SendBrightnessChange(kNonZeroBrightness, kUserCause);
- EXPECT_TRUE(power_button_test_api_->TriggerPowerButtonMenuTimeout());
- ReleasePowerButton();
- EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
- // Tapping the power button will dismiss the menu.
- AdvanceClockToAvoidIgnoring();
- PressPowerButton();
- ReleasePowerButton();
- SendBrightnessChange(0, kUserCause);
- EXPECT_TRUE(power_manager_client()->backlights_forced_off());
- EXPECT_FALSE(power_button_test_api_->IsMenuOpened());
- }
- // Tests that suspend will dismiss the opened menu.
- TEST_F(PowerButtonControllerTest, SuspendWithMenuOn) {
- OpenPowerButtonMenu();
- power_manager_client()->SendSuspendImminent(
- power_manager::SuspendImminent_Reason_OTHER);
- EXPECT_FALSE(power_button_test_api_->IsMenuOpened());
- power_manager_client()->SendSuspendDone();
- EXPECT_FALSE(power_button_test_api_->IsMenuOpened());
- }
- // Tests the formerly-active window state in showing power menu.
- TEST_F(PowerButtonControllerTest, FormerlyActiveWindowInShowingMenu) {
- std::unique_ptr<views::Widget> widget = CreateTestWidget();
- ASSERT_TRUE(widget->IsActive());
- OpenPowerButtonMenu();
- // The active window becomes inactive after menu is shown but it is still
- // painted as active to avoid frame color change.
- EXPECT_FALSE(widget->IsActive());
- EXPECT_TRUE(widget->ShouldPaintAsActive());
- EXPECT_TRUE(widget->non_client_view()->frame_view()->ShouldPaintAsActive());
- EXPECT_TRUE(
- wm::IsActiveWindow(power_button_test_api_->GetPowerButtonMenuView()
- ->GetWidget()
- ->GetNativeWindow()));
- // Should reset the previous painting as active setting of the active window
- // if dismissing the menu.
- TapToDismissPowerButtonMenu();
- // Focus may fall to the widget if it's the only remaining widget on the
- // screen. Deactivate it to verify that it's no longer being forced to render
- // as active.
- widget->Deactivate();
- EXPECT_FALSE(widget->ShouldPaintAsActive());
- // A widget which is not the active widget is not affected by opening the
- // power button menu.
- OpenPowerButtonMenu();
- EXPECT_FALSE(widget->ShouldPaintAsActive());
- TapToDismissPowerButtonMenu();
- // If focus didn't fall to the widget after the menu was closed, focus it.
- widget->Activate();
- // Dismiss menu should work well after the active window is closed between
- // showing and dismissing menu.
- OpenPowerButtonMenu();
- widget->Close();
- TapToDismissPowerButtonMenu();
- }
- // Tests that cursor is hidden after show the menu and should reappear if mouse
- // moves.
- TEST_F(PowerButtonControllerTest, HideCursorAfterShowMenu) {
- // Cursor is hidden after show the menu.
- ::wm::CursorManager* cursor_manager = Shell::Get()->cursor_manager();
- EXPECT_TRUE(cursor_manager->IsCursorVisible());
- PressPowerButton();
- ReleasePowerButton();
- EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
- EXPECT_FALSE(cursor_manager->IsCursorVisible());
- // Cursor reappears if mouse moves.
- GenerateMouseMoveEvent();
- EXPECT_TRUE(cursor_manager->IsCursorVisible());
- }
- // Tests that press VKEY_ESCAPE should dismiss the opened menu.
- TEST_F(PowerButtonControllerTest, ESCDismissMenu) {
- OpenPowerButtonMenu();
- PressKey(ui::VKEY_VOLUME_DOWN);
- EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
- PressKey(ui::VKEY_BRIGHTNESS_UP);
- EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
- PressKey(ui::VKEY_BROWSER_SEARCH);
- EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
- PressKey(ui::VKEY_ESCAPE);
- EXPECT_FALSE(power_button_test_api_->IsMenuOpened());
- }
- // Tests the navigation of the menu.
- TEST_F(PowerButtonControllerTest, MenuNavigation) {
- ClearLogin();
- Shell::Get()->UpdateAfterLoginStatusChange(LoginStatus::NOT_LOGGED_IN);
- OpenPowerButtonMenu();
- ASSERT_TRUE(power_button_test_api_->MenuHasFeedbackItem());
- auto* menu_view = power_button_test_api_->GetPowerButtonMenuView();
- PressKey(ui::VKEY_TAB);
- EXPECT_TRUE(menu_view->power_off_item_for_test()->HasFocus());
- PressKey(ui::VKEY_TAB);
- EXPECT_TRUE(menu_view->feedback_item_for_test()->HasFocus());
- TapToDismissPowerButtonMenu();
- ClearLogin();
- CreateUserSessions(1);
- OpenPowerButtonMenu();
- ASSERT_TRUE(power_button_test_api_->MenuHasSignOutItem());
- ASSERT_TRUE(power_button_test_api_->MenuHasLockScreenItem());
- ASSERT_TRUE(power_button_test_api_->MenuHasFeedbackItem());
- menu_view = power_button_test_api_->GetPowerButtonMenuView();
- PressKey(ui::VKEY_TAB);
- EXPECT_TRUE(menu_view->power_off_item_for_test()->HasFocus());
- PressKey(ui::VKEY_RIGHT);
- EXPECT_TRUE(menu_view->sign_out_item_for_test()->HasFocus());
- PressKey(ui::VKEY_DOWN);
- EXPECT_TRUE(menu_view->lock_screen_item_for_test()->HasFocus());
- PressKey(ui::VKEY_TAB);
- EXPECT_TRUE(menu_view->feedback_item_for_test()->HasFocus());
- PressKey(ui::VKEY_TAB);
- EXPECT_TRUE(menu_view->power_off_item_for_test()->HasFocus());
- PressKey(ui::VKEY_UP);
- EXPECT_TRUE(menu_view->feedback_item_for_test()->HasFocus());
- PressKey(ui::VKEY_UP);
- EXPECT_TRUE(menu_view->lock_screen_item_for_test()->HasFocus());
- PressKey(ui::VKEY_LEFT);
- EXPECT_TRUE(menu_view->sign_out_item_for_test()->HasFocus());
- PressKey(ui::VKEY_UP);
- EXPECT_TRUE(menu_view->power_off_item_for_test()->HasFocus());
- }
- // Tests that the partially shown menu will be dismissed by power button up in
- // tablet mode, and screen should not be turned off at the same time.
- TEST_F(PowerButtonControllerTest, PartiallyShownMenuInTabletMode) {
- EnableTabletMode(true);
- // Enable animations so that we can make sure that they occur.
- ui::ScopedAnimationDurationScaleMode regular_animations(
- ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
- PressPowerButton();
- EXPECT_TRUE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
- EXPECT_TRUE(power_button_test_api_->TriggerPowerButtonMenuTimeout());
- EXPECT_FALSE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
- // Power menu is in the partially shown state.
- EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
- EXPECT_FALSE(power_button_test_api_->ShowMenuAnimationDone());
- ReleasePowerButton();
- EXPECT_FALSE(power_button_test_api_->ShowMenuAnimationDone());
- // The partially shown menu should be dismissed by power button up.
- EXPECT_FALSE(power_button_test_api_->IsMenuOpened());
- // Screen should not be turned off with power button released.
- EXPECT_FALSE(power_manager_client()->backlights_forced_off());
- }
- class PowerButtonControllerWithPositionTest
- : public PowerButtonControllerTest,
- public testing::WithParamInterface<PowerButtonPosition> {
- public:
- PowerButtonControllerWithPositionTest() : power_button_position_(GetParam()) {
- base::DictionaryValue position_info;
- switch (power_button_position_) {
- case PowerButtonPosition::LEFT:
- position_info.SetStringKey(PowerButtonController::kEdgeField,
- PowerButtonController::kLeftEdge);
- break;
- case PowerButtonPosition::RIGHT:
- position_info.SetStringKey(PowerButtonController::kEdgeField,
- PowerButtonController::kRightEdge);
- break;
- case PowerButtonPosition::TOP:
- position_info.SetStringKey(PowerButtonController::kEdgeField,
- PowerButtonController::kTopEdge);
- break;
- case PowerButtonPosition::BOTTOM:
- position_info.SetStringKey(PowerButtonController::kEdgeField,
- PowerButtonController::kBottomEdge);
- break;
- default:
- return;
- }
- position_info.SetDoubleKey(PowerButtonController::kPositionField,
- kPowerButtonPercentage);
- std::string json_position_info;
- base::JSONWriter::Write(position_info, &json_position_info);
- base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
- switches::kAshPowerButtonPosition, json_position_info);
- }
- PowerButtonControllerWithPositionTest(
- const PowerButtonControllerWithPositionTest&) = delete;
- PowerButtonControllerWithPositionTest& operator=(
- const PowerButtonControllerWithPositionTest&) = delete;
- bool IsLeftOrRightPosition() const {
- return power_button_position_ == PowerButtonPosition::LEFT ||
- power_button_position_ == PowerButtonPosition::RIGHT;
- }
- // Returns true if it is in tablet mode.
- bool IsTabletMode() const {
- return Shell::Get()->tablet_mode_controller()->InTabletMode();
- }
- // Returns true if the menu is at the center of the display.
- bool IsMenuCentered() const {
- return power_button_test_api_->GetMenuBoundsInScreen().CenterPoint() ==
- display::Screen::GetScreen()
- ->GetPrimaryDisplay()
- .bounds()
- .CenterPoint();
- }
- PowerButtonPosition power_button_position() const {
- return power_button_position_;
- }
- private:
- PowerButtonPosition power_button_position_;
- };
- // TODO(crbug.com/1010194).
- TEST_P(PowerButtonControllerWithPositionTest,
- DISABLED_MenuNextToPowerButtonInTabletMode) {
- std::string display =
- std::to_string(kDisplayWidth) + "x" + std::to_string(kDisplayHeight);
- UpdateDisplay(display);
- display::test::ScopedSetInternalDisplayId set_internal(
- display_manager(), GetPrimaryDisplay().id());
- ScreenOrientationControllerTestApi test_api(
- Shell::Get()->screen_orientation_controller());
- // Set the screen orientation to LANDSCAPE_PRIMARY.
- test_api.SetDisplayRotation(display::Display::ROTATE_0,
- display::Display::RotationSource::ACTIVE);
- EXPECT_EQ(test_api.GetCurrentOrientation(),
- chromeos::OrientationType::kLandscapePrimary);
- // Menu is set at the center of the display if it is not in tablet mode.
- OpenPowerButtonMenu();
- ASSERT_FALSE(IsTabletMode());
- EXPECT_TRUE(IsMenuCentered());
- TapToDismissPowerButtonMenu();
- int animation_transform = PowerButtonMenuView::kMenuViewTransformDistanceDp;
- EnableTabletMode(true);
- EXPECT_TRUE(IsTabletMode());
- OpenPowerButtonMenu();
- EXPECT_FALSE(IsMenuCentered());
- if (power_button_position() == PowerButtonPosition::LEFT) {
- EXPECT_EQ(animation_transform,
- power_button_test_api_->GetMenuBoundsInScreen().x());
- } else if (power_button_position() == PowerButtonPosition::RIGHT) {
- EXPECT_EQ(animation_transform,
- kDisplayWidth -
- power_button_test_api_->GetMenuBoundsInScreen().right());
- } else if (power_button_position() == PowerButtonPosition::TOP) {
- EXPECT_EQ(animation_transform,
- power_button_test_api_->GetMenuBoundsInScreen().y());
- } else if (power_button_position() == PowerButtonPosition::BOTTOM) {
- EXPECT_EQ(animation_transform,
- kDisplayHeight -
- power_button_test_api_->GetMenuBoundsInScreen().bottom());
- }
- // Rotate the screen by 270 degree.
- test_api.SetDisplayRotation(display::Display::ROTATE_270,
- display::Display::RotationSource::ACTIVE);
- EXPECT_EQ(test_api.GetCurrentOrientation(),
- chromeos::OrientationType::kPortraitPrimary);
- EXPECT_FALSE(IsMenuCentered());
- if (power_button_position() == PowerButtonPosition::LEFT) {
- EXPECT_EQ(animation_transform,
- power_button_test_api_->GetMenuBoundsInScreen().y());
- } else if (power_button_position() == PowerButtonPosition::RIGHT) {
- EXPECT_EQ(animation_transform,
- kDisplayWidth -
- power_button_test_api_->GetMenuBoundsInScreen().bottom());
- } else if (power_button_position() == PowerButtonPosition::TOP) {
- EXPECT_EQ(animation_transform,
- kDisplayHeight -
- power_button_test_api_->GetMenuBoundsInScreen().right());
- } else if (power_button_position() == PowerButtonPosition::BOTTOM) {
- EXPECT_EQ(animation_transform,
- power_button_test_api_->GetMenuBoundsInScreen().x());
- }
- // Rotate the screen by 180 degree.
- test_api.SetDisplayRotation(display::Display::ROTATE_180,
- display::Display::RotationSource::ACTIVE);
- EXPECT_EQ(test_api.GetCurrentOrientation(),
- chromeos::OrientationType::kLandscapeSecondary);
- EXPECT_FALSE(IsMenuCentered());
- if (power_button_position() == PowerButtonPosition::LEFT) {
- EXPECT_EQ(animation_transform,
- kDisplayWidth -
- power_button_test_api_->GetMenuBoundsInScreen().right());
- } else if (power_button_position() == PowerButtonPosition::RIGHT) {
- EXPECT_EQ(animation_transform,
- power_button_test_api_->GetMenuBoundsInScreen().x());
- } else if (power_button_position() == PowerButtonPosition::TOP) {
- EXPECT_EQ(animation_transform,
- kDisplayHeight -
- power_button_test_api_->GetMenuBoundsInScreen().bottom());
- } else if (power_button_position() == PowerButtonPosition::BOTTOM) {
- EXPECT_EQ(animation_transform,
- power_button_test_api_->GetMenuBoundsInScreen().y());
- }
- // Rotate the screen by 90 degree.
- test_api.SetDisplayRotation(display::Display::ROTATE_90,
- display::Display::RotationSource::ACTIVE);
- EXPECT_EQ(test_api.GetCurrentOrientation(),
- chromeos::OrientationType::kPortraitSecondary);
- EXPECT_FALSE(IsMenuCentered());
- if (power_button_position() == PowerButtonPosition::LEFT) {
- EXPECT_EQ(animation_transform,
- kDisplayWidth -
- power_button_test_api_->GetMenuBoundsInScreen().bottom());
- } else if (power_button_position() == PowerButtonPosition::RIGHT) {
- EXPECT_EQ(animation_transform,
- power_button_test_api_->GetMenuBoundsInScreen().y());
- } else if (power_button_position() == PowerButtonPosition::TOP) {
- EXPECT_EQ(animation_transform,
- power_button_test_api_->GetMenuBoundsInScreen().x());
- } else if (power_button_position() == PowerButtonPosition::BOTTOM) {
- EXPECT_EQ(animation_transform,
- kDisplayHeight -
- power_button_test_api_->GetMenuBoundsInScreen().right());
- }
- }
- // Tests that the menu is always shown at the percentage of position when
- // display has different scale factors.
- TEST_P(PowerButtonControllerWithPositionTest, MenuShownAtPercentageOfPosition) {
- const int scale_factor = 2;
- std::string display = "8000x2400*" + std::to_string(scale_factor);
- UpdateDisplay(display);
- int64_t primary_id = GetPrimaryDisplay().id();
- display::test::ScopedSetInternalDisplayId set_internal(display_manager(),
- primary_id);
- ASSERT_EQ(scale_factor, GetPrimaryDisplay().device_scale_factor());
- EnableTabletMode(true);
- OpenPowerButtonMenu();
- EXPECT_FALSE(IsMenuCentered());
- gfx::Point menu_center_point =
- power_button_test_api_->GetMenuBoundsInScreen().CenterPoint();
- gfx::Rect display_bounds = GetPrimaryDisplay().bounds();
- int original_width = display_bounds.width();
- int original_height = display_bounds.height();
- if (IsLeftOrRightPosition()) {
- EXPECT_EQ(menu_center_point.y(), static_cast<int>(display_bounds.height() *
- kPowerButtonPercentage));
- } else {
- EXPECT_EQ(menu_center_point.x(), static_cast<int>(display_bounds.width() *
- kPowerButtonPercentage));
- }
- TapToDismissPowerButtonMenu();
- display_manager()->UpdateZoomFactor(primary_id, 1.f / scale_factor);
- ASSERT_EQ(1.0f, GetPrimaryDisplay().device_scale_factor());
- display_bounds = GetPrimaryDisplay().bounds();
- int scale_up_width = display_bounds.width();
- int scale_up_height = display_bounds.height();
- EXPECT_EQ(scale_up_width, original_width * scale_factor);
- EXPECT_EQ(scale_up_height, original_height * scale_factor);
- OpenPowerButtonMenu();
- menu_center_point =
- power_button_test_api_->GetMenuBoundsInScreen().CenterPoint();
- // Menu is still at the kPowerButtonPercentage position after scale up screen.
- if (IsLeftOrRightPosition()) {
- EXPECT_EQ(menu_center_point.y(), static_cast<int>(display_bounds.height() *
- kPowerButtonPercentage));
- } else {
- EXPECT_EQ(menu_center_point.x(), static_cast<int>(display_bounds.width() *
- kPowerButtonPercentage));
- }
- }
- TEST_P(PowerButtonControllerWithPositionTest, AdjustMenuShownForDisplaySize) {
- OpenPowerButtonMenu();
- gfx::Rect menu_bounds = power_button_test_api_->GetMenuBoundsInScreen();
- TapToDismissPowerButtonMenu();
- // (1 - kPowerButtonPercentage) * display_height < 0.5 * menu_height makes
- // sure menu will be cut off by display when button is on LEFT/RIGHT, and (1 -
- // kPowerButtonPercentage) * display_width < 0.5 * menu_width makes sure menu
- // will be cut off by display when button is on TOP/BOTTOM.
- int display_width =
- 0.5 / (1.0f - kPowerButtonPercentage) * menu_bounds.width() - 5;
- int display_height =
- 0.5 / (1.0f - kPowerButtonPercentage) * menu_bounds.height() - 5;
- std::string display =
- std::to_string(display_width) + "x" + std::to_string(display_height);
- UpdateDisplay(display);
- display::test::ScopedSetInternalDisplayId set_internal(
- display_manager(), GetPrimaryDisplay().id());
- ScreenOrientationControllerTestApi test_api(
- Shell::Get()->screen_orientation_controller());
- // Set the screen orientation to LANDSCAPE_PRIMARY.
- test_api.SetDisplayRotation(display::Display::ROTATE_0,
- display::Display::RotationSource::ACTIVE);
- EXPECT_EQ(test_api.GetCurrentOrientation(),
- chromeos::OrientationType::kLandscapePrimary);
- EnableTabletMode(true);
- OpenPowerButtonMenu();
- // Menu's bounds is always inside the display.
- EXPECT_TRUE(GetPrimaryDisplay().bounds().Contains(
- power_button_test_api_->GetMenuBoundsInScreen()));
- // Rotate the screen by 270 degrees.
- test_api.SetDisplayRotation(display::Display::ROTATE_270,
- display::Display::RotationSource::ACTIVE);
- EXPECT_EQ(test_api.GetCurrentOrientation(),
- chromeos::OrientationType::kPortraitPrimary);
- EXPECT_TRUE(GetPrimaryDisplay().bounds().Contains(
- power_button_test_api_->GetMenuBoundsInScreen()));
- // Rotate the screen by 180 degrees.
- test_api.SetDisplayRotation(display::Display::ROTATE_180,
- display::Display::RotationSource::ACTIVE);
- EXPECT_EQ(test_api.GetCurrentOrientation(),
- chromeos::OrientationType::kLandscapeSecondary);
- EXPECT_TRUE(GetPrimaryDisplay().bounds().Contains(
- power_button_test_api_->GetMenuBoundsInScreen()));
- // Rotate the screen by 90 degrees.
- test_api.SetDisplayRotation(display::Display::ROTATE_90,
- display::Display::RotationSource::ACTIVE);
- EXPECT_EQ(test_api.GetCurrentOrientation(),
- chromeos::OrientationType::kPortraitSecondary);
- EXPECT_TRUE(GetPrimaryDisplay().bounds().Contains(
- power_button_test_api_->GetMenuBoundsInScreen()));
- }
- // Disabled due to consistent failures. http://crbug.com/1286199
- // Tests that a power button press before the menu is fully shown will not
- // create a new menu.
- TEST_F(PowerButtonControllerTest, DISABLED_LegacyPowerButtonIgnoreExtraPress) {
- Initialize(ButtonType::LEGACY, LoginStatus::USER);
- // Enable animations so that we can make sure that they occur.
- ui::ScopedAnimationDurationScaleMode regular_animations(
- ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
- PressPowerButton();
- // Power menu is in the partially shown state.
- ASSERT_TRUE(power_button_test_api_->IsMenuOpened());
- ASSERT_FALSE(power_button_test_api_->ShowMenuAnimationDone());
- PowerButtonMenuView* menu_view_before =
- power_button_test_api_->GetPowerButtonMenuView();
- // Press power button again and make sure new PowerButtonMenuView is not
- // created. This makes sure that we do not create a new menu while we are in
- // the process of creating one for an old power button press.
- PressPowerButton();
- EXPECT_EQ(menu_view_before, power_button_test_api_->GetPowerButtonMenuView());
- // This is needed to simulate the shutdown sound having been played,
- // which blocks the shutdown timer.
- // Make sure that the second press did not trigger a shutdown.
- EXPECT_FALSE(lock_state_test_api_->real_shutdown_timer_is_running());
- // Make sure that power menu is still in partially shown state.
- ASSERT_TRUE(power_button_test_api_->IsMenuOpened());
- ASSERT_FALSE(power_button_test_api_->ShowMenuAnimationDone());
- }
- TEST_F(PowerButtonControllerTest,
- ArcPowerButtonEventShowMenuWithoutPreShutdown) {
- LaunchArcPowerButtonEvent();
- ASSERT_TRUE(power_button_test_api_->IsMenuOpened());
- EXPECT_FALSE(power_button_test_api_->TriggerPreShutdownTimeout());
- EXPECT_FALSE(lock_state_test_api_->shutdown_timer_is_running());
- EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
- }
- INSTANTIATE_TEST_SUITE_P(AshPowerButtonPosition,
- PowerButtonControllerWithPositionTest,
- testing::Values(PowerButtonPosition::LEFT,
- PowerButtonPosition::RIGHT,
- PowerButtonPosition::TOP,
- PowerButtonPosition::BOTTOM));
- } // namespace ash
|