Commit 4bcbeb30 authored by pkotwicz's avatar pkotwicz Committed by Commit bot

[Athena] Make a quick power button tap suspend the device

BUG=404661, 179713
TEST=Manual, see bug
R=flackr, oshima, derat
TBR=stevenjb

Review URL: https://codereview.chromium.org/585623003

Cr-Commit-Position: refs/heads/master@{#296515}
parent 74cafd39
......@@ -14,14 +14,6 @@ namespace aura {
class Window;
}
namespace ui {
class LayerAnimator;
}
namespace wm {
class FocusRules;
}
namespace athena {
class ScreenManagerDelegate;
......@@ -68,10 +60,6 @@ class ATHENA_EXPORT ScreenManager {
// instead: http://crbug.com/401044.
virtual void SetRotation(gfx::Display::Rotation rotation) = 0;
virtual void SetRotationLocked(bool rotation_locked) = 0;
// Returns the LayerAnimator to use to animate the entire screen (e.g. fade
// screen to white).
virtual ui::LayerAnimator* GetScreenAnimator() = 0;
};
} // namespace athena
......
......@@ -206,7 +206,6 @@ class ScreenManagerImpl : public ScreenManager {
virtual aura::Window* GetContext() OVERRIDE { return root_window_; }
virtual void SetRotation(gfx::Display::Rotation rotation) OVERRIDE;
virtual void SetRotationLocked(bool rotation_locked) OVERRIDE;
virtual ui::LayerAnimator* GetScreenAnimator() OVERRIDE;
// Not owned.
aura::Window* root_window_;
......@@ -362,10 +361,6 @@ void ScreenManagerImpl::SetRotationLocked(bool rotation_locked) {
SetRotation(last_requested_rotation_);
}
ui::LayerAnimator* ScreenManagerImpl::GetScreenAnimator() {
return root_window_->layer()->GetAnimator();
}
} // namespace
ScreenManager::ContainerParams::ContainerParams(const std::string& n,
......
......@@ -5,23 +5,31 @@
#include "athena/system/power_button_controller.h"
#include "athena/screen/public/screen_manager.h"
#include "base/strings/utf_string_conversions.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "ui/compositor/layer_animator.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/font_list.h"
#include "ui/views/background.h"
#include "ui/views/border.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/widget/widget.h"
namespace athena {
namespace {
// Duration of the shutdown animation.
const int kShutdownDurationMs = 1000;
// The amount of time that the power button must be held to show the shutdown
// warning dialog.
const int kShowShutdownWarningTimeoutMs = 1000;
// Duration of the cancel shutdown animation.
const int kCancelShutdownDurationMs = 500;
// The amount of time that the power button must be held to shut down the
// device.
const int kShutdownTimeoutMs = 5000;
} // namespace
PowerButtonController::PowerButtonController()
: brightness_is_zero_(false),
PowerButtonController::PowerButtonController(aura::Window* dialog_container)
: warning_message_container_(dialog_container),
brightness_is_zero_(false),
state_(STATE_OTHER) {
chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->AddObserver(
this);
......@@ -32,21 +40,48 @@ PowerButtonController::~PowerButtonController() {
this);
}
void PowerButtonController::StartGrayscaleAndBrightnessAnimation(
float target,
int duration_ms,
gfx::Tween::Type tween_type) {
ui::LayerAnimator* animator = ScreenManager::Get()->GetScreenAnimator();
ui::ScopedLayerAnimationSettings settings(animator);
settings.SetTransitionDuration(
base::TimeDelta::FromMilliseconds(duration_ms));
settings.SetTweenType(tween_type);
settings.SetPreemptionStrategy(
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
settings.AddObserver(this);
animator->SetBrightness(target);
animator->SetGrayscale(target);
void PowerButtonController::ShowShutdownWarningDialog() {
state_ = STATE_SHUTDOWN_WARNING_VISIBLE;
shutdown_warning_message_.reset(new views::Widget);
views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
params.parent = warning_message_container_;
shutdown_warning_message_->Init(params);
// TODO(pkotwicz): Get text from the resource.
views::Label* label = new views::Label(
base::UTF8ToUTF16("Keep holding power button to shutdown."));
label->SetBackgroundColor(SK_ColorWHITE);
label->SetFontList(gfx::FontList().DeriveWithStyle(gfx::Font::BOLD));
views::View* container = new views::View;
container->AddChildView(label);
const int kBorderSpacing = 50;
container->SetLayoutManager(new views::BoxLayout(
views::BoxLayout::kHorizontal, kBorderSpacing, kBorderSpacing, 0));
container->set_background(
views::Background::CreateSolidBackground(SK_ColorWHITE));
container->SetBorder(views::Border::CreateSolidBorder(1, SK_ColorBLACK));
shutdown_warning_message_->SetContentsView(container);
shutdown_warning_message_->CenterWindow(container->GetPreferredSize());
shutdown_warning_message_->Show();
timer_.Start(FROM_HERE,
base::TimeDelta::FromMilliseconds(kShutdownTimeoutMs -
kShowShutdownWarningTimeoutMs),
this,
&PowerButtonController::Shutdown);
}
void PowerButtonController::Shutdown() {
state_ = STATE_SHUTDOWN_REQUESTED;
chromeos::DBusThreadManager::Get()
->GetPowerManagerClient()
->RequestShutdown();
}
void PowerButtonController::BrightnessChanged(int level, bool user_initiated) {
......@@ -58,35 +93,33 @@ void PowerButtonController::BrightnessChanged(int level, bool user_initiated) {
void PowerButtonController::PowerButtonEventReceived(
bool down,
const base::TimeTicks& timestamp) {
// Avoid requesting a shutdown if the power button is pressed while the screen
// is off (http://crbug.com/128451)
if (state_ == STATE_SHUTDOWN_REQUESTED)
return;
// Avoid requesting suspend or shutdown if the power button is pressed while
// the screen is off (http://crbug.com/128451).
base::TimeDelta time_since_zero_brightness = brightness_is_zero_ ?
base::TimeDelta() : (base::TimeTicks::Now() - zero_brightness_end_time_);
const int kShortTimeMs = 10;
if (time_since_zero_brightness.InMilliseconds() <= kShortTimeMs)
return;
if (state_ == STATE_SHUTDOWN_REQUESTED)
return;
StopObservingImplicitAnimations();
if (down) {
state_ = STATE_PRE_SHUTDOWN_ANIMATION;
StartGrayscaleAndBrightnessAnimation(
1.0f, kShutdownDurationMs, gfx::Tween::EASE_IN);
state_ = STATE_SUSPEND_ON_RELEASE;
timer_.Start(
FROM_HERE,
base::TimeDelta::FromMilliseconds(kShowShutdownWarningTimeoutMs),
this,
&PowerButtonController::ShowShutdownWarningDialog);
} else {
state_ = STATE_OTHER;
StartGrayscaleAndBrightnessAnimation(
0.0f, kCancelShutdownDurationMs, gfx::Tween::EASE_IN_OUT);
}
}
void PowerButtonController::OnImplicitAnimationsCompleted() {
if (state_ == STATE_PRE_SHUTDOWN_ANIMATION) {
state_ = STATE_SHUTDOWN_REQUESTED;
if (state_ == STATE_SUSPEND_ON_RELEASE) {
chromeos::DBusThreadManager::Get()
->GetPowerManagerClient()
->RequestShutdown();
->RequestSuspend();
}
state_ = STATE_OTHER;
timer_.Stop();
shutdown_warning_message_.reset();
}
}
......
......@@ -5,24 +5,35 @@
#ifndef ATHENA_SYSTEM_POWER_BUTTON_CONTROLLER_H_
#define ATHENA_SYSTEM_POWER_BUTTON_CONTROLLER_H_
#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "chromeos/dbus/power_manager_client.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/gfx/animation/tween.h"
namespace aura {
class Window;
}
namespace views {
class Widget;
}
namespace athena {
// Shuts down in response to the power button being pressed.
class PowerButtonController : public chromeos::PowerManagerClient::Observer,
public ui::ImplicitAnimationObserver {
class PowerButtonController : public chromeos::PowerManagerClient::Observer {
public:
PowerButtonController();
explicit PowerButtonController(aura::Window* dialog_container);
virtual ~PowerButtonController();
private:
enum State {
// The screen is animating prior to shutdown. Shutdown can be canceled.
STATE_PRE_SHUTDOWN_ANIMATION,
// Releasing the power button sends a suspend request.
STATE_SUSPEND_ON_RELEASE,
// A warning that the device is about to be shutdown is visible. Releasing
// the power button does not send a suspend or a shutdown request.
STATE_SHUTDOWN_WARNING_VISIBLE,
// A D-Bus shutdown request has been sent. Shutdown cannot be canceled.
STATE_SHUTDOWN_REQUESTED,
......@@ -30,10 +41,11 @@ class PowerButtonController : public chromeos::PowerManagerClient::Observer,
STATE_OTHER
};
// Animates the screen's grayscale and brightness to |target|.
void StartGrayscaleAndBrightnessAnimation(float target,
int duration_ms,
gfx::Tween::Type tween_type);
// Shows the shutdown warning dialog.
void ShowShutdownWarningDialog();
// Requests shutdown.
void Shutdown();
// chromeos::PowerManagerClient::Observer:
virtual void BrightnessChanged(int level, bool user_initiated) OVERRIDE;
......@@ -41,8 +53,11 @@ class PowerButtonController : public chromeos::PowerManagerClient::Observer,
bool down,
const base::TimeTicks& timestamp) OVERRIDE;
// ui::ImplicitAnimationObserver:
virtual void OnImplicitAnimationsCompleted() OVERRIDE;
// |shutdown_warning_message_|'s parent container.
aura::Window* warning_message_container_;
// Shows a warning that the device is about to be shutdown.
scoped_ptr<views::Widget> shutdown_warning_message_;
// Whether the screen brightness was reduced to 0%.
bool brightness_is_zero_;
......@@ -52,6 +67,8 @@ class PowerButtonController : public chromeos::PowerManagerClient::Observer,
State state_;
base::OneShotTimer<PowerButtonController> timer_;
DISALLOW_COPY_AND_ASSIGN(PowerButtonController);
};
......
......@@ -76,7 +76,6 @@ class SystemUIImpl : public SystemUI {
public:
SystemUIImpl(scoped_refptr<base::TaskRunner> blocking_task_runner)
: orientation_controller_(new OrientationController()),
power_button_controller_(new PowerButtonController),
background_container_(NULL),
system_modal_container_(NULL) {
orientation_controller_->InitWith(blocking_task_runner);
......@@ -89,7 +88,8 @@ class SystemUIImpl : public SystemUI {
}
void Init() {
background_container_ = ScreenManager::Get()->CreateContainer(
ScreenManager* screen_manager = ScreenManager::Get();
background_container_ = screen_manager->CreateContainer(
ScreenManager::ContainerParams("AthenaBackground", CP_BACKGROUND));
background_container_->SetLayoutManager(
new FillLayoutManager(background_container_));
......@@ -97,8 +97,17 @@ class SystemUIImpl : public SystemUI {
"AthenaSystemModalContainer", CP_SYSTEM_MODAL);
system_modal_params.can_activate_children = true;
system_modal_container_ =
ScreenManager::Get()->CreateContainer(system_modal_params);
screen_manager->CreateContainer(system_modal_params);
login_screen_system_modal_container_ = screen_manager->CreateContainer(
ScreenManager::ContainerParams("AthenaLoginScreenSystemModalContainer",
CP_LOGIN_SCREEN_SYSTEM_MODAL));
// Use |login_screen_system_modal_container_| for the power button's dialog
// because it needs to show over the login screen.
// TODO(pkotwicz): Pick the most appropriate container based on whether the
// user has logged in.
power_button_controller_.reset(
new PowerButtonController(login_screen_system_modal_container_));
background_controller_.reset(
new BackgroundController(background_container_));
}
......@@ -119,9 +128,13 @@ class SystemUIImpl : public SystemUI {
// The parent container for the background.
aura::Window* background_container_;
// The parent container used by the "select network" dialog.
// The parent container used by system modal dialogs.
aura::Window* system_modal_container_;
// The parent container used by system modal dialogs when the login screen is
// visible.
aura::Window* login_screen_system_modal_container_;
DISALLOW_COPY_AND_ASSIGN(SystemUIImpl);
};
......
......@@ -13,6 +13,7 @@ enum ContainerPriorities {
CP_HOME_CARD,
CP_SYSTEM_MODAL,
CP_LOGIN_SCREEN,
CP_LOGIN_SCREEN_SYSTEM_MODAL,
CP_VIRTUAL_KEYBOARD,
};
......
......@@ -61,6 +61,9 @@ void FakePowerManagerClient::IncreaseKeyboardBrightness() {
void FakePowerManagerClient::RequestStatusUpdate() {
}
void FakePowerManagerClient::RequestSuspend() {
}
void FakePowerManagerClient::RequestRestart() {
++num_request_restart_calls_;
}
......
......@@ -47,6 +47,7 @@ class FakePowerManagerClient : public PowerManagerClient {
virtual void DecreaseKeyboardBrightness() OVERRIDE;
virtual void IncreaseKeyboardBrightness() OVERRIDE;
virtual void RequestStatusUpdate() OVERRIDE;
virtual void RequestSuspend() OVERRIDE;
virtual void RequestRestart() OVERRIDE;
virtual void RequestShutdown() OVERRIDE;
virtual void NotifyUserActivity(
......
......@@ -148,9 +148,13 @@ class PowerManagerClientImpl : public PowerManagerClient {
weak_ptr_factory_.GetWeakPtr()));
}
virtual void RequestSuspend() OVERRIDE {
SimpleMethodCallToPowerManager(power_manager::kRequestSuspendMethod);
}
virtual void RequestRestart() OVERRIDE {
SimpleMethodCallToPowerManager(power_manager::kRequestRestartMethod);
};
}
virtual void RequestShutdown() OVERRIDE {
SimpleMethodCallToPowerManager(power_manager::kRequestShutdownMethod);
......@@ -805,6 +809,7 @@ class PowerManagerClientStubImpl : public PowerManagerClient {
weak_ptr_factory_.GetWeakPtr()));
}
virtual void RequestSuspend() OVERRIDE {}
virtual void RequestRestart() OVERRIDE {}
virtual void RequestShutdown() OVERRIDE {}
......
......@@ -128,6 +128,9 @@ class CHROMEOS_EXPORT PowerManagerClient : public DBusClient {
// will be called asynchronously.
virtual void RequestStatusUpdate() = 0;
// Requests suspend of the system.
virtual void RequestSuspend() = 0;
// Requests restart of the system.
virtual void RequestRestart() = 0;
......
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