From 5b13c56c3552c9968cb6ae1eb65fce6e2edebaa1 Mon Sep 17 00:00:00 2001
From: Pu Shi <pushi@google.com>
Date: Wed, 22 Mar 2023 22:25:45 +0000
Subject: [PATCH] [Exo] Add provider to store last connection status and entry
 point

Create an AppsLaunchInfoProvider to store last connection check
result and the entry point that app streaming started from. This
will be used to check which histogram we should log the app streaming
result.

Bug: b/274477247
Change-Id: I8802d3bc5bb22cb6c936e08e64475c7ac681da3f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4347923
Reviewed-by: Crisrael Lucero <crisrael@google.com>
Reviewed-by: Jon Mann <jonmann@chromium.org>
Commit-Queue: Pu Shi <pushi@google.com>
Cr-Commit-Position: refs/heads/main@{#1120830}
---
 ash/webui/eche_app_ui/BUILD.gn                |   3 +
 .../eche_app_ui/apps_launch_info_provider.cc  |  33 ++++++
 .../eche_app_ui/apps_launch_info_provider.h   |  48 +++++++++
 .../apps_launch_info_provider_unittest.cc     | 101 ++++++++++++++++++
 ash/webui/eche_app_ui/eche_app_manager.cc     |  18 ++--
 ash/webui/eche_app_ui/eche_app_manager.h      |   5 +-
 .../eche_notification_click_handler.cc        |   9 +-
 .../eche_notification_click_handler.h         |  10 +-
 ...che_notification_click_handler_unittest.cc |  13 ++-
 .../eche_recent_app_click_handler.cc          |   8 +-
 .../eche_recent_app_click_handler.h           |   5 +-
 .../eche_recent_app_click_handler_unittest.cc |  15 ++-
 12 files changed, 251 insertions(+), 17 deletions(-)
 create mode 100644 ash/webui/eche_app_ui/apps_launch_info_provider.cc
 create mode 100644 ash/webui/eche_app_ui/apps_launch_info_provider.h
 create mode 100644 ash/webui/eche_app_ui/apps_launch_info_provider_unittest.cc

diff --git a/ash/webui/eche_app_ui/BUILD.gn b/ash/webui/eche_app_ui/BUILD.gn
index 787f232348df4..3bd749e61d7f4 100644
--- a/ash/webui/eche_app_ui/BUILD.gn
+++ b/ash/webui/eche_app_ui/BUILD.gn
@@ -54,6 +54,8 @@ static_library("eche_app_ui") {
     "apps_access_manager_impl.h",
     "apps_access_setup_operation.cc",
     "apps_access_setup_operation.h",
+    "apps_launch_info_provider.cc",
+    "apps_launch_info_provider.h",
     "eche_alert_generator.cc",
     "eche_alert_generator.h",
     "eche_app_manager.cc",
@@ -163,6 +165,7 @@ source_set("unit_tests") {
   sources = [
     "apps_access_manager_impl_unittest.cc",
     "apps_access_setup_operation_unittest.cc",
+    "apps_launch_info_provider_unittest.cc",
     "eche_alert_generator_unittest.cc",
     "eche_app_manager_unittest.cc",
     "eche_connection_scheduler_impl_unittest.cc",
diff --git a/ash/webui/eche_app_ui/apps_launch_info_provider.cc b/ash/webui/eche_app_ui/apps_launch_info_provider.cc
new file mode 100644
index 0000000000000..13b657f4c8195
--- /dev/null
+++ b/ash/webui/eche_app_ui/apps_launch_info_provider.cc
@@ -0,0 +1,33 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/webui/eche_app_ui/apps_launch_info_provider.h"
+
+#include "ash/webui/eche_app_ui/mojom/eche_app.mojom-shared.h"
+
+namespace ash {
+namespace eche_app {
+
+AppsLaunchInfoProvider::AppsLaunchInfoProvider(
+    EcheConnectionStatusHandler* connection_handler)
+    : eche_connection_status_handler_(connection_handler) {
+  eche_connection_status_handler_->AddObserver(this);
+}
+
+AppsLaunchInfoProvider::~AppsLaunchInfoProvider() {
+  eche_connection_status_handler_->RemoveObserver(this);
+}
+
+void AppsLaunchInfoProvider::OnConnectionStatusForUiChanged(
+    mojom::ConnectionStatus connection_status) {
+  last_connection_ = connection_status;
+}
+
+void AppsLaunchInfoProvider::SetEntryPoint(
+    mojom::AppStreamLaunchEntryPoint entry_point) {
+  entry_point_ = entry_point;
+}
+
+}  // namespace eche_app
+}  // namespace ash
\ No newline at end of file
diff --git a/ash/webui/eche_app_ui/apps_launch_info_provider.h b/ash/webui/eche_app_ui/apps_launch_info_provider.h
new file mode 100644
index 0000000000000..5612cba1167bf
--- /dev/null
+++ b/ash/webui/eche_app_ui/apps_launch_info_provider.h
@@ -0,0 +1,48 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_WEBUI_ECHE_APP_UI_APPS_LAUNCH_INFO_PROVIDER_H_
+#define ASH_WEBUI_ECHE_APP_UI_APPS_LAUNCH_INFO_PROVIDER_H_
+
+#include <cstdint>
+#include "ash/webui/eche_app_ui/eche_connection_status_handler.h"
+#include "ash/webui/eche_app_ui/mojom/eche_app.mojom-shared.h"
+#include "ash/webui/eche_app_ui/mojom/eche_app.mojom.h"
+
+namespace ash {
+namespace eche_app {
+
+// A class to store app stream entry point and last connection status.
+class AppsLaunchInfoProvider : public EcheConnectionStatusHandler::Observer {
+ public:
+  explicit AppsLaunchInfoProvider(EcheConnectionStatusHandler*);
+  ~AppsLaunchInfoProvider() override;
+
+  AppsLaunchInfoProvider(const AppsLaunchInfoProvider&) = delete;
+  AppsLaunchInfoProvider& operator=(const AppsLaunchInfoProvider&) = delete;
+
+  // EcheConnectionStatusHandler::Observer:
+  void OnConnectionStatusForUiChanged(
+      mojom::ConnectionStatus connection_status) override;
+
+  void SetEntryPoint(mojom::AppStreamLaunchEntryPoint entry_point);
+
+  mojom::ConnectionStatus GetConnectionStatusForUi() {
+    return last_connection_;
+  }
+
+  mojom::AppStreamLaunchEntryPoint entry_point() { return entry_point_; }
+
+ private:
+  EcheConnectionStatusHandler* eche_connection_status_handler_;
+  mojom::AppStreamLaunchEntryPoint entry_point_ =
+      mojom::AppStreamLaunchEntryPoint::UNKNOWN;
+  mojom::ConnectionStatus last_connection_ =
+      mojom::ConnectionStatus::kConnectionStatusDisconnected;
+};
+
+}  // namespace eche_app
+}  // namespace ash
+
+#endif  // ASH_WEBUI_ECHE_APP_UI_APPS_LAUNCH_INFO_PROVIDER_H_
\ No newline at end of file
diff --git a/ash/webui/eche_app_ui/apps_launch_info_provider_unittest.cc b/ash/webui/eche_app_ui/apps_launch_info_provider_unittest.cc
new file mode 100644
index 0000000000000..7b0adf5703136
--- /dev/null
+++ b/ash/webui/eche_app_ui/apps_launch_info_provider_unittest.cc
@@ -0,0 +1,101 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/webui/eche_app_ui/apps_launch_info_provider.h"
+#include <memory>
+#include "ash/webui/eche_app_ui/eche_connection_status_handler.h"
+
+#include "ash/constants/ash_features.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace ash::eche_app {
+
+class AppsLaunchInfoProviderTest : public testing::Test {
+ public:
+  AppsLaunchInfoProviderTest() = default;
+  AppsLaunchInfoProviderTest(const AppsLaunchInfoProviderTest&) = delete;
+  AppsLaunchInfoProviderTest& operator=(const AppsLaunchInfoProviderTest&) =
+      delete;
+  ~AppsLaunchInfoProviderTest() override = default;
+
+  // testing::Test:
+  void SetUp() override {
+    scoped_feature_list_.InitWithFeatures(
+        /*enabled_features=*/{features::kEcheSWA,
+                              features::kEcheNetworkConnectionState},
+        /*disabled_features=*/{});
+
+    handler_ = std::make_unique<EcheConnectionStatusHandler>();
+    provider_ = std::make_unique<AppsLaunchInfoProvider>(handler_.get());
+  }
+
+  void TearDown() override {
+    provider_.reset();
+    handler_.reset();
+  }
+
+  void NotifyConnectionStatusForUiChanged(mojom::ConnectionStatus status) {
+    handler_->SetConnectionStatusForUi(status);
+  }
+
+  mojom::ConnectionStatus GetLastConnectionStatus() {
+    return provider_->GetConnectionStatusForUi();
+  }
+
+  void SetEntryPoint(mojom::AppStreamLaunchEntryPoint entry_point) {
+    provider_->SetEntryPoint(entry_point);
+  }
+
+  mojom::AppStreamLaunchEntryPoint GetEntryPoint() {
+    return provider_->entry_point();
+  }
+
+  base::test::ScopedFeatureList scoped_feature_list_;
+
+ private:
+  std::unique_ptr<EcheConnectionStatusHandler> handler_;
+  std::unique_ptr<AppsLaunchInfoProvider> provider_;
+};
+
+TEST_F(AppsLaunchInfoProviderTest, OnConnectionStatusForUiChanged) {
+  EXPECT_EQ(GetLastConnectionStatus(),
+            mojom::ConnectionStatus::kConnectionStatusDisconnected);
+
+  NotifyConnectionStatusForUiChanged(
+      mojom::ConnectionStatus::kConnectionStatusConnecting);
+  EXPECT_EQ(GetLastConnectionStatus(),
+            mojom::ConnectionStatus::kConnectionStatusConnecting);
+
+  NotifyConnectionStatusForUiChanged(
+      mojom::ConnectionStatus::kConnectionStatusConnected);
+  EXPECT_EQ(GetLastConnectionStatus(),
+            mojom::ConnectionStatus::kConnectionStatusConnected);
+
+  NotifyConnectionStatusForUiChanged(
+      mojom::ConnectionStatus::kConnectionStatusFailed);
+  EXPECT_EQ(GetLastConnectionStatus(),
+            mojom::ConnectionStatus::kConnectionStatusFailed);
+
+  NotifyConnectionStatusForUiChanged(
+      mojom::ConnectionStatus::kConnectionStatusDisconnected);
+  EXPECT_EQ(GetLastConnectionStatus(),
+            mojom::ConnectionStatus::kConnectionStatusDisconnected);
+}
+
+TEST_F(AppsLaunchInfoProviderTest, SetEntryPoint) {
+  EXPECT_EQ(GetEntryPoint(), mojom::AppStreamLaunchEntryPoint::UNKNOWN);
+
+  SetEntryPoint(mojom::AppStreamLaunchEntryPoint::NOTIFICATION);
+  EXPECT_EQ(GetEntryPoint(), mojom::AppStreamLaunchEntryPoint::NOTIFICATION);
+
+  SetEntryPoint(mojom::AppStreamLaunchEntryPoint::APPS_LIST);
+  EXPECT_EQ(GetEntryPoint(), mojom::AppStreamLaunchEntryPoint::APPS_LIST);
+
+  SetEntryPoint(mojom::AppStreamLaunchEntryPoint::RECENT_APPS);
+  EXPECT_EQ(GetEntryPoint(), mojom::AppStreamLaunchEntryPoint::RECENT_APPS);
+}
+
+}  // namespace ash::eche_app
\ No newline at end of file
diff --git a/ash/webui/eche_app_ui/eche_app_manager.cc b/ash/webui/eche_app_ui/eche_app_manager.cc
index 0dab695597841..11d3f4c22d607 100644
--- a/ash/webui/eche_app_ui/eche_app_manager.cc
+++ b/ash/webui/eche_app_ui/eche_app_manager.cc
@@ -9,6 +9,7 @@
 #include "ash/constants/ash_features.h"
 #include "ash/public/cpp/network_config_service.h"
 #include "ash/webui/eche_app_ui/apps_access_manager_impl.h"
+#include "ash/webui/eche_app_ui/apps_launch_info_provider.h"
 #include "ash/webui/eche_app_ui/eche_alert_generator.h"
 #include "ash/webui/eche_app_ui/eche_connection_metrics_recorder.h"
 #include "ash/webui/eche_app_ui/eche_connection_scheduler_impl.h"
@@ -59,18 +60,23 @@ EcheAppManager::EcheAppManager(
           device_sync_client,
           multidevice_setup_client,
           connection_manager_.get())),
+      eche_connection_status_handler_(
+          std::make_unique<EcheConnectionStatusHandler>()),
       launch_app_helper_(
           std::make_unique<LaunchAppHelper>(phone_hub_manager,
                                             launch_eche_app_function,
                                             launch_notification_function,
                                             close_notification_function)),
+      apps_launch_info_provider_(std::make_unique<AppsLaunchInfoProvider>(
+          eche_connection_status_handler_.get())),
       stream_status_change_handler_(
           std::make_unique<EcheStreamStatusChangeHandler>()),
       eche_notification_click_handler_(
           std::make_unique<EcheNotificationClickHandler>(
               phone_hub_manager,
               feature_status_provider_.get(),
-              launch_app_helper_.get())),
+              launch_app_helper_.get(),
+              apps_launch_info_provider_.get())),
       connection_scheduler_(std::make_unique<EcheConnectionSchedulerImpl>(
           connection_manager_.get(),
           feature_status_provider_.get())),
@@ -95,7 +101,8 @@ EcheAppManager::EcheAppManager(
               phone_hub_manager,
               feature_status_provider_.get(),
               launch_app_helper_.get(),
-              stream_status_change_handler_.get())),
+              stream_status_change_handler_.get(),
+              apps_launch_info_provider_.get())),
       alert_generator_(
           std::make_unique<EcheAlertGenerator>(launch_app_helper_.get(),
                                                pref_service)),
@@ -111,9 +118,7 @@ EcheAppManager::EcheAppManager(
               stream_status_change_handler_.get(),
               feature_status_provider_.get())),
       eche_stream_orientation_observer_(
-          std::make_unique<EcheStreamOrientationObserver>()),
-      eche_connection_status_handler_(
-          std::make_unique<EcheConnectionStatusHandler>()) {
+          std::make_unique<EcheStreamOrientationObserver>()) {
   ash::GetNetworkConfigService(
       remote_cros_network_config_.BindNewPipeAndPassReceiver());
   system_info_provider_ = std::make_unique<SystemInfoProvider>(
@@ -179,7 +184,6 @@ void EcheAppManager::StreamGoBack() {
 // NOTE: These should be destroyed in the opposite order of how these objects
 // are initialized in the constructor.
 void EcheAppManager::Shutdown() {
-  eche_connection_status_handler_.reset();
   eche_stream_orientation_observer_.reset();
   system_info_provider_.reset();
   eche_tray_stream_status_observer_.reset();
@@ -194,7 +198,9 @@ void EcheAppManager::Shutdown() {
   connection_scheduler_.reset();
   eche_notification_click_handler_.reset();
   stream_status_change_handler_.reset();
+  apps_launch_info_provider_.reset();
   launch_app_helper_.reset();
+  eche_connection_status_handler_.reset();
   feature_status_provider_.reset();
   connection_manager_.reset();
 }
diff --git a/ash/webui/eche_app_ui/eche_app_manager.h b/ash/webui/eche_app_ui/eche_app_manager.h
index 2f080510d4788..16cd4802efd1c 100644
--- a/ash/webui/eche_app_ui/eche_app_manager.h
+++ b/ash/webui/eche_app_ui/eche_app_manager.h
@@ -9,6 +9,7 @@
 
 #include <memory>
 
+#include "ash/webui/eche_app_ui/apps_launch_info_provider.h"
 #include "ash/webui/eche_app_ui/eche_feature_status_provider.h"
 #include "ash/webui/eche_app_ui/eche_notification_click_handler.h"
 #include "ash/webui/eche_app_ui/eche_recent_app_click_handler.h"
@@ -42,6 +43,7 @@ class SecureChannelClient;
 
 namespace eche_app {
 
+class AppsLaunchInfoProvider;
 class EcheConnector;
 class EcheMessageReceiver;
 class EcheAlertGenerator;
@@ -113,7 +115,9 @@ class EcheAppManager : public KeyedService {
  private:
   std::unique_ptr<secure_channel::ConnectionManager> connection_manager_;
   std::unique_ptr<EcheFeatureStatusProvider> feature_status_provider_;
+  std::unique_ptr<EcheConnectionStatusHandler> eche_connection_status_handler_;
   std::unique_ptr<LaunchAppHelper> launch_app_helper_;
+  std::unique_ptr<AppsLaunchInfoProvider> apps_launch_info_provider_;
   std::unique_ptr<EcheStreamStatusChangeHandler> stream_status_change_handler_;
   std::unique_ptr<EcheNotificationClickHandler>
       eche_notification_click_handler_;
@@ -133,7 +137,6 @@ class EcheAppManager : public KeyedService {
       eche_tray_stream_status_observer_;
   std::unique_ptr<EcheStreamOrientationObserver>
       eche_stream_orientation_observer_;
-  std::unique_ptr<EcheConnectionStatusHandler> eche_connection_status_handler_;
 };
 
 }  // namespace eche_app
diff --git a/ash/webui/eche_app_ui/eche_notification_click_handler.cc b/ash/webui/eche_app_ui/eche_notification_click_handler.cc
index 6987a623ae1b9..a95bbbc3dcab8 100644
--- a/ash/webui/eche_app_ui/eche_notification_click_handler.cc
+++ b/ash/webui/eche_app_ui/eche_notification_click_handler.cc
@@ -6,6 +6,7 @@
 
 #include "ash/root_window_controller.h"
 #include "ash/shell.h"
+#include "ash/webui/eche_app_ui/apps_launch_info_provider.h"
 #include "ash/webui/eche_app_ui/launch_app_helper.h"
 #include "base/metrics/histogram_functions.h"
 #include "chromeos/ash/components/multidevice/logging/logging.h"
@@ -17,9 +18,11 @@ namespace eche_app {
 EcheNotificationClickHandler::EcheNotificationClickHandler(
     phonehub::PhoneHubManager* phone_hub_manager,
     FeatureStatusProvider* feature_status_provider,
-    LaunchAppHelper* launch_app_helper)
+    LaunchAppHelper* launch_app_helper,
+    AppsLaunchInfoProvider* apps_launch_info_provider)
     : feature_status_provider_(feature_status_provider),
-      launch_app_helper_(launch_app_helper) {
+      launch_app_helper_(launch_app_helper),
+      apps_launch_info_provider_(apps_launch_info_provider) {
   handler_ = phone_hub_manager->GetNotificationInteractionHandler();
   phone_model_ = phone_hub_manager->GetPhoneModel();
   feature_status_provider_->AddObserver(this);
@@ -49,6 +52,8 @@ void EcheNotificationClickHandler::HandleNotificationClick(
       base::UmaHistogramEnumeration(
           "Eche.AppStream.LaunchAttempt",
           mojom::AppStreamLaunchEntryPoint::NOTIFICATION);
+      apps_launch_info_provider_->SetEntryPoint(
+          mojom::AppStreamLaunchEntryPoint::NOTIFICATION);
       launch_app_helper_->LaunchEcheApp(
           notification_id, app_metadata.package_name,
           app_metadata.visible_app_name, app_metadata.user_id,
diff --git a/ash/webui/eche_app_ui/eche_notification_click_handler.h b/ash/webui/eche_app_ui/eche_notification_click_handler.h
index f0b4fba367b4a..a9c450ba10623 100644
--- a/ash/webui/eche_app_ui/eche_notification_click_handler.h
+++ b/ash/webui/eche_app_ui/eche_notification_click_handler.h
@@ -22,14 +22,17 @@ class PhoneHubManager;
 namespace eche_app {
 
 class LaunchAppHelper;
+class AppsLaunchInfoProvider;
 
 // Handles notification clicks originating from Phone Hub notifications.
 class EcheNotificationClickHandler : public phonehub::NotificationClickHandler,
                                      public FeatureStatusProvider::Observer {
  public:
-  EcheNotificationClickHandler(phonehub::PhoneHubManager* phone_hub_manager,
-                               FeatureStatusProvider* feature_status_provider,
-                               LaunchAppHelper* launch_app_helper);
+  EcheNotificationClickHandler(
+      phonehub::PhoneHubManager* phone_hub_manager,
+      FeatureStatusProvider* feature_status_provider,
+      LaunchAppHelper* launch_app_helper,
+      AppsLaunchInfoProvider* apps_launch_info_provider);
   ~EcheNotificationClickHandler() override;
 
   EcheNotificationClickHandler(const EcheNotificationClickHandler&) = delete;
@@ -51,6 +54,7 @@ class EcheNotificationClickHandler : public phonehub::NotificationClickHandler,
   phonehub::PhoneModel* phone_model_;
   FeatureStatusProvider* feature_status_provider_;
   LaunchAppHelper* launch_app_helper_;
+  AppsLaunchInfoProvider* apps_launch_info_provider_;
   bool is_click_handler_set_ = false;
 };
 
diff --git a/ash/webui/eche_app_ui/eche_notification_click_handler_unittest.cc b/ash/webui/eche_app_ui/eche_notification_click_handler_unittest.cc
index 05ef6ead0c555..8203f4c2cdb6d 100644
--- a/ash/webui/eche_app_ui/eche_notification_click_handler_unittest.cc
+++ b/ash/webui/eche_app_ui/eche_notification_click_handler_unittest.cc
@@ -7,6 +7,8 @@
 #include <string>
 
 #include "ash/constants/ash_features.h"
+#include "ash/webui/eche_app_ui/apps_launch_info_provider.h"
+#include "ash/webui/eche_app_ui/eche_connection_status_handler.h"
 #include "ash/webui/eche_app_ui/fake_feature_status_provider.h"
 #include "ash/webui/eche_app_ui/fake_launch_app_helper.h"
 #include "ash/webui/eche_app_ui/launch_app_helper.h"
@@ -50,12 +52,18 @@ class EcheNotificationClickHandlerTest : public testing::Test {
         base::BindRepeating(
             &EcheNotificationClickHandlerTest::FakeCloseNotificationFunction,
             base::Unretained(this)));
+    connection_status_handler_ =
+        std::make_unique<eche_app::EcheConnectionStatusHandler>();
+    apps_launch_info_provider_ = std::make_unique<AppsLaunchInfoProvider>(
+        connection_status_handler_.get());
     handler_ = std::make_unique<EcheNotificationClickHandler>(
         &fake_phone_hub_manager_, &fake_feature_status_provider_,
-        launch_app_helper_.get());
+        launch_app_helper_.get(), apps_launch_info_provider_.get());
   }
 
   void TearDown() override {
+    connection_status_handler_.reset();
+    apps_launch_info_provider_.reset();
     launch_app_helper_.reset();
     handler_.reset();
   }
@@ -116,6 +124,9 @@ class EcheNotificationClickHandlerTest : public testing::Test {
   base::test::ScopedFeatureList scoped_feature_list_;
   FakeFeatureStatusProvider fake_feature_status_provider_;
   std::unique_ptr<FakeLaunchAppHelper> launch_app_helper_;
+  std::unique_ptr<eche_app::EcheConnectionStatusHandler>
+      connection_status_handler_;
+  std::unique_ptr<AppsLaunchInfoProvider> apps_launch_info_provider_;
   size_t num_notifications_shown_ = 0;
   size_t num_app_launch_ = 0;
 };
diff --git a/ash/webui/eche_app_ui/eche_recent_app_click_handler.cc b/ash/webui/eche_app_ui/eche_recent_app_click_handler.cc
index 11bcd4a292b6f..6ee72051b4217 100644
--- a/ash/webui/eche_app_ui/eche_recent_app_click_handler.cc
+++ b/ash/webui/eche_app_ui/eche_recent_app_click_handler.cc
@@ -8,6 +8,7 @@
 #include "ash/shell.h"
 #include "ash/system/eche/eche_tray.h"
 #include "ash/system/phonehub/phone_hub_ui_controller.h"
+#include "ash/webui/eche_app_ui/apps_launch_info_provider.h"
 #include "ash/webui/eche_app_ui/launch_app_helper.h"
 #include "base/metrics/histogram_functions.h"
 #include "chromeos/ash/components/phonehub/phone_hub_manager.h"
@@ -19,11 +20,13 @@ EcheRecentAppClickHandler::EcheRecentAppClickHandler(
     phonehub::PhoneHubManager* phone_hub_manager,
     FeatureStatusProvider* feature_status_provider,
     LaunchAppHelper* launch_app_helper,
-    EcheStreamStatusChangeHandler* stream_status_change_handler)
+    EcheStreamStatusChangeHandler* stream_status_change_handler,
+    AppsLaunchInfoProvider* apps_launch_info_provider)
     : phone_hub_manager_(phone_hub_manager),
       feature_status_provider_(feature_status_provider),
       launch_app_helper_(launch_app_helper),
-      stream_status_change_handler_(stream_status_change_handler) {
+      stream_status_change_handler_(stream_status_change_handler),
+      apps_launch_info_provider_(apps_launch_info_provider) {
   notification_handler_ =
       phone_hub_manager->GetNotificationInteractionHandler();
   recent_apps_handler_ = phone_hub_manager->GetRecentAppsInteractionHandler();
@@ -84,6 +87,7 @@ void EcheRecentAppClickHandler::OnRecentAppClicked(
       base::UmaHistogramEnumeration("Eche.AppStream.LaunchAttempt", entrypoint);
 
       to_stream_apps_.emplace_back(app_metadata);
+      apps_launch_info_provider_->SetEntryPoint(entrypoint);
       launch_app_helper_->LaunchEcheApp(
           /*notification_id=*/absl::nullopt, app_metadata.package_name,
           app_metadata.visible_app_name, app_metadata.user_id,
diff --git a/ash/webui/eche_app_ui/eche_recent_app_click_handler.h b/ash/webui/eche_app_ui/eche_recent_app_click_handler.h
index 2116e7733153d..bea65217f4865 100644
--- a/ash/webui/eche_app_ui/eche_recent_app_click_handler.h
+++ b/ash/webui/eche_app_ui/eche_recent_app_click_handler.h
@@ -24,6 +24,7 @@ class PhoneHubManager;
 namespace eche_app {
 
 class LaunchAppHelper;
+class AppsLaunchInfoProvider;
 
 // Handles recent app clicks originating from Phone Hub recent apps.
 class EcheRecentAppClickHandler
@@ -36,7 +37,8 @@ class EcheRecentAppClickHandler
       phonehub::PhoneHubManager* phone_hub_manager,
       FeatureStatusProvider* feature_status_provider,
       LaunchAppHelper* launch_app_helper,
-      EcheStreamStatusChangeHandler* stream_status_change_handler);
+      EcheStreamStatusChangeHandler* stream_status_change_handler,
+      AppsLaunchInfoProvider* apps_launch_info_provider);
   ~EcheRecentAppClickHandler() override;
 
   EcheRecentAppClickHandler(const EcheRecentAppClickHandler&) = delete;
@@ -70,6 +72,7 @@ class EcheRecentAppClickHandler
   LaunchAppHelper* launch_app_helper_;
   EcheStreamStatusChangeHandler* stream_status_change_handler_;
   std::vector<phonehub::Notification::AppMetadata> to_stream_apps_;
+  AppsLaunchInfoProvider* apps_launch_info_provider_;
   bool is_click_handler_set_ = false;
   bool is_stream_started_ = false;
 };
diff --git a/ash/webui/eche_app_ui/eche_recent_app_click_handler_unittest.cc b/ash/webui/eche_app_ui/eche_recent_app_click_handler_unittest.cc
index 106d8062292b7..3407f3f727499 100644
--- a/ash/webui/eche_app_ui/eche_recent_app_click_handler_unittest.cc
+++ b/ash/webui/eche_app_ui/eche_recent_app_click_handler_unittest.cc
@@ -4,9 +4,12 @@
 
 #include "ash/webui/eche_app_ui/eche_recent_app_click_handler.h"
 
+#include <memory>
 #include <string>
 
 #include "ash/constants/ash_features.h"
+#include "ash/webui/eche_app_ui/apps_launch_info_provider.h"
+#include "ash/webui/eche_app_ui/eche_connection_status_handler.h"
 #include "ash/webui/eche_app_ui/eche_stream_status_change_handler.h"
 #include "ash/webui/eche_app_ui/fake_feature_status_provider.h"
 #include "ash/webui/eche_app_ui/fake_launch_app_helper.h"
@@ -50,14 +53,21 @@ class EcheRecentAppClickHandlerTest : public testing::Test {
         base::BindRepeating(
             &EcheRecentAppClickHandlerTest::FakeCloseNotificationFunction,
             base::Unretained(this)));
+    connection_status_handler_ =
+        std::make_unique<eche_app::EcheConnectionStatusHandler>();
+    apps_launch_info_provider_ = std::make_unique<AppsLaunchInfoProvider>(
+        connection_status_handler_.get());
     stream_status_change_handler_ =
         std::make_unique<EcheStreamStatusChangeHandler>();
     handler_ = std::make_unique<EcheRecentAppClickHandler>(
         &fake_phone_hub_manager_, &fake_feature_status_provider_,
-        launch_app_helper_.get(), stream_status_change_handler_.get());
+        launch_app_helper_.get(), stream_status_change_handler_.get(),
+        apps_launch_info_provider_.get());
   }
 
   void TearDown() override {
+    apps_launch_info_provider_.reset();
+    connection_status_handler_.reset();
     launch_app_helper_.reset();
     handler_.reset();
     stream_status_change_handler_.reset();
@@ -137,6 +147,9 @@ class EcheRecentAppClickHandlerTest : public testing::Test {
   std::unique_ptr<FakeLaunchAppHelper> launch_app_helper_;
   std::unique_ptr<EcheStreamStatusChangeHandler> stream_status_change_handler_;
   std::unique_ptr<EcheRecentAppClickHandler> handler_;
+  std::unique_ptr<eche_app::EcheConnectionStatusHandler>
+      connection_status_handler_;
+  std::unique_ptr<AppsLaunchInfoProvider> apps_launch_info_provider_;
   std::string package_name_;
   std::u16string visible_name_;
   int64_t user_id_;