Commit 29736b94 authored by Xiaohui Chen's avatar Xiaohui Chen Committed by Commit Bot

ambient: handle suspend case better

Previously ambient mode will trigger lockscreen on screen dimm and then
rely on lock screen idle to show screen saver. This works in some cases,
but in suspend case the time between screen dim and cpu suspend is too
short. Screen saver was not able to enguage. The reason we have the set
up is because the screen saver was sharing the same window constainer as
the lock screen, it cannot show before lock screen is ready.

Now screen saver has its own window container, we changed the flow to
show ambient mode immediately when idle. This will prevent cpu suspend
because screen saver will take a wake lock if charging. Screen saver
will still lock the screen in the back if user reference indicated
lockscreen after wake.

Bug: b:169442907
Test: unitests and manual tests
Change-Id: I1a5df2c58c976bba492c709e0a61dd5a6314d084
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2435334Reviewed-by: default avatarTao Wu <wutao@chromium.org>
Commit-Queue: Xiaohui Chen <xiaohuic@chromium.org>
Cr-Commit-Position: refs/heads/master@{#812397}
parent 97f51122
...@@ -28,6 +28,9 @@ constexpr base::TimeDelta kPhotoRefreshInterval = ...@@ -28,6 +28,9 @@ constexpr base::TimeDelta kPhotoRefreshInterval =
constexpr base::TimeDelta kWeatherRefreshInterval = constexpr base::TimeDelta kWeatherRefreshInterval =
base::TimeDelta::FromMinutes(5); base::TimeDelta::FromMinutes(5);
// The delay between ambient mode starts and enabling lock screen.
constexpr base::TimeDelta kLockScreenDelay = base::TimeDelta::FromSeconds(5);
// The batch size of topics to fetch in one request. // The batch size of topics to fetch in one request.
// Magic number 2 is based on experiments that no curation on Google Photos. // Magic number 2 is based on experiments that no curation on Google Photos.
constexpr int kTopicsBatchSize = 2; constexpr int kTopicsBatchSize = 2;
......
...@@ -96,10 +96,6 @@ bool IsUiHidden(AmbientUiVisibility visibility) { ...@@ -96,10 +96,6 @@ bool IsUiHidden(AmbientUiVisibility visibility) {
return visibility == AmbientUiVisibility::kHidden; return visibility == AmbientUiVisibility::kHidden;
} }
bool IsLockScreenUi(AmbientUiMode mode) {
return mode == AmbientUiMode::kLockScreenUi;
}
bool IsAmbientModeEnabled() { bool IsAmbientModeEnabled() {
if (!AmbientClient::Get()->IsAmbientModeAllowed()) if (!AmbientClient::Get()->IsAmbientModeAllowed())
return false; return false;
...@@ -204,7 +200,8 @@ void AmbientController::OnAmbientUiVisibilityChanged( ...@@ -204,7 +200,8 @@ void AmbientController::OnAmbientUiVisibilityChanged(
// Record metrics on ambient mode usage. // Record metrics on ambient mode usage.
ambient::RecordAmbientModeActivation( ambient::RecordAmbientModeActivation(
/*ui_mode=*/ambient_ui_model_.ui_mode(), /*ui_mode=*/LockScreen::HasInstance() ? AmbientUiMode::kLockScreenUi
: AmbientUiMode::kInSessionUi,
/*tablet_mode=*/Shell::Get()->IsInTabletMode()); /*tablet_mode=*/Shell::Get()->IsInTabletMode());
DCHECK(!start_time_); DCHECK(!start_time_);
...@@ -319,7 +316,11 @@ void AmbientController::OnLockStateChanged(bool locked) { ...@@ -319,7 +316,11 @@ void AmbientController::OnLockStateChanged(bool locked) {
// wait. // wait.
RequestAccessToken(base::DoNothing(), /*may_refresh_token_on_lock=*/true); RequestAccessToken(base::DoNothing(), /*may_refresh_token_on_lock=*/true);
ShowUi(AmbientUiMode::kLockScreenUi); if (!IsShown()) {
// When lock screen starts, we don't immediately show the UI. The Ui is
// hidden and will show after a delay.
ShowHiddenUi();
}
} else { } else {
// Ambient screen will be destroyed along with the lock screen when user // Ambient screen will be destroyed along with the lock screen when user
// logs in. // logs in.
...@@ -374,7 +375,7 @@ void AmbientController::ScreenBrightnessChanged( ...@@ -374,7 +375,7 @@ void AmbientController::ScreenBrightnessChanged(
is_screen_off_ = false; is_screen_off_ = false;
// If screen is back on, turn on ambient mode for lock screen. // If screen is back on, turn on ambient mode for lock screen.
if (LockScreen::HasInstance()) if (LockScreen::HasInstance())
ShowUi(AmbientUiMode::kLockScreenUi); ShowHiddenUi();
} }
void AmbientController::ScreenIdleStateChanged( void AmbientController::ScreenIdleStateChanged(
...@@ -392,16 +393,7 @@ void AmbientController::ScreenIdleStateChanged( ...@@ -392,16 +393,7 @@ void AmbientController::ScreenIdleStateChanged(
if (!idle_state.dimmed()) if (!idle_state.dimmed())
return; return;
auto* session_controller = Shell::Get()->session_controller(); ShowUi();
if (session_controller->CanLockScreen() &&
session_controller->ShouldLockScreenAutomatically()) {
if (!session_controller->IsScreenLocked()) {
// TODO(b/161469136): revise this behavior after further discussion.
Shell::Get()->session_controller()->LockScreen();
}
} else {
ShowUi(AmbientUiMode::kInSessionUi);
}
} }
void AmbientController::AddAmbientViewDelegateObserver( void AmbientController::AddAmbientViewDelegateObserver(
...@@ -414,8 +406,8 @@ void AmbientController::RemoveAmbientViewDelegateObserver( ...@@ -414,8 +406,8 @@ void AmbientController::RemoveAmbientViewDelegateObserver(
delegate_.RemoveObserver(observer); delegate_.RemoveObserver(observer);
} }
void AmbientController::ShowUi(AmbientUiMode mode) { void AmbientController::ShowUi() {
DVLOG(1) << "ShowUi: " << mode; DVLOG(1) << __func__;
// TODO(meilinw): move the eligibility check to the idle entry point once // TODO(meilinw): move the eligibility check to the idle entry point once
// implemented: b/149246117. // implemented: b/149246117.
...@@ -424,30 +416,24 @@ void AmbientController::ShowUi(AmbientUiMode mode) { ...@@ -424,30 +416,24 @@ void AmbientController::ShowUi(AmbientUiMode mode) {
return; return;
} }
ambient_ui_model_.SetUiMode(mode); ambient_ui_model_.SetUiVisibility(AmbientUiVisibility::kShown);
switch (mode) {
case AmbientUiMode::kInSessionUi:
ambient_ui_model_.SetUiVisibility(AmbientUiVisibility::kShown);
break;
case AmbientUiMode::kLockScreenUi:
ambient_ui_model_.SetUiVisibility(AmbientUiVisibility::kHidden);
break;
}
} }
void AmbientController::CloseUi() { void AmbientController::ShowHiddenUi() {
ambient_ui_model_.SetUiVisibility(AmbientUiVisibility::kClosed); DVLOG(1) << __func__;
ambient_ui_model_.SetUiVisibility(AmbientUiVisibility::kHidden);
} }
void AmbientController::HideLockScreenUi() { void AmbientController::CloseUi() {
DCHECK(IsLockScreenUi(ambient_ui_model_.ui_mode())); DVLOG(1) << __func__;
ambient_ui_model_.SetUiVisibility(AmbientUiVisibility::kHidden); ambient_ui_model_.SetUiVisibility(AmbientUiVisibility::kClosed);
} }
void AmbientController::ToggleInSessionUi() { void AmbientController::ToggleInSessionUi() {
if (!container_view_) if (ambient_ui_model_.ui_visibility() == AmbientUiVisibility::kClosed)
ShowUi(AmbientUiMode::kInSessionUi); ShowUi();
else else
CloseUi(); CloseUi();
} }
...@@ -458,16 +444,12 @@ bool AmbientController::IsShown() const { ...@@ -458,16 +444,12 @@ bool AmbientController::IsShown() const {
void AmbientController::OnBackgroundPhotoEvents() { void AmbientController::OnBackgroundPhotoEvents() {
// Dismisses the ambient screen when user interacts with the background photo. // Dismisses the ambient screen when user interacts with the background photo.
if (IsLockScreenUi(ambient_ui_model_.ui_mode())) if (LockScreen::HasInstance())
HideLockScreenUi(); ShowHiddenUi();
else else
CloseUi(); CloseUi();
} }
void AmbientController::UpdateUiMode(AmbientUiMode ui_mode) {
ambient_ui_model_.SetUiMode(ui_mode);
}
void AmbientController::AcquireWakeLock() { void AmbientController::AcquireWakeLock() {
if (!wake_lock_) { if (!wake_lock_) {
mojo::Remote<device::mojom::WakeLockProvider> provider; mojo::Remote<device::mojom::WakeLockProvider> provider;
...@@ -482,6 +464,17 @@ void AmbientController::AcquireWakeLock() { ...@@ -482,6 +464,17 @@ void AmbientController::AcquireWakeLock() {
DCHECK(wake_lock_); DCHECK(wake_lock_);
wake_lock_->RequestWakeLock(); wake_lock_->RequestWakeLock();
VLOG(1) << "Acquired wake lock"; VLOG(1) << "Acquired wake lock";
auto* session_controller = Shell::Get()->session_controller();
if (session_controller->CanLockScreen() &&
session_controller->ShouldLockScreenAutomatically()) {
if (!session_controller->IsScreenLocked()) {
delayed_lock_timer_.Start(
FROM_HERE, kLockScreenDelay, base::BindOnce([]() {
Shell::Get()->session_controller()->LockScreen();
}));
}
}
} }
void AmbientController::ReleaseWakeLock() { void AmbientController::ReleaseWakeLock() {
...@@ -490,6 +483,8 @@ void AmbientController::ReleaseWakeLock() { ...@@ -490,6 +483,8 @@ void AmbientController::ReleaseWakeLock() {
wake_lock_->CancelWakeLock(); wake_lock_->CancelWakeLock();
VLOG(1) << "Released wake lock"; VLOG(1) << "Released wake lock";
delayed_lock_timer_.Stop();
} }
void AmbientController::CloseWidget(bool immediately) { void AmbientController::CloseWidget(bool immediately) {
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/scoped_observer.h" #include "base/scoped_observer.h"
#include "base/timer/timer.h"
#include "chromeos/dbus/power/power_manager_client.h" #include "chromeos/dbus/power/power_manager_client.h"
#include "components/prefs/pref_change_registrar.h" #include "components/prefs/pref_change_registrar.h"
#include "components/prefs/pref_service.h" #include "components/prefs/pref_service.h"
...@@ -74,12 +75,12 @@ class ASH_EXPORT AmbientController ...@@ -74,12 +75,12 @@ class ASH_EXPORT AmbientController
void AddAmbientViewDelegateObserver(AmbientViewDelegateObserver* observer); void AddAmbientViewDelegateObserver(AmbientViewDelegateObserver* observer);
void RemoveAmbientViewDelegateObserver(AmbientViewDelegateObserver* observer); void RemoveAmbientViewDelegateObserver(AmbientViewDelegateObserver* observer);
// Invoked to show/close ambient UI in |mode|. void ShowUi();
void ShowUi(AmbientUiMode mode); // Ui will be enabled but not shown immediately. If there is no user activity
// Ui will be shown after a short delay.
void ShowHiddenUi();
void CloseUi(); void CloseUi();
void HideLockScreenUi();
void ToggleInSessionUi(); void ToggleInSessionUi();
// Returns true if the |container_view_| is currently visible. // Returns true if the |container_view_| is currently visible.
...@@ -88,8 +89,6 @@ class ASH_EXPORT AmbientController ...@@ -88,8 +89,6 @@ class ASH_EXPORT AmbientController
// Handles events on the background photo. // Handles events on the background photo.
void OnBackgroundPhotoEvents(); void OnBackgroundPhotoEvents();
void UpdateUiMode(AmbientUiMode ui_mode);
void RequestAccessToken( void RequestAccessToken(
AmbientAccessTokenController::AccessTokenCallback callback, AmbientAccessTokenController::AccessTokenCallback callback,
bool may_refresh_token_on_lock = false); bool may_refresh_token_on_lock = false);
...@@ -190,6 +189,8 @@ class ASH_EXPORT AmbientController ...@@ -190,6 +189,8 @@ class ASH_EXPORT AmbientController
// Used to record Ambient mode engagement metrics. // Used to record Ambient mode engagement metrics.
base::Optional<base::Time> start_time_ = base::nullopt; base::Optional<base::Time> start_time_ = base::nullopt;
base::OneShotTimer delayed_lock_timer_;
base::WeakPtrFactory<AmbientController> weak_ptr_factory_{this}; base::WeakPtrFactory<AmbientController> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(AmbientController); DISALLOW_COPY_AND_ASSIGN(AmbientController);
}; };
......
This diff is collapsed.
...@@ -35,6 +35,9 @@ ...@@ -35,6 +35,9 @@
#include "ui/views/controls/label.h" #include "ui/views/controls/label.h"
namespace ash { namespace ash {
namespace {
constexpr float kFastForwardFactor = 1.0001;
} // namespace
class TestAmbientURLLoaderImpl : public AmbientURLLoader { class TestAmbientURLLoaderImpl : public AmbientURLLoader {
public: public:
...@@ -141,7 +144,7 @@ void AmbientAshTestBase::SetAmbientModeEnabled(bool enabled) { ...@@ -141,7 +144,7 @@ void AmbientAshTestBase::SetAmbientModeEnabled(bool enabled) {
void AmbientAshTestBase::ShowAmbientScreen() { void AmbientAshTestBase::ShowAmbientScreen() {
// The widget will be destroyed in |AshTestBase::TearDown()|. // The widget will be destroyed in |AshTestBase::TearDown()|.
ambient_controller()->ShowUi(AmbientUiMode::kInSessionUi); ambient_controller()->ShowUi();
// The UI only shows when images are downloaded to avoid showing blank screen. // The UI only shows when images are downloaded to avoid showing blank screen.
FastForwardToNextImage(); FastForwardToNextImage();
// Flush the message loop to finish all async calls. // Flush the message loop to finish all async calls.
...@@ -149,12 +152,11 @@ void AmbientAshTestBase::ShowAmbientScreen() { ...@@ -149,12 +152,11 @@ void AmbientAshTestBase::ShowAmbientScreen() {
} }
void AmbientAshTestBase::HideAmbientScreen() { void AmbientAshTestBase::HideAmbientScreen() {
ambient_controller()->HideLockScreenUi(); ambient_controller()->ShowHiddenUi();
} }
void AmbientAshTestBase::CloseAmbientScreen() { void AmbientAshTestBase::CloseAmbientScreen() {
ambient_controller()->ambient_ui_model()->SetUiVisibility( ambient_controller()->CloseUi();
AmbientUiVisibility::kClosed);
} }
void AmbientAshTestBase::LockScreen() { void AmbientAshTestBase::LockScreen() {
...@@ -242,11 +244,51 @@ MediaStringView* AmbientAshTestBase::GetMediaStringView() { ...@@ -242,11 +244,51 @@ MediaStringView* AmbientAshTestBase::GetMediaStringView() {
void AmbientAshTestBase::FastForwardToInactivity() { void AmbientAshTestBase::FastForwardToInactivity() {
task_environment()->FastForwardBy( task_environment()->FastForwardBy(
2 * AmbientController::kAutoShowWaitTimeInterval); kFastForwardFactor * AmbientController::kAutoShowWaitTimeInterval);
} }
void AmbientAshTestBase::FastForwardToNextImage() { void AmbientAshTestBase::FastForwardToNextImage() {
task_environment()->FastForwardBy(1.2 * kPhotoRefreshInterval); task_environment()->FastForwardBy(kFastForwardFactor * kPhotoRefreshInterval);
}
void AmbientAshTestBase::FastForwardTiny() {
// `TestAmbientURLLoaderImpl` has a small delay (1ms) to fake download delay,
// here we fake plenty of time to download the image.
task_environment()->FastForwardBy(base::TimeDelta::FromMilliseconds(10));
}
void AmbientAshTestBase::FastForwardToLockScreen() {
task_environment()->FastForwardBy(kFastForwardFactor * kLockScreenDelay);
}
void AmbientAshTestBase::SetPowerStateCharging() {
power_manager::PowerSupplyProperties proto;
proto.set_battery_state(
power_manager::PowerSupplyProperties_BatteryState_CHARGING);
proto.set_external_power(
power_manager::PowerSupplyProperties_ExternalPower_AC);
PowerStatus::Get()->SetProtoForTesting(proto);
ambient_controller()->OnPowerStatusChanged();
}
void AmbientAshTestBase::SetPowerStateDischarging() {
power_manager::PowerSupplyProperties proto;
proto.set_battery_state(
power_manager::PowerSupplyProperties_BatteryState_DISCHARGING);
proto.set_external_power(
power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED);
PowerStatus::Get()->SetProtoForTesting(proto);
ambient_controller()->OnPowerStatusChanged();
}
void AmbientAshTestBase::SetPowerStateFull() {
power_manager::PowerSupplyProperties proto;
proto.set_battery_state(
power_manager::PowerSupplyProperties_BatteryState_FULL);
proto.set_external_power(
power_manager::PowerSupplyProperties_ExternalPower_AC);
PowerStatus::Get()->SetProtoForTesting(proto);
ambient_controller()->OnPowerStatusChanged();
} }
void AmbientAshTestBase::FastForwardToRefreshWeather() { void AmbientAshTestBase::FastForwardToRefreshWeather() {
......
...@@ -96,9 +96,20 @@ class AmbientAshTestBase : public AshTestBase { ...@@ -96,9 +96,20 @@ class AmbientAshTestBase : public AshTestBase {
// Advance the task environment timer to load the next photo. // Advance the task environment timer to load the next photo.
void FastForwardToNextImage(); void FastForwardToNextImage();
// Advance the task environment timer a tiny amount. This is intended to
// trigger any pending async operations.
void FastForwardTiny();
// Advance the task environment timer to load the weather info. // Advance the task environment timer to load the weather info.
void FastForwardToRefreshWeather(); void FastForwardToRefreshWeather();
// Advance the task environment timer to ambient mode lock screen delay.
void FastForwardToLockScreen();
void SetPowerStateCharging();
void SetPowerStateDischarging();
void SetPowerStateFull();
// Returns the number of active wake locks of type |type|. // Returns the number of active wake locks of type |type|.
int GetNumOfActiveWakeLocks(device::mojom::WakeLockType type); int GetNumOfActiveWakeLocks(device::mojom::WakeLockType type);
......
...@@ -360,6 +360,7 @@ TEST_F(MediaStringViewTest, DoNotShowOnLockScreenIfPrefIsDisabled) { ...@@ -360,6 +360,7 @@ TEST_F(MediaStringViewTest, DoNotShowOnLockScreenIfPrefIsDisabled) {
// Simulates Ambient Mode shown on lock-screen. // Simulates Ambient Mode shown on lock-screen.
LockScreen(); LockScreen();
FastForwardToInactivity(); FastForwardToInactivity();
FastForwardTiny();
// Simulates active and playing media session. // Simulates active and playing media session.
SimulateMediaPlaybackStateChanged( SimulateMediaPlaybackStateChanged(
......
...@@ -44,13 +44,6 @@ void AmbientUiModel::SetUiVisibility(AmbientUiVisibility visibility) { ...@@ -44,13 +44,6 @@ void AmbientUiModel::SetUiVisibility(AmbientUiVisibility visibility) {
NotifyAmbientUiVisibilityChanged(); NotifyAmbientUiVisibilityChanged();
} }
void AmbientUiModel::SetUiMode(AmbientUiMode ui_mode) {
if (ui_mode_ == ui_mode)
return;
ui_mode_ = ui_mode;
}
void AmbientUiModel::NotifyAmbientUiVisibilityChanged() { void AmbientUiModel::NotifyAmbientUiVisibilityChanged() {
for (auto& observer : observers_) for (auto& observer : observers_)
observer.OnAmbientUiVisibilityChanged(ui_visibility_); observer.OnAmbientUiVisibilityChanged(ui_visibility_);
...@@ -68,4 +61,19 @@ std::ostream& operator<<(std::ostream& out, AmbientUiMode mode) { ...@@ -68,4 +61,19 @@ std::ostream& operator<<(std::ostream& out, AmbientUiMode mode) {
return out; return out;
} }
std::ostream& operator<<(std::ostream& out, AmbientUiVisibility visibility) {
switch (visibility) {
case AmbientUiVisibility::kShown:
out << "kShown";
break;
case AmbientUiVisibility::kHidden:
out << "kHidden";
break;
case AmbientUiVisibility::kClosed:
out << "kClosed";
break;
}
return out;
}
} // namespace ash } // namespace ash
...@@ -51,18 +51,12 @@ class ASH_PUBLIC_EXPORT AmbientUiModel { ...@@ -51,18 +51,12 @@ class ASH_PUBLIC_EXPORT AmbientUiModel {
// Updates current UI visibility and notifies all subscribers. // Updates current UI visibility and notifies all subscribers.
void SetUiVisibility(AmbientUiVisibility visibility); void SetUiVisibility(AmbientUiVisibility visibility);
// Updates current UI mode.
void SetUiMode(AmbientUiMode ui_mode);
AmbientUiVisibility ui_visibility() const { return ui_visibility_; } AmbientUiVisibility ui_visibility() const { return ui_visibility_; }
AmbientUiMode ui_mode() const { return ui_mode_; }
private: private:
void NotifyAmbientUiVisibilityChanged(); void NotifyAmbientUiVisibilityChanged();
AmbientUiVisibility ui_visibility_ = AmbientUiVisibility::kClosed; AmbientUiVisibility ui_visibility_ = AmbientUiVisibility::kClosed;
AmbientUiMode ui_mode_ = AmbientUiMode::kLockScreenUi;
base::ObserverList<AmbientUiModelObserver> observers_; base::ObserverList<AmbientUiModelObserver> observers_;
}; };
...@@ -70,6 +64,9 @@ class ASH_PUBLIC_EXPORT AmbientUiModel { ...@@ -70,6 +64,9 @@ class ASH_PUBLIC_EXPORT AmbientUiModel {
ASH_PUBLIC_EXPORT std::ostream& operator<<(std::ostream& out, ASH_PUBLIC_EXPORT std::ostream& operator<<(std::ostream& out,
AmbientUiMode mode); AmbientUiMode mode);
ASH_PUBLIC_EXPORT std::ostream& operator<<(std::ostream& out,
AmbientUiVisibility visibility);
} // namespace ash } // namespace ash
#endif // ASH_PUBLIC_CPP_AMBIENT_AMBIENT_UI_MODEL_H_ #endif // ASH_PUBLIC_CPP_AMBIENT_AMBIENT_UI_MODEL_H_
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