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
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
ash / components / arc / metrics / arc_metrics_service.h [blame]
// Copyright 2016 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_COMPONENTS_ARC_METRICS_ARC_METRICS_SERVICE_H_
#define ASH_COMPONENTS_ARC_METRICS_ARC_METRICS_SERVICE_H_
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
#include "ash/components/arc/metrics/arc_daily_metrics.h"
#include "ash/components/arc/metrics/arc_metrics_constants.h"
#include "ash/components/arc/metrics/arc_wm_metrics.h"
#include "ash/components/arc/mojom/anr.mojom.h"
#include "ash/components/arc/mojom/metrics.mojom.h"
#include "ash/components/arc/mojom/process.mojom.h"
#include "ash/components/arc/session/arc_bridge_service.h"
#include "ash/components/arc/session/connection_observer.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/singleton.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/observer_list_types.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "chromeos/ash/components/dbus/vm_concierge/concierge_service.pb.h"
#include "components/guest_os/guest_os_engagement_metrics.h"
#include "components/keyed_service/core/keyed_service.h"
#include "ui/events/ozone/gamepad/gamepad_observer.h"
#include "ui/wm/public/activation_change_observer.h"
class BrowserContextKeyedServiceFactory;
class PrefService;
namespace metrics {
class PSIMemoryParser;
} // namespace metrics
namespace aura {
class Window;
} // namespace aura
namespace content {
class BrowserContext;
} // namespace content
namespace arc {
class ArcMetricsAnr;
namespace mojom {
class AppInstance;
class IntentHelperInstance;
} // namespace mojom
// Collects information from other ArcServices and send UMA metrics.
class ArcMetricsService : public KeyedService,
public wm::ActivationChangeObserver,
public mojom::MetricsHost,
public ui::GamepadObserver {
public:
using HistogramNamerCallback =
base::RepeatingCallback<std::string(const std::string& base_name)>;
class AppKillObserver : public base::CheckedObserver {
public:
virtual void OnArcLowMemoryKill() = 0;
virtual void OnArcOOMKillCount(unsigned long count) = 0;
virtual void OnArcMemoryPressureKill(int count, int estimated_freed_kb) = 0;
virtual void OnArcMetricsServiceDestroyed() {}
};
class UserInteractionObserver : public base::CheckedObserver {
public:
virtual void OnUserInteraction(UserInteractionType type) = 0;
};
class BootTypeObserver : public base::CheckedObserver {
public:
virtual void OnBootTypeRetrieved(mojom::BootType type) = 0;
};
// Returns singleton instance for the given BrowserContext,
// or nullptr if the browser |context| is not allowed to use ARC.
static ArcMetricsService* GetForBrowserContext(
content::BrowserContext* context);
static ArcMetricsService* GetForBrowserContextForTesting(
content::BrowserContext* context);
// Returns factory instance for this class.
static BrowserContextKeyedServiceFactory* GetFactory();
ArcMetricsService(content::BrowserContext* context,
ArcBridgeService* bridge_service);
ArcMetricsService(const ArcMetricsService&) = delete;
ArcMetricsService& operator=(const ArcMetricsService&) = delete;
~ArcMetricsService() override;
// KeyedService overrides.
void Shutdown() override;
// Records one of Arc.UserInteraction UMA stats. |context| cannot be null.
static void RecordArcUserInteraction(content::BrowserContext* context,
UserInteractionType type);
// Sets the histogram namer. Required to not have a dependency on browser
// codebase.
void SetHistogramNamerCallback(HistogramNamerCallback histogram_namer_cb);
// Implementations for ConnectionObserver<mojom::ProcessInstance>.
void OnProcessConnectionReady();
void OnProcessConnectionClosed();
// MetricsHost overrides.
void ReportBootProgress(std::vector<mojom::BootProgressEventPtr> events,
mojom::BootType boot_type) override;
void ReportNativeBridge(mojom::NativeBridgeType native_bridge_type) override;
void ReportCompanionLibApiUsage(mojom::CompanionLibApiId api_id) override;
void ReportDnsQueryResult(mojom::ArcDnsQuery query, bool success) override;
void ReportAppKill(mojom::AppKillPtr app_kill) override;
void ReportArcCorePriAbiMigEvent(
mojom::ArcCorePriAbiMigEvent event_type) override;
void ReportArcCorePriAbiMigFailedTries(uint32_t failed_attempts) override;
void ReportArcCorePriAbiMigDowngradeDelay(base::TimeDelta delay) override;
void ReportArcCorePriAbiMigBootTime(base::TimeDelta duration) override;
void ReportArcSystemHealthUpgrade(base::TimeDelta duration,
bool packages_deleted) override;
void ReportAnr(mojom::AnrPtr anr) override;
void ReportLowLatencyStylusLibApiUsage(
mojom::LowLatencyStylusLibApiId api_id) override;
void ReportLowLatencyStylusLibPredictionTarget(
mojom::LowLatencyStylusLibPredictionTargetPtr prediction_target) override;
void ReportVpnServiceBuilderCompatApiUsage(
mojom::VpnServiceBuilderCompatApiId api_id) override;
void ReportNewQosSocketCount(int count) override;
void ReportQosSocketPercentage(int perc) override;
void ReportMainAccountHashMigrationMetrics(
mojom::MainAccountHashMigrationStatus status) override;
void ReportArcNetworkEvent(mojom::ArcNetworkEvent event) override;
void ReportArcNetworkError(mojom::ArcNetworkError error) override;
void ReportAppPrimaryAbi(mojom::AppPrimaryAbi abi) override;
void ReportDataRestore(mojom::DataRestoreStatus status,
int64_t duration_ms) override;
void ReportMemoryPressure(const std::vector<uint8_t>& psiFile) override;
void ReportProvisioningPreSignIn() override;
void ReportWaylandLateTimingEvent(mojom::WaylandTimingEvent event,
base::TimeDelta duration) override;
void ReportWebViewProcessStarted() override;
void ReportArcKeyMintError(mojom::ArcKeyMintError error) override;
void ReportDragResizeLatency(
const std::vector<base::TimeDelta>& durations) override;
void ReportAppErrorDialogType(mojom::AppErrorDialogType type) override;
void ReportApkCacheHit(bool hit) override;
void ReportAppCategoryDataSizeList(
std::vector<mojom::AppCategoryDataSizePtr> list) override;
void ReportDataDirectorySizeList(
std::vector<mojom::DataDirectorySizePtr> list) override;
void ReportArcKeyMintErrorForOperation(
mojom::ArcKeyMintError error,
mojom::ArcKeyMintLoggedOperation operation) override;
// wm::ActivationChangeObserver overrides.
// Records to UMA when a user has interacted with an ARC app window.
void OnWindowActivated(wm::ActivationChangeObserver::ActivationReason reason,
aura::Window* gained_active,
aura::Window* lost_active) override;
// ui::GamepadObserver overrides.
void OnGamepadEvent(const ui::GamepadEvent& event) override;
// ArcAppListPrefs::Observer callbacks which are called through
// ArcMetricsServiceProxy.
void OnTaskCreated(int32_t task_id,
const std::string& package_name,
const std::string& activity,
const std::string& intent);
void OnTaskDestroyed(int32_t task_id);
// ArcSessionManagerObserver callbacks which are called through
// ArcMetricsServiceProxy.
void OnArcStarted();
void OnArcSessionStopped();
void AddAppKillObserver(AppKillObserver* obs);
void RemoveAppKillObserver(AppKillObserver* obs);
void AddUserInteractionObserver(UserInteractionObserver* obs);
void RemoveUserInteractionObserver(UserInteractionObserver* obs);
void AddBootTypeObserver(BootTypeObserver* obs);
void RemoveBootTypeObserver(BootTypeObserver* obs);
// Finds the boot_progress_arc_upgraded event, removes it from |events|, and
// returns the event time. If the boot_progress_arc_upgraded event is not
// found, std::nullopt is returned. This function is public for testing
// purposes.
std::optional<base::TimeTicks> GetArcStartTimeFromEvents(
std::vector<mojom::BootProgressEventPtr>& events);
// Forwards reports of app kills resulting from a MemoryPressureArcvm signal
// to MemoryKillsMonitor via ArcMetricsServiceProxy.
void ReportMemoryPressureArcVmKills(int count, int estimated_freed_kb);
// Make a request to Concierge service for running VMs, then a request to
// ArcProcessService for kill counts. Public for testing.
void RequestKillCountsForTesting();
void SetPrefService(PrefService* prefs);
// Sets the UserId hash (cryptohome ID). Required to not have a dependency on
// browser codebase.
void set_user_id_hash(const std::string& user_id_hash) {
user_id_hash_ = user_id_hash;
}
ArcDailyMetrics* get_daily_metrics_for_testing() { return daily_.get(); }
// Record the starting time of ARC provisioning, for later use.
void ReportProvisioningStartTime(const base::TimeTicks& start_time,
const std::string& account_type_suffix);
private:
// Adapter to be able to also observe ProcessInstance events.
class ProcessObserver : public ConnectionObserver<mojom::ProcessInstance> {
public:
explicit ProcessObserver(ArcMetricsService* arc_metrics_service);
ProcessObserver(const ProcessObserver&) = delete;
ProcessObserver& operator=(const ProcessObserver&) = delete;
~ProcessObserver() override;
private:
// ConnectionObserver<mojom::ProcessInstance> overrides.
void OnConnectionReady() override;
void OnConnectionClosed() override;
raw_ptr<ArcMetricsService> arc_metrics_service_;
};
class ArcBridgeServiceObserver : public arc::ArcBridgeService::Observer {
public:
ArcBridgeServiceObserver();
ArcBridgeServiceObserver(const ArcBridgeServiceObserver&) = delete;
ArcBridgeServiceObserver& operator=(const ArcBridgeServiceObserver&) =
delete;
~ArcBridgeServiceObserver() override;
// Whether the arc bridge is in the process of closing.
bool arc_bridge_closing_ = false;
private:
// arc::ArcBridgeService::Observer overrides.
void BeforeArcBridgeClosed() override;
void AfterArcBridgeClosed() override;
};
class IntentHelperObserver
: public ConnectionObserver<mojom::IntentHelperInstance> {
public:
IntentHelperObserver(ArcMetricsService* arc_metrics_service,
ArcBridgeServiceObserver* arc_bridge_service_observer);
IntentHelperObserver(const IntentHelperObserver&) = delete;
IntentHelperObserver& operator=(const IntentHelperObserver&) = delete;
~IntentHelperObserver() override;
private:
// arc::internal::ConnectionObserver<mojom::IntentHelperInstance>
// overrides.
void OnConnectionClosed() override;
raw_ptr<ArcMetricsService> arc_metrics_service_;
raw_ptr<ArcBridgeServiceObserver> arc_bridge_service_observer_;
};
class AppLauncherObserver : public ConnectionObserver<mojom::AppInstance> {
public:
AppLauncherObserver(ArcMetricsService* arc_metrics_service,
ArcBridgeServiceObserver* arc_bridge_service_observer);
AppLauncherObserver(const AppLauncherObserver&) = delete;
AppLauncherObserver& operator=(const AppLauncherObserver&) = delete;
~AppLauncherObserver() override;
private:
// arc::internal::ConnectionObserver<mojom::IntentHelperInstance>
// overrides.
void OnConnectionClosed() override;
raw_ptr<ArcMetricsService> arc_metrics_service_;
raw_ptr<ArcBridgeServiceObserver> arc_bridge_service_observer_;
};
void RecordArcUserInteraction(UserInteractionType type);
void RequestProcessList();
void ParseProcessList(std::vector<mojom::RunningAppProcessInfoPtr> processes);
void OnRequestKillCountTimer();
void OnListVmsResponse(
std::optional<vm_tools::concierge::ListVmsResponse> response);
void OnLowMemoryKillCounts(
std::optional<vm_tools::concierge::ListVmsResponse> vms_list,
mojom::LowMemoryKillCountsPtr counts);
// DBus callbacks.
void OnArcStartTimeRetrieved(std::vector<mojom::BootProgressEventPtr> events,
mojom::BootType boot_type,
std::optional<base::TimeTicks> arc_start_time);
void OnArcStartTimeForPriAbiMigration(
base::TimeTicks durationTicks,
std::optional<base::TimeTicks> arc_start_time);
void OnVmsListedForKillCounts(
std::optional<vm_tools::concierge::ListVmsResponse> response);
// Notify AppKillObservers.
void NotifyLowMemoryKill();
void NotifyOOMKillCount(unsigned long count);
// Calls sysinfo() to get the load average value and store it.
void MeasureLoadAverage(size_t index);
// Records load average with the appropriate histogram name if ready.
void MaybeRecordLoadAveragePerProcessor();
THREAD_CHECKER(thread_checker_);
const raw_ptr<ArcBridgeService>
arc_bridge_service_; // Owned by ArcServiceManager.
// Helper class for tracking engagement metrics.
guest_os::GuestOsEngagementMetrics guest_os_engagement_metrics_;
// A function that appends a suffix to the base of a histogram name based on
// the current user profile.
HistogramNamerCallback histogram_namer_cb_;
std::string user_id_hash_;
ProcessObserver process_observer_;
base::RepeatingTimer request_process_list_timer_;
base::RepeatingTimer request_kill_count_timer_;
mojom::LowMemoryKillCountsPtr prev_logged_memory_kills_;
// Tracks metrics that should be logged daily. Lazily initialized in
// SetPrefService because we need PrefService to create.
std::unique_ptr<ArcDailyMetrics> daily_;
ArcBridgeServiceObserver arc_bridge_service_observer_;
IntentHelperObserver intent_helper_observer_;
AppLauncherObserver app_launcher_observer_;
std::unique_ptr<metrics::PSIMemoryParser> psi_parser_;
bool was_arc_window_active_ = false;
std::vector<int32_t> task_ids_;
bool gamepad_interaction_recorded_ = false;
base::ObserverList<AppKillObserver> app_kill_observers_;
base::ObserverList<UserInteractionObserver> user_interaction_observers_;
base::ObserverList<BootTypeObserver> boot_type_observers_;
raw_ptr<PrefService> prefs_ = nullptr;
std::unique_ptr<ArcMetricsAnr> metrics_anr_;
// Tracks window management related metrics.
std::unique_ptr<ArcWmMetrics> arc_wm_metrics_;
// For reporting Arc.Provisioning.PreSignInTimeDelta.
std::optional<base::TimeTicks> arc_provisioning_start_time_;
std::optional<std::string> arc_provisioning_account_type_suffix_;
// Load average values returned by sysinfo() after ARC start.
// Maps from the index of the value to the value itself.
std::map<size_t, int> load_averages_after_arc_start_;
mojom::BootType boot_type_ = mojom::BootType::UNKNOWN;
// Always keep this the last member of this class to make sure it's the
// first thing to be destructed.
base::WeakPtrFactory<ArcMetricsService> weak_ptr_factory_{this};
};
// Singleton factory for ArcMetricsService.
class ArcMetricsServiceFactory
: public internal::ArcBrowserContextKeyedServiceFactoryBase<
ArcMetricsService,
ArcMetricsServiceFactory> {
public:
// Factory name used by ArcBrowserContextKeyedServiceFactoryBase.
static constexpr const char* kName = "ArcMetricsServiceFactory";
static ArcMetricsServiceFactory* GetInstance();
private:
friend base::DefaultSingletonTraits<ArcMetricsServiceFactory>;
ArcMetricsServiceFactory() = default;
~ArcMetricsServiceFactory() override = default;
};
} // namespace arc
#endif // ASH_COMPONENTS_ARC_METRICS_ARC_METRICS_SERVICE_H_