Commit c8d3eed1 authored by Min Chen's avatar Min Chen Committed by Commit Bot

ash: Make power menu item focusable and start pre-shutdown

     animation after 'Power off' item has focused for
     a while after showing.

focus related spec:
https://drive.google.com/file/d/1JNH0ZDknXSvV00C7TeT4xT_rFx48OdZd/view

changes in this cl,
- Set pre_shutdown_timer_ in PowerButtonController to start the cancellable
  pre-shutdown animation after power menu has been shown for 650ms. And remove
  the previous shutdown_timer_ which will start the clean shutdown after
  pressing power button for 3s.

- Add power button menu item focus. Focus on the 'Power off' item after menu is
  shown.

- Since we add the cancellable pre-shutdown animation back in this cl. Add the
  related tests in LockStateControllerTest back which removed in the previous cl
  https://chromium-review.googlesource.com/c/chromium/src/+/916838

- Modify related tests.

Bug: 826064
Change-Id: Ibefb22067f5bd37849eb1b8c3fb3143f5d3b8dc8
Reviewed-on: https://chromium-review.googlesource.com/991398
Commit-Queue: Min Chen <minch@chromium.org>
Reviewed-by: default avatarQiang Xu <warx@google.com>
Reviewed-by: default avatarDan Erat <derat@chromium.org>
Cr-Commit-Position: refs/heads/master@{#547820}
parent c5f35620
......@@ -17,7 +17,9 @@
#include "ash/shell_port.h"
#include "ash/shutdown_reason.h"
#include "ash/system/power/power_button_display_controller.h"
#include "ash/system/power/power_button_menu_item_view.h"
#include "ash/system/power/power_button_menu_screen_view.h"
#include "ash/system/power/power_button_menu_view.h"
#include "ash/system/power/power_button_screenshot_controller.h"
#include "ash/wm/lock_state_controller.h"
#include "ash/wm/session_state_animator.h"
......@@ -43,9 +45,10 @@ constexpr base::TimeDelta kShowMenuWhenScreenOnTimeout =
constexpr base::TimeDelta kShowMenuWhenScreenOffTimeout =
base::TimeDelta::FromMilliseconds(2000);
// Time that power button should be pressed before starting to shutdown.
constexpr base::TimeDelta kStartShutdownTimeout =
base::TimeDelta::FromSeconds(3);
// Time that power button should be pressed after power menu is shown before
// starting the cancellable pre-shutdown animation.
constexpr base::TimeDelta kStartShutdownAnimationTimeout =
base::TimeDelta::FromMilliseconds(650);
// Creates a fullscreen widget responsible for showing the power button menu.
std::unique_ptr<views::Widget> CreateMenuWidget() {
......@@ -234,16 +237,16 @@ void PowerButtonController::OnPowerButtonEvent(
FROM_HERE, timeout, this,
&PowerButtonController::StartPowerMenuAnimation);
}
shutdown_timer_.Start(FROM_HERE, kStartShutdownTimeout, this,
&PowerButtonController::OnShutdownTimeout);
} else {
if (lock_state_controller_->CanCancelShutdownAnimation())
lock_state_controller_->CancelShutdownAnimation();
const base::TimeTicks previous_up_time = last_button_up_time_;
last_button_up_time_ = timestamp;
const bool menu_timer_was_running = power_button_menu_timer_.IsRunning();
power_button_menu_timer_.Stop();
shutdown_timer_.Stop();
pre_shutdown_timer_.Stop();
// Ignore the event if it comes too soon after the last one.
if (timestamp - previous_up_time <= kIgnoreRepeatedButtonUpDelay)
......@@ -416,7 +419,7 @@ bool PowerButtonController::ShouldTurnScreenOffForTap() const {
}
void PowerButtonController::StopTimersAndDismissMenu() {
shutdown_timer_.Stop();
pre_shutdown_timer_.Stop();
power_button_menu_timer_.Stop();
DismissMenu();
}
......@@ -446,11 +449,6 @@ void PowerButtonController::StartPowerMenuAnimation() {
->ScheduleShowHideAnimation(true);
}
void PowerButtonController::OnShutdownTimeout() {
display_controller_->SetBacklightsForcedOff(true);
lock_state_controller_->RequestShutdown(ShutdownReason::POWER_BUTTON);
}
void PowerButtonController::ProcessCommandLine() {
const base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
button_type_ = cl->HasSwitch(switches::kAuraLegacyPowerButton)
......@@ -486,6 +484,21 @@ void PowerButtonController::LockScreenIfRequired() {
void PowerButtonController::SetShowMenuAnimationDone() {
show_menu_animation_done_ = true;
DCHECK(menu_widget_->GetContentsView());
// Focus on 'Power off' when menu is shown.
static_cast<PowerButtonMenuScreenView*>(menu_widget_->GetContentsView())
->power_button_menu_view()
->power_off_item()
->RequestFocus();
pre_shutdown_timer_.Start(
FROM_HERE, kStartShutdownAnimationTimeout,
base::BindRepeating(
[](LockStateController* controller) {
controller->StartShutdownAnimation(ShutdownReason::POWER_BUTTON);
},
lock_state_controller_));
}
void PowerButtonController::ParsePowerButtonPositionSwitch() {
......
......@@ -159,9 +159,6 @@ class ASH_EXPORT PowerButtonController
// button is pressed or when |power_button_menu_timer_| fires.
void StartPowerMenuAnimation();
// Called by |shutdown_timer_| to turn the screen off and request shutdown.
void OnShutdownTimeout();
// Updates |button_type_| and |force_clamshell_power_button_| based on the
// current command line.
void ProcessCommandLine();
......@@ -245,9 +242,10 @@ class ASH_EXPORT PowerButtonController
// Saves the most recent timestamp that power button was released.
base::TimeTicks last_button_up_time_;
// Started when the power button is pressed and stopped when it's released.
// Runs OnShutdownTimeout() to start shutdown.
base::OneShotTimer shutdown_timer_;
// Started when |show_menu_animation_done_| is set to true and stopped when
// power button is released. Runs OnPreShutdownTimeout() to start the
// cancellable pre-shutdown animation.
base::OneShotTimer pre_shutdown_timer_;
// Started when the power button of convertible/slate/detachable devices is
// pressed and stopped when it's released. Runs StartPowerMenuAnimation() to
......
......@@ -20,16 +20,16 @@ PowerButtonControllerTestApi::PowerButtonControllerTestApi(
PowerButtonControllerTestApi::~PowerButtonControllerTestApi() = default;
bool PowerButtonControllerTestApi::ShutdownTimerIsRunning() const {
return controller_->shutdown_timer_.IsRunning();
bool PowerButtonControllerTestApi::PreShutdownTimerIsRunning() const {
return controller_->pre_shutdown_timer_.IsRunning();
}
bool PowerButtonControllerTestApi::TriggerShutdownTimeout() {
if (!controller_->shutdown_timer_.IsRunning())
bool PowerButtonControllerTestApi::TriggerPreShutdownTimeout() {
if (!controller_->pre_shutdown_timer_.IsRunning())
return false;
base::Closure task = controller_->shutdown_timer_.user_task();
controller_->shutdown_timer_.Stop();
base::Closure task = controller_->pre_shutdown_timer_.user_task();
controller_->pre_shutdown_timer_.Stop();
task.Run();
return true;
}
......
......@@ -31,12 +31,12 @@ class PowerButtonControllerTestApi {
explicit PowerButtonControllerTestApi(PowerButtonController* controller);
~PowerButtonControllerTestApi();
// Returns true when |controller_->shutdown_timer_| is running.
bool ShutdownTimerIsRunning() const;
// Returns true when |controller_->pre_shutdown_timer_| is running.
bool PreShutdownTimerIsRunning() const;
// If |controller_->shutdown_timer_| is running, stops it, runs its task, and
// returns true. Otherwise, returns false.
bool TriggerShutdownTimeout() WARN_UNUSED_RESULT;
// If |controller_->pre_shutdown_timer_| is running, stops it, runs its task,
// and returns true. Otherwise, returns false.
bool TriggerPreShutdownTimeout() WARN_UNUSED_RESULT;
// Returns true when |power_button_menu_timer_| is running.
bool PowerButtonMenuTimerIsRunning() const;
......
......@@ -15,6 +15,7 @@
#include "ash/session/session_controller.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"
......@@ -129,6 +130,10 @@ class PowerButtonControllerTest : public PowerButtonTestBase {
ASSERT_TRUE(power_button_test_api_->TriggerPowerButtonMenuTimeout());
ReleasePowerButton();
ASSERT_TRUE(power_button_test_api_->IsMenuOpened());
// "Power off" item has focus after menu is opened.
EXPECT_TRUE(power_button_test_api_->GetPowerButtonMenuView()
->power_off_item()
->HasFocus());
}
// Tap outside of the menu view to dismiss the menu.
......@@ -290,48 +295,20 @@ TEST_F(PowerButtonControllerTest, ModeSpecificPowerButton) {
// Tests that release power button after menu is opened but before trigger
// shutdown will not turn screen off.
TEST_F(PowerButtonControllerTest, ReleasePowerButtonAfterShowPowerButtonMenu) {
TEST_F(PowerButtonControllerTest, ReleasePowerButtonBeforeTriggerShutdown) {
PressPowerButton();
EXPECT_TRUE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
EXPECT_TRUE(power_button_test_api_->ShutdownTimerIsRunning());
EXPECT_FALSE(power_manager_client_->backlights_forced_off());
EXPECT_TRUE(power_button_test_api_->TriggerPowerButtonMenuTimeout());
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(power_button_test_api_->ShutdownTimerIsRunning());
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 the real shutdown is started if the power button is released
// after the timer fires when screen is on.
TEST_F(PowerButtonControllerTest, RealShutdownIfScreenIsOn) {
PressPowerButton();
EXPECT_TRUE(power_button_test_api_->TriggerShutdownTimeout());
ShutdownSoundPlayed();
EXPECT_TRUE(lock_state_test_api_->real_shutdown_timer_is_running());
ReleasePowerButton();
EXPECT_TRUE(power_manager_client_->backlights_forced_off());
// Release power button if real shutdown started will not cancel the shutdown.
EXPECT_TRUE(lock_state_test_api_->real_shutdown_timer_is_running());
}
// Tests that the real shutdown is started if the power button is released
// after the timer fires when screen is off.
TEST_F(PowerButtonControllerTest, RealShutdownIfScreenIsOff) {
// Press power button to turn screen off.
PressPowerButton();
ReleaseLockButton();
PressPowerButton();
EXPECT_TRUE(power_button_test_api_->TriggerShutdownTimeout());
ShutdownSoundPlayed();
EXPECT_TRUE(lock_state_test_api_->real_shutdown_timer_is_running());
ReleasePowerButton();
EXPECT_TRUE(power_manager_client_->backlights_forced_off());
// Release power button if real shutdown started will not cancel the shutdown.
EXPECT_TRUE(lock_state_test_api_->real_shutdown_timer_is_running());
}
// Should dismiss the menu if locking screen when menu is opened.
TEST_F(PowerButtonControllerTest, LockScreenIfMenuIsOpened) {
Initialize(ButtonType::NORMAL, LoginStatus::USER);
......@@ -407,19 +384,19 @@ TEST_F(PowerButtonControllerTest,
// are not forced off.
tick_clock_.Advance(base::TimeDelta::FromMilliseconds(500));
PressPowerButton();
EXPECT_TRUE(power_button_test_api_->ShutdownTimerIsRunning());
EXPECT_TRUE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
ReleasePowerButton();
EXPECT_FALSE(power_button_test_api_->ShutdownTimerIsRunning());
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::TimeDelta::FromMilliseconds(1600));
PressPowerButton();
EXPECT_TRUE(power_button_test_api_->ShutdownTimerIsRunning());
EXPECT_TRUE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
ReleasePowerButton();
SendBrightnessChange(0, kUserCause);
EXPECT_FALSE(power_button_test_api_->ShutdownTimerIsRunning());
EXPECT_FALSE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
EXPECT_TRUE(power_manager_client_->backlights_forced_off());
}
......@@ -443,19 +420,19 @@ TEST_F(PowerButtonControllerTest,
tick_clock_.Advance(base::TimeDelta::FromMilliseconds(500));
PressPowerButton();
SendBrightnessChange(kNonZeroBrightness, kUserCause);
EXPECT_TRUE(power_button_test_api_->ShutdownTimerIsRunning());
EXPECT_TRUE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
ReleasePowerButton();
EXPECT_FALSE(power_button_test_api_->ShutdownTimerIsRunning());
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::TimeDelta::FromMilliseconds(1600));
PressPowerButton();
EXPECT_TRUE(power_button_test_api_->ShutdownTimerIsRunning());
EXPECT_TRUE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
ReleasePowerButton();
SendBrightnessChange(0, kUserCause);
EXPECT_FALSE(power_button_test_api_->ShutdownTimerIsRunning());
EXPECT_FALSE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
EXPECT_TRUE(power_manager_client_->backlights_forced_off());
}
......@@ -598,10 +575,8 @@ TEST_F(PowerButtonControllerTest, DisableTouchscreenForInactivity) {
TEST_F(PowerButtonControllerTest,
EnterOrLeaveTabletModeWhilePressingPowerButton) {
PressPowerButton();
EXPECT_TRUE(power_button_test_api_->ShutdownTimerIsRunning());
EXPECT_TRUE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
power_button_controller_->OnTabletModeStarted();
EXPECT_FALSE(power_button_test_api_->ShutdownTimerIsRunning());
EXPECT_FALSE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
tick_clock_.Advance(base::TimeDelta::FromMilliseconds(1500));
ReleasePowerButton();
......@@ -609,10 +584,8 @@ TEST_F(PowerButtonControllerTest,
EXPECT_FALSE(power_button_test_api_->IsMenuOpened());
PressPowerButton();
EXPECT_TRUE(power_button_test_api_->ShutdownTimerIsRunning());
EXPECT_TRUE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
power_button_controller_->OnTabletModeEnded();
EXPECT_FALSE(power_button_test_api_->ShutdownTimerIsRunning());
EXPECT_FALSE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
tick_clock_.Advance(base::TimeDelta::FromMilliseconds(2500));
ReleasePowerButton();
......
......@@ -9,6 +9,7 @@
#include "ui/gfx/color_palette.h"
#include "ui/gfx/font.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/views/border.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
......@@ -35,6 +36,17 @@ constexpr int kIconTopPadding = 16;
// Top padding of the label of title to the top of the item view.
constexpr int kTitleTopPadding = 53;
// The amount of rounding applied to the corners of the focused menu item.
constexpr int kFocusedItemRoundRectRadiusDp = 8;
// Color of the focused menu item's border.
constexpr SkColor kFocusedItemBorderColor =
SkColorSetARGBMacro(0x66, 0x1A, 0x73, 0xE8);
// Color of the focused menu item.
constexpr SkColor kFocusedItemColor =
SkColorSetARGBMacro(0x0A, 0x1A, 0x73, 0xE8);
} // namespace
PowerButtonMenuItemView::PowerButtonMenuItemView(
......@@ -44,6 +56,8 @@ PowerButtonMenuItemView::PowerButtonMenuItemView(
: views::ImageButton(listener),
icon_view_(new views::ImageView),
title_(new views::Label) {
SetFocusBehavior(FocusBehavior::ALWAYS);
SetFocusPainter(nullptr);
SetPaintToLayer();
icon_view_->SetImage(gfx::CreateVectorIcon(icon, kItemIconColor));
AddChildView(icon_view_);
......@@ -57,6 +71,10 @@ PowerButtonMenuItemView::PowerButtonMenuItemView(
title_->SetEnabledColor(kItemTitleColor);
title_->SetText(title_text);
AddChildView(title_);
SetBorder(views::CreateEmptyBorder(kItemBorderThickness, kItemBorderThickness,
kItemBorderThickness,
kItemBorderThickness));
}
PowerButtonMenuItemView::~PowerButtonMenuItemView() = default;
......@@ -77,12 +95,29 @@ void PowerButtonMenuItemView::Layout() {
}
gfx::Size PowerButtonMenuItemView::CalculatePreferredSize() const {
return gfx::Size(kMenuItemWidth, kMenuItemHeight);
return gfx::Size(kMenuItemWidth + 2 * kItemBorderThickness,
kMenuItemHeight + 2 * kItemBorderThickness);
}
void PowerButtonMenuItemView::OnFocus() {
SchedulePaint();
}
void PowerButtonMenuItemView::OnBlur() {
SchedulePaint();
}
void PowerButtonMenuItemView::PaintButtonContents(gfx::Canvas* canvas) {
views::View::OnPaint(canvas);
canvas->DrawColor(SK_ColorWHITE);
if (!HasFocus() || GetContentsBounds().IsEmpty())
return;
SetBorder(views::CreateRoundedRectBorder(kItemBorderThickness,
kFocusedItemRoundRectRadiusDp,
kFocusedItemBorderColor));
canvas->FillRect(GetContentsBounds(), kFocusedItemColor);
views::View::OnPaintBorder(canvas);
}
} // namespace ash
......@@ -30,6 +30,9 @@ class ASH_EXPORT PowerButtonMenuItemView : public views::ImageButton {
// Width of the menu item in pixels.
static constexpr int kMenuItemWidth = 84;
// Thickness of the menu item's border in pixels.
static constexpr int kItemBorderThickness = 2;
PowerButtonMenuItemView(views::ButtonListener* listener,
const gfx::VectorIcon& icon,
const base::string16& title_text);
......@@ -39,6 +42,8 @@ class ASH_EXPORT PowerButtonMenuItemView : public views::ImageButton {
// views::View:
void Layout() override;
gfx::Size CalculatePreferredSize() const override;
void OnFocus() override;
void OnBlur() override;
// views::ImageButton:
void PaintButtonContents(gfx::Canvas* canvas) override;
......
......@@ -29,7 +29,7 @@ constexpr int kMenuItemVerticalPadding = 16;
constexpr int kMenuViewRoundRectRadiusDp = 16;
// Horizontal padding between two menu items.
constexpr int kPaddingBetweenMenuItems = 8;
constexpr int kPaddingBetweenMenuItmes = 8;
} // namespace
......@@ -145,8 +145,10 @@ void PowerButtonMenuView::Layout() {
const gfx::Rect rect(GetContentsBounds());
gfx::Rect power_off_rect(rect);
power_off_rect.set_size(power_off_item_->GetPreferredSize());
power_off_rect.Offset(
gfx::Vector2d(kMenuItemVerticalPadding, kMenuItemHorizontalPadding));
power_off_rect.Offset(gfx::Vector2d(
kMenuItemVerticalPadding - PowerButtonMenuItemView::kItemBorderThickness,
kMenuItemHorizontalPadding -
PowerButtonMenuItemView::kItemBorderThickness));
power_off_item_->SetBoundsRect(power_off_rect);
if (sign_out_item_) {
......@@ -155,8 +157,10 @@ void PowerButtonMenuView::Layout() {
sign_out_rect.Offset(
gfx::Vector2d(kMenuItemHorizontalPadding +
power_off_item_->GetPreferredSize().width() +
kPaddingBetweenMenuItems,
kMenuItemVerticalPadding));
kPaddingBetweenMenuItmes -
PowerButtonMenuItemView::kItemBorderThickness,
kMenuItemVerticalPadding -
PowerButtonMenuItemView::kItemBorderThickness));
sign_out_item_->SetBoundsRect(sign_out_rect);
}
}
......@@ -182,7 +186,7 @@ gfx::Size PowerButtonMenuView::CalculatePreferredSize() const {
menu_size.set_width(sign_out_item_
? 2 * PowerButtonMenuItemView::kMenuItemWidth +
2 * kMenuItemHorizontalPadding +
kPaddingBetweenMenuItems
kPaddingBetweenMenuItmes
: PowerButtonMenuItemView::kMenuItemWidth +
2 * kMenuItemHorizontalPadding);
return menu_size;
......
......@@ -44,6 +44,8 @@ class ASH_EXPORT PowerButtonMenuView : public views::View,
bool sign_out_item_for_testing() const { return sign_out_item_; }
PowerButtonMenuItemView* power_off_item() const { return power_off_item_; }
// Schedules an animation to show or hide the view.
void ScheduleShowHideAnimation(bool show);
......
......@@ -187,10 +187,8 @@ TEST_F(PowerButtonScreenshotControllerTest,
// Tests volume down key can stop power button's shutdown timer and power
// button menu timer.
PressPowerButton();
EXPECT_TRUE(power_button_test_api_->ShutdownTimerIsRunning());
EXPECT_TRUE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
PressKey(ui::VKEY_VOLUME_DOWN);
EXPECT_FALSE(power_button_test_api_->ShutdownTimerIsRunning());
EXPECT_FALSE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
ReleasePowerButton();
ReleaseKey(ui::VKEY_VOLUME_DOWN);
......@@ -199,11 +197,9 @@ TEST_F(PowerButtonScreenshotControllerTest,
// Tests volume up key can stop power button's shutdown timer and power button
// menu timer. Also tests that volume up key is not consumed.
PressPowerButton();
EXPECT_TRUE(power_button_test_api_->ShutdownTimerIsRunning());
EXPECT_TRUE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
PressKey(ui::VKEY_VOLUME_UP);
EXPECT_FALSE(LastKeyConsumed());
EXPECT_FALSE(power_button_test_api_->ShutdownTimerIsRunning());
EXPECT_FALSE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
ReleasePowerButton();
ReleaseKey(ui::VKEY_VOLUME_UP);
......@@ -211,20 +207,19 @@ TEST_F(PowerButtonScreenshotControllerTest,
EXPECT_FALSE(LastKeyConsumed());
}
// Tests volume key pressed can not cancel the started real shutdown.
// Tests volume key pressed can not cancel the started pre-shutdown animation.
TEST_F(PowerButtonScreenshotControllerTest,
PowerButtonPressedFirst_VolumeKeyNotCancelPowerButton) {
// Power button shutdown behavior will turn screen off and then start the real
// shutdown.
PressPowerButton();
EXPECT_TRUE(power_button_test_api_->TriggerShutdownTimeout());
ShutdownSoundPlayed();
EXPECT_TRUE(lock_state_test_api_->real_shutdown_timer_is_running());
ASSERT_TRUE(power_button_test_api_->TriggerPowerButtonMenuTimeout());
EXPECT_TRUE(power_button_test_api_->PreShutdownTimerIsRunning());
EXPECT_TRUE(power_button_test_api_->TriggerPreShutdownTimeout());
EXPECT_TRUE(lock_state_test_api_->shutdown_timer_is_running());
PressKey(ui::VKEY_VOLUME_DOWN);
ReleasePowerButton();
ReleaseKey(ui::VKEY_VOLUME_DOWN);
EXPECT_TRUE(power_manager_client_->backlights_forced_off());
EXPECT_TRUE(lock_state_test_api_->real_shutdown_timer_is_running());
EXPECT_TRUE(lock_state_test_api_->shutdown_timer_is_running());
ReleasePowerButton();
EXPECT_FALSE(lock_state_test_api_->shutdown_timer_is_running());
}
// Tests volume down key pressed first and meets screenshot chord condition.
......@@ -300,7 +295,6 @@ TEST_F(PowerButtonScreenshotControllerTest,
// Tests volume down key invalidates the power button behavior.
PressKey(ui::VKEY_VOLUME_DOWN);
PressPowerButton();
EXPECT_FALSE(power_button_test_api_->ShutdownTimerIsRunning());
EXPECT_FALSE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
ReleasePowerButton();
ReleaseKey(ui::VKEY_VOLUME_DOWN);
......@@ -311,7 +305,6 @@ TEST_F(PowerButtonScreenshotControllerTest,
PressKey(ui::VKEY_VOLUME_UP);
PressPowerButton();
EXPECT_FALSE(LastKeyConsumed());
EXPECT_FALSE(power_button_test_api_->ShutdownTimerIsRunning());
EXPECT_FALSE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
ReleasePowerButton();
ReleaseKey(ui::VKEY_VOLUME_UP);
......
......@@ -4,7 +4,6 @@
#include "ash/system/power/power_button_test_base.h"
#include "ash/accessibility/accessibility_controller.h"
#include "ash/public/cpp/ash_switches.h"
#include "ash/session/session_controller.h"
#include "ash/session/test_session_controller_client.h"
......@@ -44,9 +43,6 @@ void PowerButtonTestBase::SetUp() {
lock_state_controller_ = Shell::Get()->lock_state_controller();
lock_state_test_api_ =
std::make_unique<LockStateControllerTestApi>(lock_state_controller_);
a11y_controller_ = Shell::Get()->accessibility_controller();
a11y_controller_->SetClient(a11y_client_.CreateInterfacePtrAndBind());
}
void PowerButtonTestBase::TearDown() {
......@@ -148,8 +144,4 @@ void PowerButtonTestBase::AdvanceClockToAvoidIgnoring() {
base::TimeDelta::FromMilliseconds(1));
}
void PowerButtonTestBase::ShutdownSoundPlayed() {
a11y_controller_->FlushMojoForTest();
}
} // namespace ash
......@@ -7,7 +7,6 @@
#include <memory>
#include "ash/accessibility/test_accessibility_controller_client.h"
#include "ash/system/power/power_button_controller.h"
#include "ash/test/ash_test_base.h"
#include "base/test/simple_test_tick_clock.h"
......@@ -20,7 +19,6 @@ class FakeSessionManagerClient;
namespace ash {
class AccessibilityController;
class LockStateController;
class LockStateControllerTestApi;
class PowerButtonControllerTestApi;
......@@ -93,9 +91,6 @@ class PowerButtonTestBase : public AshTestBase {
// they come too close.
void AdvanceClockToAvoidIgnoring();
// Simulate that shutdown sound duration callback is done.
void ShutdownSoundPlayed();
// Ownership is passed on to chromeos::DBusThreadManager.
chromeos::FakePowerManagerClient* power_manager_client_ = nullptr;
chromeos::FakeSessionManagerClient* session_manager_client_ = nullptr;
......@@ -107,8 +102,6 @@ class PowerButtonTestBase : public AshTestBase {
std::unique_ptr<LockStateControllerTestApi> lock_state_test_api_;
std::unique_ptr<PowerButtonControllerTestApi> power_button_test_api_;
base::SimpleTestTickClock tick_clock_;
AccessibilityController* a11y_controller_;
TestAccessibilityControllerClient a11y_client_;
DISALLOW_COPY_AND_ASSIGN(PowerButtonTestBase);
};
......
......@@ -7,6 +7,8 @@
#include <memory>
#include <utility>
#include "ash/accessibility/accessibility_controller.h"
#include "ash/accessibility/test_accessibility_controller_client.h"
#include "ash/public/cpp/ash_switches.h"
#include "ash/public/cpp/config.h"
#include "ash/session/session_controller.h"
......@@ -14,6 +16,7 @@
#include "ash/shutdown_controller.h"
#include "ash/shutdown_reason.h"
#include "ash/system/power/power_button_controller.h"
#include "ash/system/power/power_button_controller_test_api.h"
#include "ash/system/power/power_button_test_base.h"
#include "ash/touch/touch_devices_controller.h"
#include "ash/wm/lock_state_controller_test_api.h"
......@@ -80,6 +83,9 @@ class LockStateControllerTest : public PowerButtonTestBase {
test_animator_ = new TestSessionStateAnimator;
lock_state_controller_->set_animator_for_test(test_animator_);
lock_state_test_api_->set_shutdown_controller(&test_shutdown_controller_);
a11y_controller_ = Shell::Get()->accessibility_controller();
a11y_controller_->SetClient(a11y_client_.CreateInterfacePtrAndBind());
}
protected:
......@@ -212,6 +218,22 @@ class LockStateControllerTest : public PowerButtonTestBase {
SessionStateAnimator::ANIMATION_GRAYSCALE_BRIGHTNESS));
}
void ExpectShutdownAnimationFinished() {
SCOPED_TRACE("Failure in ExpectShutdownAnimationFinished");
EXPECT_EQ(0u, test_animator_->GetAnimationCount());
EXPECT_FALSE(test_animator_->AreContainersAnimated(
SessionStateAnimator::ROOT_CONTAINER,
SessionStateAnimator::ANIMATION_GRAYSCALE_BRIGHTNESS));
}
void ExpectShutdownAnimationCancel() {
SCOPED_TRACE("Failure in ExpectShutdownAnimationCancel");
EXPECT_LT(0u, test_animator_->GetAnimationCount());
EXPECT_TRUE(test_animator_->AreContainersAnimated(
SessionStateAnimator::ROOT_CONTAINER,
SessionStateAnimator::ANIMATION_UNDO_GRAYSCALE_BRIGHTNESS));
}
void ExpectWallpaperIsShowing() {
SCOPED_TRACE("Failure in ExpectWallpaperIsShowing");
EXPECT_LT(0u, test_animator_->GetAnimationCount());
......@@ -263,8 +285,13 @@ class LockStateControllerTest : public PowerButtonTestBase {
lock_state_controller_->OnLockScreenHide(closure);
}
// Simulate that shutdown sound duration callback is done.
void ShutdownSoundPlayed() { a11y_controller_->FlushMojoForTest(); }
TestShutdownController test_shutdown_controller_;
TestSessionStateAnimator* test_animator_ = nullptr; // not owned
AccessibilityController* a11y_controller_ = nullptr; // not owned
TestAccessibilityControllerClient a11y_client_;
private:
DISALLOW_COPY_AND_ASSIGN(LockStateControllerTest);
......@@ -679,4 +706,42 @@ TEST_F(LockStateControllerTest, TouchscreenUnableWhileScreenOff) {
TouchDeviceEnabledSource::GLOBAL));
}
// Tests that continue pressing the power button for a while after power menu is
// shown should trigger the cancellable pre-shutdown animation.
TEST_F(LockStateControllerTest, ShutDownAfterShowPowerMenu) {
Initialize(ButtonType::NORMAL, LoginStatus::USER);
PressPowerButton();
EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
ASSERT_TRUE(power_button_test_api_->TriggerPreShutdownTimeout());
EXPECT_TRUE(lock_state_test_api_->shutdown_timer_is_running());
ExpectShutdownAnimationStarted();
AdvancePartially(SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN, 0.5f);
// Release the power button before the shutdown timer fires.
ReleasePowerButton();
EXPECT_FALSE(lock_state_test_api_->shutdown_timer_is_running());
ExpectShutdownAnimationCancel();
power_button_controller_->DismissMenu();
EXPECT_FALSE(power_button_test_api_->IsMenuOpened());
// Press the button again and make the shutdown timeout fire this time.
// Check that we start the timer for actually requesting the shutdown.
PressPowerButton();
ASSERT_TRUE(power_button_test_api_->TriggerPreShutdownTimeout());
EXPECT_TRUE(lock_state_test_api_->shutdown_timer_is_running());
Advance(SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN);
ExpectShutdownAnimationFinished();
lock_state_test_api_->trigger_shutdown_timeout();
ShutdownSoundPlayed();
EXPECT_TRUE(lock_state_test_api_->real_shutdown_timer_is_running());
EXPECT_EQ(0, NumShutdownRequests());
// When the timeout fires, we should request a shutdown.
lock_state_test_api_->trigger_real_shutdown_timeout();
EXPECT_EQ(1, NumShutdownRequests());
}
} // namespace ash
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment