Commit 6354c8f4 authored by Meilin Wang's avatar Meilin Wang Committed by Commit Bot

Keep display awake when ambient shown.

Bug: 159382866
Test: covered by unittests.
Change-Id: I47295da3c1aacd00b649a5175d5f01eccd8c9e66
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2253363
Commit-Queue: Meilin Wang <meilinw@chromium.org>
Reviewed-by: default avatarXiaohui Chen <xiaohuic@chromium.org>
Reviewed-by: default avatarJeroen Dhollander <jeroendh@google.com>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#781404}
parent 2039c961
......@@ -2579,6 +2579,7 @@ static_library("test_support") {
"//components/user_manager:user_manager",
"//components/viz/test:test_support",
"//device/bluetooth",
"//services/device/public/cpp:test_support",
"//services/device/public/mojom",
"//skia",
"//testing/gtest",
......
......@@ -45,6 +45,9 @@ namespace {
constexpr base::TimeDelta kAutoShowWaitTimeInterval =
base::TimeDelta::FromSeconds(15);
// Used by wake lock APIs.
constexpr char kWakeLockReason[] = "AmbientMode";
void CloseAssistantUi() {
DCHECK(AssistantUiController::Get());
AssistantUiController::Get()->CloseUi(
......@@ -163,10 +166,14 @@ void AmbientController::OnAmbientUiVisibilityChanged(
DCHECK(container_view_);
// This will be no-op if the view is already visible.
container_view_->SetVisible(true);
AcquireWakeLock();
StartRefreshingImages();
break;
case AmbientUiVisibility::kHidden:
container_view_->GetWidget()->Hide();
ReleaseWakeLock();
StopRefreshingImages();
// Creates the monitor and starts the auto-show timer upon hidden.
......@@ -298,6 +305,29 @@ void AmbientController::UpdateUiMode(AmbientUiMode ui_mode) {
ambient_ui_model_.SetUiMode(ui_mode);
}
void AmbientController::AcquireWakeLock() {
if (!wake_lock_) {
mojo::Remote<device::mojom::WakeLockProvider> provider;
AmbientClient::Get()->RequestWakeLockProvider(
provider.BindNewPipeAndPassReceiver());
provider->GetWakeLockWithoutContext(
device::mojom::WakeLockType::kPreventDisplaySleep,
device::mojom::WakeLockReason::kOther, kWakeLockReason,
wake_lock_.BindNewPipeAndPassReceiver());
}
DCHECK(wake_lock_);
wake_lock_->RequestWakeLock();
VLOG(1) << "Acquired wake lock";
}
void AmbientController::ReleaseWakeLock() {
DCHECK(wake_lock_);
wake_lock_->CancelWakeLock();
VLOG(1) << "Released wake lock";
}
void AmbientController::RequestAccessToken(
AmbientAccessTokenController::AccessTokenCallback callback) {
access_token_controller_.RequestAccessToken(std::move(callback));
......@@ -327,6 +357,8 @@ void AmbientController::CleanUpOnClosed() {
// Invalidates the view pointer.
container_view_ = nullptr;
inactivity_monitor_.reset();
// Should do nothing if the wake lock has already been released.
ReleaseWakeLock();
}
void AmbientController::StartRefreshingImages() {
......
......@@ -17,6 +17,8 @@
#include "ash/session/session_observer.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/device/public/mojom/wake_lock.mojom.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_observer.h"
......@@ -100,6 +102,13 @@ class ASH_EXPORT AmbientController : public AmbientUiModelObserver,
void set_backend_controller_for_testing(
std::unique_ptr<AmbientBackendController> photo_client);
// Creates (if not created) and acquires |wake_lock_|. Called when ambient
// screen starts to show.
void AcquireWakeLock();
// Release |wake_lock_|. Called when ambient screen is hidden/closed.
void ReleaseWakeLock();
AmbientPhotoController* get_ambient_photo_controller_for_testing() {
return &ambient_photo_controller_;
}
......@@ -121,6 +130,9 @@ class ASH_EXPORT AmbientController : public AmbientUiModelObserver,
// Monitors the device inactivity and controls the auto-show of ambient.
std::unique_ptr<InactivityMonitor> inactivity_monitor_;
// Lazily initialized on the first call of |AcquireWakeLock|.
mojo::Remote<device::mojom::WakeLock> wake_lock_;
base::WeakPtrFactory<AmbientController> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(AmbientController);
};
......
......@@ -121,4 +121,26 @@ TEST_F(AmbientControllerTest, ShouldRefreshAccessTokenAfterFailure) {
EXPECT_TRUE(IsAccessTokenRequestPending());
}
TEST_F(AmbientControllerTest, CheckAcquireAndReleaseWakeLock) {
// Simulates screen lock to show ambient mode, will result in acquiring a wake
// lock.
LockScreen();
// Run loop to ensure the request has reached the wake lock provider.
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(ambient_controller()->IsShown());
EXPECT_EQ(1, GetNumOfActiveWakeLocks(
device::mojom::WakeLockType::kPreventDisplaySleep));
// Simulates user logs in to close ambient mode, will result in releasing the
// wake lock.
UnlockScreen();
// Run loop to ensure the request has reached the wake lock provider.
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(ambient_controller()->IsShown());
EXPECT_EQ(0, GetNumOfActiveWakeLocks(
device::mojom::WakeLockType::kPreventDisplaySleep));
}
} // namespace ash
......@@ -11,6 +11,7 @@
#include "ash/ambient/ui/ambient_container_view.h"
#include "ash/ambient/ui/photo_view.h"
#include "ash/shell.h"
#include "base/run_loop.h"
#include "chromeos/constants/chromeos_features.h"
#include "ui/gfx/image/image_skia.h"
......@@ -25,7 +26,7 @@ void AmbientAshTestBase::SetUp() {
scoped_feature_list_.InitAndEnableFeature(
chromeos::features::kAmbientModeFeature);
image_downloader_ = std::make_unique<TestImageDownloader>();
ambient_client_ = std::make_unique<TestAmbientClient>();
ambient_client_ = std::make_unique<TestAmbientClient>(&wake_lock_provider_);
AshTestBase::SetUp();
......@@ -67,6 +68,21 @@ const gfx::ImageSkia& AmbientAshTestBase::GetImageInPhotoView() {
->GetCurrentImagesForTesting();
}
int AmbientAshTestBase::GetNumOfActiveWakeLocks(
device::mojom::WakeLockType type) {
base::RunLoop run_loop;
int result_count = 0;
wake_lock_provider_.GetActiveWakeLocksForTests(
type, base::BindOnce(
[](base::RunLoop* run_loop, int* result_count, int32_t count) {
*result_count = count;
run_loop->Quit();
},
&run_loop, &result_count));
run_loop.Run();
return result_count;
}
void AmbientAshTestBase::IssueAccessToken(const std::string& token,
bool with_error) {
ambient_client_->IssueAccessToken(token, with_error);
......
......@@ -13,6 +13,7 @@
#include "ash/public/cpp/test/test_image_downloader.h"
#include "ash/test/ash_test_base.h"
#include "base/test/scoped_feature_list.h"
#include "services/device/public/cpp/test/test_wake_lock_provider.h"
#include "ui/views/widget/widget.h"
namespace gfx {
......@@ -48,6 +49,9 @@ class AmbientAshTestBase : public AshTestBase {
const gfx::ImageSkia& GetImageInPhotoView();
// Returns the number of active wake locks of type |type|.
int GetNumOfActiveWakeLocks(device::mojom::WakeLockType type);
// Simulate to issue an |access_token|.
// If |with_error| is true, will return an empty access token.
void IssueAccessToken(const std::string& access_token, bool with_error);
......@@ -64,6 +68,8 @@ class AmbientAshTestBase : public AshTestBase {
private:
base::test::ScopedFeatureList scoped_feature_list_;
std::unique_ptr<TestImageDownloader> image_downloader_;
device::TestWakeLockProvider wake_lock_provider_;
std::unique_ptr<TestAmbientClient> ambient_client_;
std::unique_ptr<views::Widget> widget_;
};
......
......@@ -358,6 +358,7 @@ source_set("test_support") {
deps = [
":cpp",
"//base",
"//services/device/public/cpp:test_support",
"//services/network/public/cpp:cpp",
"//ui/aura",
"//ui/aura:test_support",
......
......@@ -11,6 +11,7 @@
#include "ash/public/cpp/ash_public_export.h"
#include "base/callback_forward.h"
#include "base/memory/scoped_refptr.h"
#include "services/device/public/mojom/wake_lock_provider.mojom.h"
namespace base {
class Time;
......@@ -43,6 +44,11 @@ class ASH_PUBLIC_EXPORT AmbientClient {
virtual scoped_refptr<network::SharedURLLoaderFactory>
GetURLLoaderFactory() = 0;
// Requests a connection to the device service's |WakeLockProvider|
// from the browser.
virtual void RequestWakeLockProvider(
mojo::PendingReceiver<device::mojom::WakeLockProvider> receiver) = 0;
protected:
AmbientClient();
AmbientClient(const AmbientClient&) = delete;
......
......@@ -20,7 +20,9 @@ constexpr base::TimeDelta kDefaultTokenExpirationDelay =
} // namespace
TestAmbientClient::TestAmbientClient() = default;
TestAmbientClient::TestAmbientClient(
device::TestWakeLockProvider* wake_lock_provider)
: wake_lock_provider_(wake_lock_provider) {}
TestAmbientClient::~TestAmbientClient() = default;
......@@ -38,6 +40,11 @@ TestAmbientClient::GetURLLoaderFactory() {
return nullptr;
}
void TestAmbientClient::RequestWakeLockProvider(
mojo::PendingReceiver<device::mojom::WakeLockProvider> receiver) {
wake_lock_provider_->BindReceiver(std::move(receiver));
}
void TestAmbientClient::IssueAccessToken(const std::string& access_token,
bool with_error) {
if (!pending_callback_)
......
......@@ -10,6 +10,7 @@
#include "ash/public/cpp/ambient/ambient_client.h"
#include "ash/public/cpp/ash_public_export.h"
#include "base/callback.h"
#include "services/device/public/cpp/test/test_wake_lock_provider.h"
namespace ash {
......@@ -17,13 +18,15 @@ namespace ash {
// IsAmbientModeAllowedForProfile() returns true to run the unittests.
class ASH_PUBLIC_EXPORT TestAmbientClient : public AmbientClient {
public:
TestAmbientClient();
explicit TestAmbientClient(device::TestWakeLockProvider* wake_lock_provider);
~TestAmbientClient() override;
// AmbientClient:
bool IsAmbientModeAllowedForActiveUser() override;
void RequestAccessToken(GetAccessTokenCallback callback) override;
scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override;
void RequestWakeLockProvider(
mojo::PendingReceiver<device::mojom::WakeLockProvider> receiver) override;
// Simulate to issue an |access_token|.
// If |with_error| is true, will return an empty access token.
......@@ -33,6 +36,8 @@ class ASH_PUBLIC_EXPORT TestAmbientClient : public AmbientClient {
private:
GetAccessTokenCallback pending_callback_;
device::TestWakeLockProvider* const wake_lock_provider_;
};
} // namespace ash
......
......@@ -20,6 +20,7 @@
#include "components/signin/public/identity_manager/scope_set.h"
#include "components/user_manager/user.h"
#include "components/user_manager/user_manager.h"
#include "content/public/browser/device_service.h"
#include "google_apis/gaia/google_service_auth_error.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
......@@ -95,6 +96,11 @@ AmbientClientImpl::GetURLLoaderFactory() {
return profile->GetURLLoaderFactory();
}
void AmbientClientImpl::RequestWakeLockProvider(
mojo::PendingReceiver<device::mojom::WakeLockProvider> receiver) {
content::GetDeviceService().BindWakeLockProvider(std::move(receiver));
}
void AmbientClientImpl::GetAccessToken(
GetAccessTokenCallback callback,
const std::string& gaia_id,
......
......@@ -6,6 +6,7 @@
#define CHROME_BROWSER_UI_ASH_AMBIENT_AMBIENT_CLIENT_IMPL_H_
#include <memory>
#include <string>
#include "ash/public/cpp/ambient/ambient_client.h"
#include "base/memory/weak_ptr.h"
......@@ -27,6 +28,8 @@ class AmbientClientImpl : public ash::AmbientClient {
bool IsAmbientModeAllowedForActiveUser() override;
void RequestAccessToken(GetAccessTokenCallback callback) override;
scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override;
void RequestWakeLockProvider(
mojo::PendingReceiver<device::mojom::WakeLockProvider> receiver) override;
private:
void GetAccessToken(GetAccessTokenCallback callback,
......
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