File: demo_session_metrics_recorder.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (287 lines) | stat: -rw-r--r-- 10,777 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
// Copyright 2018 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_METRICS_DEMO_SESSION_METRICS_RECORDER_H_
#define ASH_METRICS_DEMO_SESSION_METRICS_RECORDER_H_

#include <map>
#include <memory>
#include <string>
#include <vector>

#include "ash/ash_export.h"
#include "base/containers/flat_set.h"
#include "base/memory/raw_ptr.h"
#include "base/scoped_observation.h"
#include "base/time/time.h"
#include "chromeos/ui/base/app_types.h"
#include "ui/aura/window_observer.h"
#include "ui/base/user_activity/user_activity_detector.h"
#include "ui/base/user_activity/user_activity_observer.h"
#include "ui/events/event_handler.h"
#include "ui/wm/public/activation_change_observer.h"
#include "ui/wm/public/activation_client.h"

namespace base {
class RepeatingTimer;
}  // namespace base

namespace ash {

// A metrics recorder for demo sessions that samples the active window's app or
// window type. Only used when the device is in Demo Mode.
class ASH_EXPORT DemoSessionMetricsRecorder
    : public ui::UserActivityObserver,
      public wm::ActivationChangeObserver,
      public ui::EventHandler {
 public:
  // These apps are preinstalled in Demo Mode. This list is not exhaustive, and
  // includes first- and third-party Chrome and ARC apps.
  //
  // These values are persisted to logs. Entries should not be renumbered and
  // numeric values should never be reused.
  enum class DemoModeApp {
    kBrowser = 0,
    kOtherChromeApp = 1,
    kOtherArcApp = 2,
    kOtherWindow = 3,
    kHighlights = 4,  // Auto-launched Demo Mode app highlighting CrOS features.
    kAsphalt8 = 5,    // Android racing game demo app.
    kCamera = 6,
    kFiles = 7,
    kGetHelp = 8,
    kGoogleKeepChromeApp = 9,
    kGooglePhotos = 10,
    kGoogleSheetsAndroidApp = 11,
    kGoogleSlidesAndroidApp = 12,
    kInfinitePainter = 13,  // Android painting app.
    kMyScriptNebo = 14,     // Android note-taking app.
    kPlayStore = 15,
    kSquid = 16,  // Android note-taking app.
    kWebStore = 17,
    kYouTube = 18,
    kScreensaver = 19,    // Demo Mode screensaver app.
    kAsphalt9 = 20,       // Android racing game demo app.
    kStardewValley = 21,  // Android farming game demo app.
    kKinemaster = 22,     // Android video editing software demo app. nocheck
    kGoogleKeepAndroidApp = 23,
    kAutoCAD = 24,     // Android 2D/3D drawing software demo app.
    kPixlr = 25,       // Android photo editing software demo app.
    kCalculator = 26,  // Essential apps calculator.
    kCalendar = 27,
    kGoogleDocsChromeApp = 28,
    kGoogleSheetsChromeApp = 29,
    kGoogleSlidesChromeApp = 30,
    kYoutubePwa = 31,
    kGoogleDocsPwa = 32,
    kGoogleMeetPwa = 33,
    kGoogleSheetsPwa = 34,
    kSpotify = 35,
    kBeFunky = 36,
    kClipchamp = 37,
    kGeForceNow = 38,
    kZoom = 39,
    kSumo = 40,
    kAdobeSpark = 41,
    kMinecraft = 42,
    kGemini = 43,
    // Add future entries above this comment, in sync with enums.xml.
    // Update kMaxValue to the last value.
    kMaxValue = kGemini,
  };

  enum class ExitSessionFrom {
    kShelf = 0,
    kSystemTray = 1,
    kSystemTrayPowerButton = 2,
  };

  // The types of the result of the demo account setup or cleanup request.
  // This enum is tied directly to a UMA enum
  // `DemoModeSignedInAccountRequestResult`, and should always reflect it (do
  // not change one without changing the other). Entries should never be
  // modified or reordered. Entries can only be removed by deprecating it and
  // its value should never be reused. New ones should be added to the end
  // (right before the max value).
  enum class DemoAccountRequestResultCode {
    kSuccess = 0,               // Demo account request success.
    kResponseParsingError = 1,  // Malformat Http response.
    kInvalidCreds = 2,          // Missing required credential for login.
    kEmptyResponse = 3,         // Empty Http response.
    kNetworkError = 4,          // Network error.
    kRequestFailed = 5,         // Server side error or out of quota.
    kCloudPolicyNotConnected =
        6,  // Unable to obtain the DM Token and the Client ID due to the cloud
            // policy not connected.
    kEmptyDMToken = 7,   // The DM Token on the device is empty.
    kEmptyClientID = 8,  // The Client ID on the device is empty.
    kQuotaExhaustedRetriable =
        9,  // Server quota exhausted, might be max QPS reached.
    kQuotaExhaustedNotRetriable =
        10,  // Server quota exhausted, device might be blocked.
    kMaxValue = kQuotaExhaustedNotRetriable,
  };

  // Types of the current demo session.
  //
  // It is worth noting that here is not perfectly accurate on the word
  // "current", because functions in `[demo_login_controller.cc]
  // LoginDemoAccount()` are asyc calls and they may fail with no failure
  // handlers. It may not reflect the actual current session type on failure,
  // but instead, it's more like an "upcoming" session type, also because it's
  // set before entering the session.
  //
  // However, when you get its value in `DemoSessionMetricsRecorder`, it is
  // reflecting the current session type as we're currently in the session.
  enum class SessionType {
    // Classic managed guest session.
    kClassicMGS = 0,
    // Signed-in demo session.
    kSignedInDemoSession = 1,
    // Fallback managed guest session due to the sign-in failure.
    kFallbackMGS = 2,
  };

  static constexpr char kUserClicksAndPressesMetric[] =
      "DemoMode.UserClicksAndPresses";

  static void RecordExitSessionAction(ExitSessionFrom recorded_from);

  // Getter of this class' instance.
  static DemoSessionMetricsRecorder* Get();

  // Records the result of the demo account setup request.
  static void ReportDemoAccountSetupResult(
      DemoAccountRequestResultCode result_code);

  // Records the result of the demo account cleanup request.
  static void ReportDemoAccountCleanupResult(
      DemoAccountRequestResultCode result_code);

  // It is used by Demo Mode only, and called by DemoLoginController before
  // entering the session, to set the upcoming session type.
  static void SetCurrentSessionType(SessionType session_type);

  // Get the type of the current demo session.
  static SessionType GetCurrentSessionTypeForTesting();

  // Records cloud policy connections timeout.
  static void RecordCloudPolicyConnectionTimeout();

  // The recorder will create a normal timer by default. Tests should provide a
  // mock timer to control sampling periods.
  explicit DemoSessionMetricsRecorder(
      std::unique_ptr<base::RepeatingTimer> timer = nullptr);

  DemoSessionMetricsRecorder(const DemoSessionMetricsRecorder&) = delete;
  DemoSessionMetricsRecorder& operator=(const DemoSessionMetricsRecorder&) =
      delete;

  ~DemoSessionMetricsRecorder() override;

  // ui::UserActivityObserver:
  void OnUserActivity(const ui::Event* event) override;

  // wm::ActivationChangeObserver:
  void OnWindowActivated(wm::ActivationChangeObserver::ActivationReason reason,
                         aura::Window* gained_active,
                         aura::Window* lost_active) override;

  // ui::EventHandler:
  void OnMouseEvent(ui::MouseEvent* event) override;
  void OnTouchEvent(ui::TouchEvent* event) override;

  // Records the duration of time the user spent interacting with the current
  // demo mode signed-in shopper session, measured from first user activity to
  // last user activity.
  void ReportShopperSessionDwellTime();

  // Called by DemoModeWindowCloser::OnInstanceUpdate:
  // Passing `app_id_or_package` instead of `aura::Window` here because app
  // information set in window property might now be ready on app creation.
  void OnAppCreation(const std::string& app_id_or_package,
                     const bool is_arc_app);
  void OnAppDestruction(const std::string& app_id_or_package,
                        const bool is_arc_app);

 private:
  // Starts the timer for periodic sampling.
  void StartRecording();

  // Records the active window's app type or, if the user has been inactive for
  // too long, pauses sampling and wipes samples from the inactive period.
  void TakeSampleOrPause();

  // Emits histograms for recorded samples.
  void ReportSamples();

  // Records |app| as being seen while sampling all active apps.
  void RecordActiveAppSample(DemoModeApp app);

  // Indicates whether the specified app_id should be recorded for
  // the unique-apps-launched stat.
  bool ShouldRecordAppLaunch(const std::string& app_id);

  // Records the specified app's launch, subject to the
  // restrictions of ShouldRecordAppLaunch().
  void RecordAppLaunch(const std::string& id, chromeos::AppType app_type);

  // Emits various histograms for unique apps launched.
  void ReportUniqueAppsLaunched();

  // Records the duration of time the user spent interacting with the current
  // demo session, measured from first user activity to last user activity.
  void ReportDwellTime();

  // Records the number of times the user clicks mouse/trackpad and presses
  // screen in the demo session.
  void ReportUserClickesAndPresses();

  // Stores samples as they are collected. Report to UMA if we see user
  // activity soon after. Guaranteed not to grow too large.
  std::vector<DemoModeApp> unreported_samples_;

  // Indicates whether the unique-app-launch stats recording has been enabled.
  bool unique_apps_launched_recording_enabled_ = false;

  // Tracks the ids of apps that have been launched in Demo Mode.
  base::flat_set<std::string> unique_apps_launched_;

  // Used for subscribing to window activation events.
  raw_ptr<wm::ActivationClient> activation_client_ = nullptr;

  // How many periods have elapsed since the last user activity.
  int periods_since_activity_ = 0;

  // Indicates number of user clicks mouse/trackpad and presses screen with
  // demo mode in the current session.
  int user_clicks_and_presses_ = 0;

  base::TimeTicks first_user_activity_;

  base::TimeTicks last_user_activity_;

  base::TimeTicks shopper_session_first_user_activity_;

  std::unique_ptr<base::RepeatingTimer> timer_;

  base::ScopedObservation<ui::UserActivityDetector, ui::UserActivityObserver>
      observation_{this};

  class ActiveAppArcPackageNameObserver;
  class UniqueAppsLaunchedArcPackageNameObserver;

  std::unique_ptr<UniqueAppsLaunchedArcPackageNameObserver>
      unique_apps_arc_package_name_observer_;

  std::unique_ptr<ActiveAppArcPackageNameObserver>
      active_app_arc_package_name_observer_;

  // Tracks the app start time for app defined in `kAppsHistogramSuffix`.
  std::map<DemoModeApp, base::TimeTicks> apps_start_time_;
};

}  // namespace ash

#endif  // ASH_METRICS_DEMO_SESSION_METRICS_RECORDER_H_