[M73 Dev][EFL] Disable VizDisplayCompositor for EFL port
[platform/framework/web/chromium-efl.git] / components / ukm / ukm_service.cc
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/ukm/ukm_service.h"
6
7 #include <memory>
8 #include <string>
9 #include <utility>
10
11 #include "base/bind.h"
12 #include "base/feature_list.h"
13 #include "base/metrics/field_trial.h"
14 #include "base/metrics/field_trial_params.h"
15 #include "base/metrics/histogram_macros.h"
16 #include "base/rand_util.h"
17 #include "base/threading/sequenced_task_runner_handle.h"
18 #include "base/time/time.h"
19 #include "components/metrics/metrics_log.h"
20 #include "components/metrics/metrics_service_client.h"
21 #include "components/prefs/pref_registry_simple.h"
22 #include "components/prefs/pref_service.h"
23 #include "components/ukm/persisted_logs_metrics_impl.h"
24 #include "components/ukm/ukm_pref_names.h"
25 #include "components/ukm/ukm_rotation_scheduler.h"
26 #include "services/metrics/public/cpp/delegating_ukm_recorder.h"
27 #include "third_party/metrics_proto/ukm/report.pb.h"
28
29 namespace ukm {
30
31 namespace {
32
33 // Generates a new client id and stores it in prefs.
34 uint64_t GenerateAndStoreClientId(PrefService* pref_service) {
35   uint64_t client_id = 0;
36   while (!client_id)
37     client_id = base::RandUint64();
38   pref_service->SetInt64(prefs::kUkmClientId, client_id);
39
40   // Also reset the session id counter.
41   pref_service->SetInteger(prefs::kUkmSessionId, 0);
42   return client_id;
43 }
44
45 uint64_t LoadOrGenerateAndStoreClientId(PrefService* pref_service) {
46   uint64_t client_id = pref_service->GetInt64(prefs::kUkmClientId);
47   if (!client_id)
48     client_id = GenerateAndStoreClientId(pref_service);
49   return client_id;
50 }
51
52 int32_t LoadAndIncrementSessionId(PrefService* pref_service) {
53   int32_t session_id = pref_service->GetInteger(prefs::kUkmSessionId);
54   ++session_id;  // Increment session id, once per session.
55   pref_service->SetInteger(prefs::kUkmSessionId, session_id);
56   return session_id;
57 }
58
59 }  // namespace
60
61 UkmService::UkmService(PrefService* pref_service,
62                        metrics::MetricsServiceClient* client,
63                        bool restrict_to_whitelist_entries)
64     : pref_service_(pref_service),
65       restrict_to_whitelist_entries_(restrict_to_whitelist_entries),
66       client_id_(0),
67       session_id_(0),
68       report_count_(0),
69       client_(client),
70       reporting_service_(client, pref_service),
71       initialize_started_(false),
72       initialize_complete_(false),
73       self_ptr_factory_(this) {
74   DCHECK(pref_service_);
75   DCHECK(client_);
76   DVLOG(1) << "UkmService::Constructor";
77
78   reporting_service_.Initialize();
79
80   base::Closure rotate_callback =
81       base::Bind(&UkmService::RotateLog, self_ptr_factory_.GetWeakPtr());
82   // MetricsServiceClient outlives UkmService, and
83   // MetricsReportingScheduler is tied to the lifetime of |this|.
84   const base::Callback<base::TimeDelta(void)>& get_upload_interval_callback =
85       base::Bind(&metrics::MetricsServiceClient::GetStandardUploadInterval,
86                  base::Unretained(client_));
87   scheduler_.reset(new ukm::UkmRotationScheduler(rotate_callback,
88                                                  get_upload_interval_callback));
89
90   StoreWhitelistedEntries();
91
92   DelegatingUkmRecorder::Get()->AddDelegate(self_ptr_factory_.GetWeakPtr());
93 }
94
95 UkmService::~UkmService() {
96   DisableReporting();
97   DelegatingUkmRecorder::Get()->RemoveDelegate(this);
98 }
99
100 void UkmService::Initialize() {
101   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
102   DCHECK(!initialize_started_);
103   DVLOG(1) << "UkmService::Initialize";
104   initialize_started_ = true;
105
106   DCHECK_EQ(0, report_count_);
107   client_id_ = LoadOrGenerateAndStoreClientId(pref_service_);
108   session_id_ = LoadAndIncrementSessionId(pref_service_);
109   metrics_providers_.Init();
110
111   StartInitTask();
112 }
113
114 void UkmService::EnableReporting() {
115   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
116   DVLOG(1) << "UkmService::EnableReporting";
117   if (reporting_service_.reporting_active())
118     return;
119
120   metrics_providers_.OnRecordingEnabled();
121
122   if (!initialize_started_)
123     Initialize();
124   scheduler_->Start();
125   reporting_service_.EnableReporting();
126 }
127
128 void UkmService::DisableReporting() {
129   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
130   DVLOG(1) << "UkmService::DisableReporting";
131
132   reporting_service_.DisableReporting();
133
134   metrics_providers_.OnRecordingDisabled();
135
136   scheduler_->Stop();
137   Flush();
138 }
139
140 #if defined(OS_ANDROID) || defined(OS_IOS)
141 void UkmService::OnAppEnterForeground() {
142   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
143   DVLOG(1) << "UkmService::OnAppEnterForeground";
144
145   // If initialize_started_ is false, UKM has not yet been started, so bail. The
146   // scheduler will instead be started via EnableReporting().
147   if (!initialize_started_)
148     return;
149
150   scheduler_->Start();
151 }
152
153 void UkmService::OnAppEnterBackground() {
154   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
155   DVLOG(1) << "UkmService::OnAppEnterBackground";
156
157   if (!initialize_started_)
158     return;
159
160   scheduler_->Stop();
161
162   // Give providers a chance to persist ukm data as part of being backgrounded.
163   metrics_providers_.OnAppEnterBackground();
164
165   Flush();
166 }
167 #endif
168
169 void UkmService::Flush() {
170   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
171   if (initialize_complete_)
172     BuildAndStoreLog();
173   reporting_service_.ukm_log_store()->PersistUnsentLogs();
174 }
175
176 void UkmService::Purge() {
177   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
178   DVLOG(1) << "UkmService::Purge";
179   reporting_service_.ukm_log_store()->Purge();
180   UkmRecorderImpl::Purge();
181 }
182
183 void UkmService::ResetClientState(ResetReason reason) {
184   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
185
186   UMA_HISTOGRAM_ENUMERATION("UKM.ResetReason", reason);
187
188   client_id_ = GenerateAndStoreClientId(pref_service_);
189   // Note: the session_id has already been cleared by GenerateAndStoreClientId.
190   session_id_ = LoadAndIncrementSessionId(pref_service_);
191   report_count_ = 0;
192 }
193
194 void UkmService::RegisterMetricsProvider(
195     std::unique_ptr<metrics::MetricsProvider> provider) {
196   metrics_providers_.RegisterMetricsProvider(std::move(provider));
197 }
198
199 // static
200 void UkmService::RegisterPrefs(PrefRegistrySimple* registry) {
201   registry->RegisterInt64Pref(prefs::kUkmClientId, 0);
202   registry->RegisterIntegerPref(prefs::kUkmSessionId, 0);
203   UkmReportingService::RegisterPrefs(registry);
204 }
205
206 void UkmService::StartInitTask() {
207   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
208   DVLOG(1) << "UkmService::StartInitTask";
209   metrics_providers_.AsyncInit(base::Bind(&UkmService::FinishedInitTask,
210                                           self_ptr_factory_.GetWeakPtr()));
211 }
212
213 void UkmService::FinishedInitTask() {
214   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
215   DVLOG(1) << "UkmService::FinishedInitTask";
216   initialize_complete_ = true;
217   scheduler_->InitTaskComplete();
218 }
219
220 void UkmService::RotateLog() {
221   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
222   DVLOG(1) << "UkmService::RotateLog";
223   if (!reporting_service_.ukm_log_store()->has_unsent_logs())
224     BuildAndStoreLog();
225   reporting_service_.Start();
226   scheduler_->RotationFinished();
227 }
228
229 void UkmService::BuildAndStoreLog() {
230   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
231   DVLOG(1) << "UkmService::BuildAndStoreLog";
232
233   // Suppress generating a log if we have no new data to include.
234   bool empty = sources().empty() && entries().empty();
235   UMA_HISTOGRAM_BOOLEAN("UKM.BuildAndStoreLogIsEmpty", empty);
236   if (empty)
237     return;
238
239   Report report;
240   report.set_client_id(client_id_);
241   report.set_session_id(session_id_);
242   report.set_report_id(++report_count_);
243
244   StoreRecordingsInReport(&report);
245
246   metrics::MetricsLog::RecordCoreSystemProfile(client_,
247                                                report.mutable_system_profile());
248
249   metrics_providers_.ProvideSystemProfileMetrics(
250       report.mutable_system_profile());
251
252   std::string serialized_log;
253   report.SerializeToString(&serialized_log);
254   reporting_service_.ukm_log_store()->StoreLog(serialized_log);
255 }
256
257 bool UkmService::ShouldRestrictToWhitelistedEntries() const {
258   return restrict_to_whitelist_entries_;
259 }
260
261 }  // namespace ukm