Skip to content

Commit

Permalink
[CrOS PhoneHub] Hook up recent apps UI to real data.
Browse files Browse the repository at this point in the history
Connect the recent app view to recent apps interaction handler to hook
up data.

and ash_unittests.

Test: Pass test cases: chromeos_components_unittests,
Bug: b/190466630, b/190466008
Change-Id: I82a42bf5d69bc7df79083d6c2e1ef824c9d359b7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3030882
Commit-Queue: Paulz Chen <paulzchen@google.com>
Auto-Submit: Paulz Chen <paulzchen@google.com>
Reviewed-by: Ryan Hansberry <hansberry@chromium.org>
Reviewed-by: Daniel Nishi <dhnishi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#906970}
  • Loading branch information
paulzhchen authored and Chromium LUCI CQ committed Jul 30, 2021
1 parent 98e3ffa commit 2889a37
Show file tree
Hide file tree
Showing 12 changed files with 301 additions and 65 deletions.
9 changes: 6 additions & 3 deletions ash/system/phonehub/phone_connected_view.cc
Expand Up @@ -55,9 +55,12 @@ PhoneConnectedView::PhoneConnectedView(
phone_model, phone_hub_manager->GetUserActionRecorder())));
}

if (features::IsEcheSWAEnabled() && features::IsPhoneHubRecentAppsEnabled()) {
setup_layered_view(
AddChildView(std::make_unique<PhoneHubRecentAppsView>()));
auto* recent_apps_handler =
phone_hub_manager->GetRecentAppsInteractionHandler();
if (features::IsEcheSWAEnabled() && features::IsPhoneHubRecentAppsEnabled() &&
recent_apps_handler) {
setup_layered_view(AddChildView(
std::make_unique<PhoneHubRecentAppsView>(recent_apps_handler)));
}
}

Expand Down
16 changes: 8 additions & 8 deletions ash/system/phonehub/phone_hub_recent_app_button.cc
Expand Up @@ -6,6 +6,7 @@

#include "ash/style/ash_color_provider.h"
#include "ash/system/tray/tray_popup_utils.h"
#include "ui/gfx/image/image_skia_operations.h"
#include "ui/views/controls/focus_ring.h"
#include "ui/views/controls/highlight_path_generator.h"
#include "ui/views/controls/image_view.h"
Expand All @@ -19,10 +20,13 @@ constexpr int kRecentAppButtonSize = 32;

} // namespace

PhoneHubRecentAppButton::PhoneHubRecentAppButton()
: views::ImageButton(
base::BindRepeating(&PhoneHubRecentAppButton::ButtonPressed,
base::Unretained(this))) {
PhoneHubRecentAppButton::PhoneHubRecentAppButton(const gfx::Image& icon,
PressedCallback callback)
: views::ImageButton(callback) {
SetImage(views::Button::STATE_NORMAL,
gfx::ImageSkiaOperations::CreateResizedImage(
icon.AsImageSkia(), skia::ImageOperations::RESIZE_BEST,
gfx::Size(kRecentAppButtonSize, kRecentAppButtonSize)));
SetImageHorizontalAlignment(ALIGN_CENTER);
SetImageVerticalAlignment(ALIGN_MIDDLE);
TrayPopupUtils::ConfigureTrayPopupButton(this);
Expand Down Expand Up @@ -57,8 +61,4 @@ const char* PhoneHubRecentAppButton::GetClassName() const {
return "PhoneHubRecentAppButton";
}

void PhoneHubRecentAppButton::ButtonPressed() {
// TODO(paulzchen): Launch the recent apps with package name.
}

} // namespace ash
11 changes: 6 additions & 5 deletions ash/system/phonehub/phone_hub_recent_app_button.h
Expand Up @@ -6,15 +6,19 @@
#define ASH_SYSTEM_PHONEHUB_PHONE_HUB_RECENT_APP_BUTTON_H_

#include "ash/ash_export.h"
#include "chromeos/components/phonehub/recent_apps_interaction_handler.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/image.h"
#include "ui/views/controls/button/image_button.h"

namespace ash {

// A recent app button containing an |AppMetadata|.
// A recent app button containing a application |icon|. The |callback| provided
// to build PhoneHubRecentAppButton implicitly contains the package name of the
// same application.
class ASH_EXPORT PhoneHubRecentAppButton : public views::ImageButton {
public:
PhoneHubRecentAppButton();
PhoneHubRecentAppButton(const gfx::Image& icon, PressedCallback callback);
~PhoneHubRecentAppButton() override;
PhoneHubRecentAppButton(PhoneHubRecentAppButton&) = delete;
PhoneHubRecentAppButton operator=(PhoneHubRecentAppButton&) = delete;
Expand All @@ -26,9 +30,6 @@ class ASH_EXPORT PhoneHubRecentAppButton : public views::ImageButton {
void PaintButtonContents(gfx::Canvas* canvas) override;
const char* GetClassName() const override;
void OnThemeChanged() override;

private:
void ButtonPressed();
};

} // namespace ash
Expand Down
29 changes: 20 additions & 9 deletions ash/system/phonehub/phone_hub_recent_apps_view.cc
Expand Up @@ -14,6 +14,7 @@
#include "ash/system/phonehub/ui_constants.h"
#include "ash/system/tray/tray_constants.h"
#include "base/cxx17_backports.h"
#include "chromeos/components/phonehub/notification.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/views/controls/label.h"
Expand Down Expand Up @@ -60,7 +61,10 @@ class HeaderView : public views::Label {

} // namespace

PhoneHubRecentAppsView::PhoneHubRecentAppsView() {
PhoneHubRecentAppsView::PhoneHubRecentAppsView(
chromeos::phonehub::RecentAppsInteractionHandler*
recent_apps_interaction_handler)
: recent_apps_interaction_handler_(recent_apps_interaction_handler) {
SetID(PhoneHubViewID::kPhoneHubRecentAppsView);
auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kVertical));
Expand All @@ -70,10 +74,6 @@ PhoneHubRecentAppsView::PhoneHubRecentAppsView() {
recent_app_buttons_view_ =
AddChildView(std::make_unique<RecentAppButtonsView>());

// TODO(paulzchen): Add recent apps button using real data from phone.
recent_app_button_list_.push_back(
std::make_unique<PhoneHubRecentAppButton>());

Update();
}

Expand Down Expand Up @@ -146,15 +146,26 @@ void PhoneHubRecentAppsView::RecentAppButtonsView::Reset() {

void PhoneHubRecentAppsView::Update() {
recent_app_buttons_view_->Reset();
recent_app_button_list_.clear();

if (recent_app_button_list_.empty()) {
std::vector<chromeos::phonehub::Notification::AppMetadata> recent_apps_list =
recent_apps_interaction_handler_->FetchRecentAppMetadataList();
if (recent_apps_list.empty()) {
SetVisible(false);
return;
}

// TODO(paulzchen): Add recent apps button using real data from phone.
for (auto& recent_app_button : recent_app_button_list_)
recent_app_buttons_view_->AddRecentAppButton(recent_app_button.get());
for (const auto& recent_app : recent_apps_list) {
auto pressed_callback =
base::BindRepeating(&chromeos::phonehub::RecentAppsInteractionHandler::
NotifyRecentAppClicked,
base::Unretained(recent_apps_interaction_handler_),
recent_app.package_name);
recent_app_button_list_.push_back(std::make_unique<PhoneHubRecentAppButton>(
recent_app.icon, pressed_callback));
recent_app_buttons_view_->AddRecentAppButton(
recent_app_button_list_.back().get());
}

PreferredSizeChanged();
SetVisible(true);
Expand Down
12 changes: 10 additions & 2 deletions ash/system/phonehub/phone_hub_recent_apps_view.h
Expand Up @@ -6,6 +6,7 @@
#define ASH_SYSTEM_PHONEHUB_PHONE_HUB_RECENT_APPS_VIEW_H_

#include "ash/ash_export.h"
#include "chromeos/components/phonehub/recent_apps_interaction_handler.h"
#include "ui/views/view.h"
#include "ui/views/view_model.h"

Expand All @@ -15,7 +16,9 @@ namespace ash {
// the recent apps list.
class ASH_EXPORT PhoneHubRecentAppsView : public views::View {
public:
PhoneHubRecentAppsView();
explicit PhoneHubRecentAppsView(
chromeos::phonehub::RecentAppsInteractionHandler*
recent_apps_interaction_handler);
~PhoneHubRecentAppsView() override;
PhoneHubRecentAppsView(PhoneHubRecentAppsView&) = delete;
PhoneHubRecentAppsView operator=(PhoneHubRecentAppsView&) = delete;
Expand All @@ -25,7 +28,10 @@ class ASH_EXPORT PhoneHubRecentAppsView : public views::View {

private:
FRIEND_TEST_ALL_PREFIXES(RecentAppButtonsViewTest, TaskViewVisibility);
FRIEND_TEST_ALL_PREFIXES(RecentAppButtonsViewTest, RecentAppButtonsView);
FRIEND_TEST_ALL_PREFIXES(RecentAppButtonsViewTest,
SingleRecentAppButtonsView);
FRIEND_TEST_ALL_PREFIXES(RecentAppButtonsViewTest,
MultipleRecentAppButtonsView);

class RecentAppButtonsView : public views::View {
public:
Expand All @@ -48,6 +54,8 @@ class ASH_EXPORT PhoneHubRecentAppsView : public views::View {

RecentAppButtonsView* recent_app_buttons_view_ = nullptr;
std::vector<std::unique_ptr<views::View>> recent_app_button_list_;
chromeos::phonehub::RecentAppsInteractionHandler*
recent_apps_interaction_handler_ = nullptr;
};

} // namespace ash
Expand Down
71 changes: 62 additions & 9 deletions ash/system/phonehub/phone_hub_recent_apps_view_unittest.cc
Expand Up @@ -6,9 +6,25 @@

#include "ash/system/phonehub/phone_hub_recent_app_button.h"
#include "ash/test/ash_test_base.h"
#include "chromeos/components/phonehub/fake_recent_apps_interaction_handler.h"
#include "chromeos/components/phonehub/notification.h"
#include "ui/gfx/image/image.h"
#include "ui/views/test/button_test_api.h"

namespace ash {

const char16_t kAppName[] = u"Test App";
const char kPackageName[] = "com.google.testapp";

namespace {

class FakeEvent : public ui::Event {
public:
FakeEvent() : Event(ui::ET_UNKNOWN, base::TimeTicks(), 0) {}
};

} // namespace

class RecentAppButtonsViewTest : public AshTestBase {
public:
RecentAppButtonsViewTest() = default;
Expand All @@ -18,7 +34,8 @@ class RecentAppButtonsViewTest : public AshTestBase {
void SetUp() override {
AshTestBase::SetUp();

phone_hub_recent_apps_view_ = std::make_unique<PhoneHubRecentAppsView>();
phone_hub_recent_apps_view_ = std::make_unique<PhoneHubRecentAppsView>(
&fake_recent_apps_interaction_handler_);
}

void TearDown() override {
Expand All @@ -31,28 +48,64 @@ class RecentAppButtonsViewTest : public AshTestBase {
return phone_hub_recent_apps_view_.get();
}

void NotifyRecentAppAddedOrUpdated() {
fake_recent_apps_interaction_handler_.NotifyRecentAppAddedOrUpdated(
chromeos::phonehub::Notification::AppMetadata(kAppName, kPackageName,
/*icon=*/gfx::Image()),
base::Time::Now());
}

size_t PackageNameToClickCount(const std::string& package_name) {
return fake_recent_apps_interaction_handler_.HandledRecentAppsCount(
package_name);
}

private:
std::unique_ptr<PhoneHubRecentAppsView> phone_hub_recent_apps_view_;
chromeos::phonehub::FakeRecentAppsInteractionHandler
fake_recent_apps_interaction_handler_;
};

TEST_F(RecentAppButtonsViewTest, TaskViewVisibility) {
// The view should not be shown when tab sync is not enabled.
recent_apps_view()->recent_app_button_list_.clear();
recent_apps_view()->Update();
// The recent app view is not visible if the NotifyRecentAppAddedOrUpdated
// function never be called, e.g. device boot.
EXPECT_FALSE(recent_apps_view()->GetVisible());

recent_apps_view()->recent_app_button_list_.push_back(
std::make_unique<PhoneHubRecentAppButton>());
NotifyRecentAppAddedOrUpdated();
recent_apps_view()->Update();

EXPECT_TRUE(recent_apps_view()->GetVisible());
}

TEST_F(RecentAppButtonsViewTest, RecentAppButtonsView) {
// TODO(paulzchen): Check real expected number when the recent app button
// using real data from phone.
TEST_F(RecentAppButtonsViewTest, SingleRecentAppButtonsView) {
NotifyRecentAppAddedOrUpdated();
recent_apps_view()->Update();

size_t expected_recent_app_button = 1;
EXPECT_EQ(expected_recent_app_button,
recent_apps_view()->recent_app_buttons_view_->children().size());
}

TEST_F(RecentAppButtonsViewTest, MultipleRecentAppButtonsView) {
NotifyRecentAppAddedOrUpdated();
NotifyRecentAppAddedOrUpdated();
NotifyRecentAppAddedOrUpdated();
recent_apps_view()->Update();

size_t expected_recent_app_button = 3;
EXPECT_EQ(expected_recent_app_button,
recent_apps_view()->recent_app_buttons_view_->children().size());

for (auto* child : recent_apps_view()->recent_app_buttons_view_->children()) {
PhoneHubRecentAppButton* recent_app =
static_cast<PhoneHubRecentAppButton*>(child);
// Simulate clicking button using placeholder event.
views::test::ButtonTestApi(recent_app).NotifyClick(FakeEvent());
}

size_t expected_number_of_button_be_clicked = 3;
EXPECT_EQ(expected_number_of_button_be_clicked,
PackageNameToClickCount(kPackageName));
}

} // namespace ash
Expand Up @@ -3,6 +3,7 @@
// found in the LICENSE file.

#include "chromeos/components/phonehub/fake_recent_apps_interaction_handler.h"
#include "base/containers/contains.h"
#include "chromeos/components/phonehub/notification.h"

namespace chromeos {
Expand All @@ -13,8 +14,12 @@ FakeRecentAppsInteractionHandler::FakeRecentAppsInteractionHandler() = default;
FakeRecentAppsInteractionHandler::~FakeRecentAppsInteractionHandler() = default;

void FakeRecentAppsInteractionHandler::NotifyRecentAppClicked(
const Notification::AppMetadata& app_metadata) {
handled_recent_apps_count_++;
const std::string& recent_app_package_name) {
if (base::Contains(package_name_to_click_count_, recent_app_package_name)) {
package_name_to_click_count_.at(recent_app_package_name)++;
return;
}
package_name_to_click_count_[recent_app_package_name] = 1;
}

void FakeRecentAppsInteractionHandler::AddRecentAppClickObserver(
Expand All @@ -27,5 +32,20 @@ void FakeRecentAppsInteractionHandler::RemoveRecentAppClickObserver(
recent_app_click_observer_count_--;
}

void FakeRecentAppsInteractionHandler::NotifyRecentAppAddedOrUpdated(
const Notification::AppMetadata& app_metadata,
base::Time last_accessed_timestamp) {
recent_apps_metadata_.emplace_back(app_metadata, last_accessed_timestamp);
}

std::vector<Notification::AppMetadata>
FakeRecentAppsInteractionHandler::FetchRecentAppMetadataList() {
std::vector<Notification::AppMetadata> app_metadata_list;
for (const auto& recent_app_metadata : recent_apps_metadata_) {
app_metadata_list.emplace_back(recent_app_metadata.first);
}
return app_metadata_list;
}

} // namespace phonehub
} // namespace chromeos
Expand Up @@ -22,22 +22,29 @@ class FakeRecentAppsInteractionHandler : public RecentAppsInteractionHandler {
const FakeRecentAppsInteractionHandler&) = delete;
~FakeRecentAppsInteractionHandler() override;

size_t handled_recent_apps_count() const {
return handled_recent_apps_count_;
size_t HandledRecentAppsCount(const std::string& package_name) const {
return package_name_to_click_count_.at(package_name);
}

size_t recent_app_click_observer_count() const {
return recent_app_click_observer_count_;
}

void NotifyRecentAppClicked(
const Notification::AppMetadata& app_metadata) override;
const std::string& recent_app_package_name) override;
void AddRecentAppClickObserver(RecentAppClickObserver* observer) override;
void RemoveRecentAppClickObserver(RecentAppClickObserver* observer) override;
void NotifyRecentAppAddedOrUpdated(
const Notification::AppMetadata& app_metadata,
base::Time last_accessed_timestamp) override;
std::vector<Notification::AppMetadata> FetchRecentAppMetadataList() override;

private:
size_t handled_recent_apps_count_ = 0;
size_t recent_app_click_observer_count_ = 0;

std::vector<std::pair<Notification::AppMetadata, base::Time>>
recent_apps_metadata_;
std::map<std::string, size_t> package_name_to_click_count_;
};

} // namespace phonehub
Expand Down
3 changes: 1 addition & 2 deletions chromeos/components/phonehub/recent_app_click_observer.h
Expand Up @@ -6,7 +6,6 @@
#define CHROMEOS_COMPONENTS_PHONEHUB_RECENT_APP_CLICK_OBSERVER_H_

#include "base/observer_list_types.h"
#include "chromeos/components/phonehub/notification.h"

namespace chromeos {
namespace phonehub {
Expand All @@ -18,7 +17,7 @@ class RecentAppClickObserver : public base::CheckedObserver {
// Called when the user clicks the recent app which has an open
// action in the PhoneHub.
virtual void OnRecentAppClicked(
const Notification::AppMetadata& app_metadata) = 0;
const std::string& recent_app_package_name) = 0;
};

} // namespace phonehub
Expand Down

0 comments on commit 2889a37

Please sign in to comment.