| // Copyright 2013 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/metrics/user_metrics_recorder.h" |
| |
| #include <memory> |
| #include <vector> |
| |
| #include "ash/app_list/app_list_metrics.h" |
| #include "ash/constants/ash_pref_names.h" |
| #include "ash/login/ui/lock_screen.h" |
| #include "ash/metrics/demo_session_metrics_recorder.h" |
| #include "ash/metrics/desktop_task_switch_metric_recorder.h" |
| #include "ash/metrics/pointer_metrics_recorder.h" |
| #include "ash/metrics/stylus_metrics_recorder.h" |
| #include "ash/metrics/touch_usage_metrics_recorder.h" |
| #include "ash/public/cpp/accessibility_controller_enums.h" |
| #include "ash/public/cpp/shelf_item.h" |
| #include "ash/public/cpp/shelf_model.h" |
| #include "ash/session/session_controller_impl.h" |
| #include "ash/shelf/shelf.h" |
| #include "ash/shelf/shelf_view.h" |
| #include "ash/shell.h" |
| #include "base/metrics/histogram_macros.h" |
| #include "base/metrics/user_metrics.h" |
| #include "components/prefs/pref_service.h" |
| |
| namespace ash { |
| |
| namespace { |
| |
| // Time between calls to "RecordPeriodicMetrics". |
| constexpr base::TimeDelta kRecordPeriodicMetricsInterval = base::Minutes(30); |
| |
| // Returns true if kiosk mode is active. |
| bool IsKioskModeActive() { |
| return Shell::Get()->session_controller()->login_status() == |
| LoginStatus::KIOSK_APP; |
| } |
| |
| // Returns true if there is an active user and their session isn't currently |
| // locked. |
| bool IsUserActive() { |
| SessionControllerImpl* session = Shell::Get()->session_controller(); |
| return session->IsActiveUserSessionStarted() && !session->IsScreenLocked(); |
| } |
| |
| // Records the number of items in the shelf as an UMA statistic. |
| void RecordShelfItemCounts() { |
| int pinned_item_count = 0; |
| int unpinned_item_count = 0; |
| for (const ShelfItem& item : ShelfModel::Get()->items()) { |
| if (item.type == TYPE_PINNED_APP || item.type == TYPE_BROWSER_SHORTCUT) |
| ++pinned_item_count; |
| else |
| ++unpinned_item_count; |
| } |
| |
| UMA_HISTOGRAM_COUNTS_100("Ash.Shelf.NumberOfItems", |
| pinned_item_count + unpinned_item_count); |
| UMA_HISTOGRAM_COUNTS_100("Ash.Shelf.NumberOfPinnedItems", pinned_item_count); |
| UMA_HISTOGRAM_COUNTS_100("Ash.Shelf.NumberOfUnpinnedItems", |
| unpinned_item_count); |
| } |
| |
| } // namespace |
| |
| UserMetricsRecorder::UserMetricsRecorder() { |
| StartTimer(); |
| login_metrics_recorder_ = std::make_unique<LoginMetricsRecorder>(); |
| } |
| |
| UserMetricsRecorder::UserMetricsRecorder(bool record_periodic_metrics) { |
| if (record_periodic_metrics) |
| StartTimer(); |
| } |
| |
| UserMetricsRecorder::~UserMetricsRecorder() { |
| timer_.Stop(); |
| } |
| |
| // static |
| void UserMetricsRecorder::RecordUserClickOnTray( |
| LoginMetricsRecorder::TrayClickTarget target) { |
| LoginMetricsRecorder* recorder = |
| Shell::Get()->metrics()->login_metrics_recorder(); |
| recorder->RecordUserTrayClick(target); |
| } |
| |
| // static |
| void UserMetricsRecorder::RecordUserClickOnShelfButton( |
| LoginMetricsRecorder::ShelfButtonClickTarget target) { |
| LoginMetricsRecorder* recorder = |
| Shell::Get()->metrics()->login_metrics_recorder(); |
| recorder->RecordUserShelfButtonClick(target); |
| } |
| |
| void UserMetricsRecorder::StartDemoSessionMetricsRecording() { |
| demo_session_metrics_recorder_ = |
| std::make_unique<DemoSessionMetricsRecorder>(); |
| Shell::Get()->AddPreTargetHandler(demo_session_metrics_recorder_.get()); |
| } |
| |
| void UserMetricsRecorder::OnShellInitialized() { |
| // Lazy creation of the DesktopTaskSwitchMetricRecorder because it accesses |
| // Shell::Get() which is not available when |this| is instantiated. |
| if (!desktop_task_switch_metric_recorder_) { |
| desktop_task_switch_metric_recorder_ = |
| std::make_unique<DesktopTaskSwitchMetricRecorder>(); |
| } |
| pointer_metrics_recorder_ = std::make_unique<PointerMetricsRecorder>(); |
| touch_usage_metrics_recorder_ = std::make_unique<TouchUsageMetricsRecorder>(); |
| stylus_metrics_recorder_ = std::make_unique<StylusMetricsRecorder>(); |
| } |
| |
| void UserMetricsRecorder::OnShellShuttingDown() { |
| // Doing the nullptr check as the recorder is not initialized outside demo |
| // session. It was initialized during StartDemoSessionMetricsRecording(). |
| if (demo_session_metrics_recorder_ != nullptr) { |
| Shell::Get()->RemovePreTargetHandler(demo_session_metrics_recorder_.get()); |
| demo_session_metrics_recorder_.reset(); |
| } |
| desktop_task_switch_metric_recorder_.reset(); |
| |
| // To clean up `pointer_metrics_recorder_`, `touch_usage_metrics_recorder_` |
| // and `stylus_metrics_recorder_` properly, a valid shell instance is |
| // required, so explicitly delete them before the shell instance becomes |
| // invalid. |
| pointer_metrics_recorder_.reset(); |
| touch_usage_metrics_recorder_.reset(); |
| stylus_metrics_recorder_.reset(); |
| } |
| |
| void UserMetricsRecorder::RecordPeriodicMetrics() { |
| if (IsUserInActiveDesktopEnvironment()) { |
| RecordShelfItemCounts(); |
| RecordPeriodicAppListMetrics(); |
| } |
| } |
| |
| bool UserMetricsRecorder::IsUserInActiveDesktopEnvironment() const { |
| return IsUserActive() && !IsKioskModeActive(); |
| } |
| |
| void UserMetricsRecorder::StartTimer() { |
| timer_.Start(FROM_HERE, kRecordPeriodicMetricsInterval, this, |
| &UserMetricsRecorder::RecordPeriodicMetrics); |
| } |
| |
| } // namespace ash |