blob: f213ca48fd6989635b84b6aeb6e27eee3c7b35e6 [file] [log] [blame]
[email protected]c9afed6e2014-02-03 22:12:291// Copyright 2014 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
[email protected]8304f61a2014-05-24 12:17:335#include "chrome/browser/metrics/chromeos_metrics_provider.h"
[email protected]c9afed6e2014-02-03 22:12:296
avi6846aef2015-12-26 01:09:387#include <stddef.h>
8
Steven Holte915c99f2017-07-21 23:34:319#include "base/barrier_closure.h"
sque82e4d1552016-02-26 22:47:1910#include "base/feature_list.h"
asvitkine776f9db2017-01-25 21:39:2911#include "base/metrics/histogram_macros.h"
[email protected]c9afed6e2014-02-03 22:12:2912#include "base/strings/string_number_conversions.h"
13#include "base/strings/string_util.h"
14#include "base/strings/utf_string_conversions.h"
isherman904f82f2017-06-30 18:36:2915#include "base/task_scheduler/post_task.h"
16#include "base/task_scheduler/task_traits.h"
[email protected]8304f61a2014-05-24 12:17:3317#include "chrome/browser/browser_process.h"
hidehiko5d944082016-11-18 06:16:0418#include "chrome/browser/chromeos/arc/arc_session_manager.h"
kaznacheev9ec12512015-03-11 21:49:3719#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
sque82e4d1552016-02-26 22:47:1920#include "chrome/common/chrome_features.h"
[email protected]c9afed6e2014-02-03 22:12:2921#include "chrome/common/pref_names.h"
[email protected]51994b22014-05-30 13:24:2122#include "chromeos/system/statistics_provider.h"
sque82e4d1552016-02-26 22:47:1923#include "components/metrics/leak_detector/leak_detector.h"
[email protected]d6147bd2014-06-11 01:58:1924#include "components/metrics/metrics_service.h"
brettwb1fc1b82016-02-02 00:19:0825#include "components/prefs/pref_registry_simple.h"
26#include "components/prefs/pref_service.h"
[email protected]4d390782014-08-15 09:22:5827#include "components/user_manager/user_manager.h"
[email protected]c9afed6e2014-02-03 22:12:2928#include "device/bluetooth/bluetooth_adapter.h"
29#include "device/bluetooth/bluetooth_adapter_factory.h"
30#include "device/bluetooth/bluetooth_device.h"
Steven Holtef9d5ed62017-10-21 02:02:3031#include "third_party/metrics_proto/chrome_user_metrics_extension.pb.h"
oshimad5c972e2016-04-28 23:17:1432#include "ui/display/display.h"
[email protected]86203922014-02-07 08:10:1033#include "ui/events/event_utils.h"
[email protected]c9afed6e2014-02-03 22:12:2934
[email protected]c9afed6e2014-02-03 22:12:2935using metrics::ChromeUserMetricsExtension;
[email protected]dbd4e6092014-05-31 01:04:2136using metrics::SampledProfile;
[email protected]c9afed6e2014-02-03 22:12:2937using metrics::SystemProfileProto;
38typedef SystemProfileProto::Hardware::Bluetooth::PairedDevice PairedDevice;
39
[email protected]86203922014-02-07 08:10:1040namespace {
41
[email protected]c9afed6e2014-02-03 22:12:2942PairedDevice::Type AsBluetoothDeviceType(
fukino6da34d62016-10-05 23:03:1343 device::BluetoothDeviceType device_type) {
[email protected]c9afed6e2014-02-03 22:12:2944 switch (device_type) {
fukino6da34d62016-10-05 23:03:1345 case device::BluetoothDeviceType::UNKNOWN:
[email protected]c9afed6e2014-02-03 22:12:2946 return PairedDevice::DEVICE_UNKNOWN;
fukino6da34d62016-10-05 23:03:1347 case device::BluetoothDeviceType::COMPUTER:
[email protected]c9afed6e2014-02-03 22:12:2948 return PairedDevice::DEVICE_COMPUTER;
fukino6da34d62016-10-05 23:03:1349 case device::BluetoothDeviceType::PHONE:
[email protected]c9afed6e2014-02-03 22:12:2950 return PairedDevice::DEVICE_PHONE;
fukino6da34d62016-10-05 23:03:1351 case device::BluetoothDeviceType::MODEM:
[email protected]c9afed6e2014-02-03 22:12:2952 return PairedDevice::DEVICE_MODEM;
fukino6da34d62016-10-05 23:03:1353 case device::BluetoothDeviceType::AUDIO:
[email protected]c9afed6e2014-02-03 22:12:2954 return PairedDevice::DEVICE_AUDIO;
fukino6da34d62016-10-05 23:03:1355 case device::BluetoothDeviceType::CAR_AUDIO:
[email protected]c9afed6e2014-02-03 22:12:2956 return PairedDevice::DEVICE_CAR_AUDIO;
fukino6da34d62016-10-05 23:03:1357 case device::BluetoothDeviceType::VIDEO:
[email protected]c9afed6e2014-02-03 22:12:2958 return PairedDevice::DEVICE_VIDEO;
fukino6da34d62016-10-05 23:03:1359 case device::BluetoothDeviceType::PERIPHERAL:
[email protected]c9afed6e2014-02-03 22:12:2960 return PairedDevice::DEVICE_PERIPHERAL;
fukino6da34d62016-10-05 23:03:1361 case device::BluetoothDeviceType::JOYSTICK:
[email protected]c9afed6e2014-02-03 22:12:2962 return PairedDevice::DEVICE_JOYSTICK;
fukino6da34d62016-10-05 23:03:1363 case device::BluetoothDeviceType::GAMEPAD:
[email protected]c9afed6e2014-02-03 22:12:2964 return PairedDevice::DEVICE_GAMEPAD;
fukino6da34d62016-10-05 23:03:1365 case device::BluetoothDeviceType::KEYBOARD:
[email protected]c9afed6e2014-02-03 22:12:2966 return PairedDevice::DEVICE_KEYBOARD;
fukino6da34d62016-10-05 23:03:1367 case device::BluetoothDeviceType::MOUSE:
[email protected]c9afed6e2014-02-03 22:12:2968 return PairedDevice::DEVICE_MOUSE;
fukino6da34d62016-10-05 23:03:1369 case device::BluetoothDeviceType::TABLET:
[email protected]c9afed6e2014-02-03 22:12:2970 return PairedDevice::DEVICE_TABLET;
fukino6da34d62016-10-05 23:03:1371 case device::BluetoothDeviceType::KEYBOARD_MOUSE_COMBO:
[email protected]c9afed6e2014-02-03 22:12:2972 return PairedDevice::DEVICE_KEYBOARD_MOUSE_COMBO;
73 }
74
75 NOTREACHED();
76 return PairedDevice::DEVICE_UNKNOWN;
77}
78
[email protected]8304f61a2014-05-24 12:17:3379void IncrementPrefValue(const char* path) {
80 PrefService* pref = g_browser_process->local_state();
81 DCHECK(pref);
82 int value = pref->GetInteger(path);
83 pref->SetInteger(path, value + 1);
84}
85
Steven Holteb7f8139b2017-08-08 20:00:2186// Called on a background thread to load hardware class information.
87std::string GetHardwareClassOnBackgroundThread() {
Steven Holteb7f8139b2017-08-08 20:00:2188 std::string hardware_class;
89 chromeos::system::StatisticsProvider::GetInstance()->GetMachineStatistic(
90 "hardware_class", &hardware_class);
91 return hardware_class;
92}
93
[email protected]86203922014-02-07 08:10:1094} // namespace
95
[email protected]8304f61a2014-05-24 12:17:3396ChromeOSMetricsProvider::ChromeOSMetricsProvider()
97 : registered_user_count_at_log_initialization_(false),
[email protected]51994b22014-05-30 13:24:2198 user_count_at_log_initialization_(0),
99 weak_ptr_factory_(this) {
[email protected]c9afed6e2014-02-03 22:12:29100}
101
[email protected]8304f61a2014-05-24 12:17:33102ChromeOSMetricsProvider::~ChromeOSMetricsProvider() {
[email protected]c9afed6e2014-02-03 22:12:29103}
104
[email protected]8304f61a2014-05-24 12:17:33105// static
106void ChromeOSMetricsProvider::RegisterPrefs(PrefRegistrySimple* registry) {
107 registry->RegisterIntegerPref(prefs::kStabilityOtherUserCrashCount, 0);
108 registry->RegisterIntegerPref(prefs::kStabilityKernelCrashCount, 0);
109 registry->RegisterIntegerPref(prefs::kStabilitySystemUncleanShutdownCount, 0);
110}
111
112// static
113void ChromeOSMetricsProvider::LogCrash(const std::string& crash_type) {
114 if (crash_type == "user")
115 IncrementPrefValue(prefs::kStabilityOtherUserCrashCount);
116 else if (crash_type == "kernel")
117 IncrementPrefValue(prefs::kStabilityKernelCrashCount);
118 else if (crash_type == "uncleanshutdown")
119 IncrementPrefValue(prefs::kStabilitySystemUncleanShutdownCount);
120 else
121 NOTREACHED() << "Unexpected Chrome OS crash type " << crash_type;
122
123 // Wake up metrics logs sending if necessary now that new
124 // log data is available.
125 g_browser_process->metrics_service()->OnApplicationNotIdle();
126}
127
glevina7154d152015-11-04 14:28:43128ChromeOSMetricsProvider::EnrollmentStatus
129ChromeOSMetricsProvider::GetEnrollmentStatus() {
130 policy::BrowserPolicyConnectorChromeOS* connector =
131 g_browser_process->platform_part()->browser_policy_connector_chromeos();
132 if (!connector)
133 return ERROR_GETTING_ENROLLMENT_STATUS;
134
135 return connector->IsEnterpriseManaged() ? MANAGED : NON_MANAGED;
136}
137
dhsharpb0073a22016-02-18 21:54:09138void ChromeOSMetricsProvider::Init() {
139 perf_provider_.Init();
sque82e4d1552016-02-26 22:47:19140
sque961ce9c2016-04-21 04:42:55141#if defined(ARCH_CPU_X86_64)
142 // Currently, the runtime memory leak detector is only supported on x86_64
143 // systems.
sque82e4d1552016-02-26 22:47:19144 if (base::FeatureList::IsEnabled(features::kRuntimeMemoryLeakDetector)) {
145 leak_detector_controller_.reset(new metrics::LeakDetectorController);
146 }
sque961ce9c2016-04-21 04:42:55147#endif
dhsharpb0073a22016-02-18 21:54:09148}
149
Steven Holte915c99f2017-07-21 23:34:31150void ChromeOSMetricsProvider::AsyncInit(const base::Closure& done_callback) {
151 base::Closure barrier = base::BarrierClosure(2, done_callback);
152 InitTaskGetHardwareClass(barrier);
153 InitTaskGetBluetoothAdapter(barrier);
154}
155
[email protected]8304f61a2014-05-24 12:17:33156void ChromeOSMetricsProvider::OnDidCreateMetricsLog() {
157 registered_user_count_at_log_initialization_ = false;
[email protected]4d390782014-08-15 09:22:58158 if (user_manager::UserManager::IsInitialized()) {
[email protected]8304f61a2014-05-24 12:17:33159 registered_user_count_at_log_initialization_ = true;
160 user_count_at_log_initialization_ =
[email protected]4d390782014-08-15 09:22:58161 user_manager::UserManager::Get()->GetLoggedInUsers().size();
[email protected]8304f61a2014-05-24 12:17:33162 }
163}
164
[email protected]51994b22014-05-30 13:24:21165void ChromeOSMetricsProvider::InitTaskGetHardwareClass(
166 const base::Closure& callback) {
isherman904f82f2017-06-30 18:36:29167 // Run the (potentially expensive) task in the background to avoid blocking
[email protected]51994b22014-05-30 13:24:21168 // the UI thread.
Steven Holteb7f8139b2017-08-08 20:00:21169 base::PostTaskWithTraitsAndReplyWithResult(
[email protected]51994b22014-05-30 13:24:21170 FROM_HERE,
Ilya Shermanf97af9d2017-07-20 20:16:23171 {base::MayBlock(), base::WithBaseSyncPrimitives(),
172 base::TaskPriority::BACKGROUND,
isherman904f82f2017-06-30 18:36:29173 base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
Steven Holteb7f8139b2017-08-08 20:00:21174 base::BindOnce(&GetHardwareClassOnBackgroundThread),
175 base::BindOnce(&ChromeOSMetricsProvider::SetHardwareClass,
176 weak_ptr_factory_.GetWeakPtr(), callback));
[email protected]51994b22014-05-30 13:24:21177}
178
ortuno4958ca4f2016-02-26 02:15:43179void ChromeOSMetricsProvider::InitTaskGetBluetoothAdapter(
180 const base::Closure& callback) {
181 device::BluetoothAdapterFactory::GetAdapter(
182 base::Bind(&ChromeOSMetricsProvider::SetBluetoothAdapter,
183 weak_ptr_factory_.GetWeakPtr(), callback));
184}
185
[email protected]8304f61a2014-05-24 12:17:33186void ChromeOSMetricsProvider::ProvideSystemProfileMetrics(
187 metrics::SystemProfileProto* system_profile_proto) {
[email protected]8304f61a2014-05-24 12:17:33188 WriteBluetoothProto(system_profile_proto);
189 UpdateMultiProfileUserCount(system_profile_proto);
[email protected]86203922014-02-07 08:10:10190
[email protected]8304f61a2014-05-24 12:17:33191 metrics::SystemProfileProto::Hardware* hardware =
192 system_profile_proto->mutable_hardware();
[email protected]51994b22014-05-30 13:24:21193 hardware->set_hardware_class(hardware_class_);
oshimad5c972e2016-04-28 23:17:14194 display::Display::TouchSupport has_touch =
195 ui::GetInternalDisplayTouchSupport();
196 if (has_touch == display::Display::TOUCH_SUPPORT_AVAILABLE)
[email protected]86203922014-02-07 08:10:10197 hardware->set_internal_display_supports_touch(true);
oshimad5c972e2016-04-28 23:17:14198 else if (has_touch == display::Display::TOUCH_SUPPORT_UNAVAILABLE)
[email protected]86203922014-02-07 08:10:10199 hardware->set_internal_display_supports_touch(false);
[email protected]c9afed6e2014-02-03 22:12:29200}
201
[email protected]8304f61a2014-05-24 12:17:33202void ChromeOSMetricsProvider::ProvideStabilityMetrics(
203 metrics::SystemProfileProto* system_profile_proto) {
204 metrics::SystemProfileProto::Stability* stability_proto =
205 system_profile_proto->mutable_stability();
206 PrefService* pref = g_browser_process->local_state();
[email protected]c9afed6e2014-02-03 22:12:29207 int count = pref->GetInteger(prefs::kStabilityOtherUserCrashCount);
208 if (count) {
[email protected]8304f61a2014-05-24 12:17:33209 stability_proto->set_other_user_crash_count(count);
[email protected]c9afed6e2014-02-03 22:12:29210 pref->SetInteger(prefs::kStabilityOtherUserCrashCount, 0);
211 }
212
213 count = pref->GetInteger(prefs::kStabilityKernelCrashCount);
214 if (count) {
[email protected]8304f61a2014-05-24 12:17:33215 stability_proto->set_kernel_crash_count(count);
[email protected]c9afed6e2014-02-03 22:12:29216 pref->SetInteger(prefs::kStabilityKernelCrashCount, 0);
217 }
218
219 count = pref->GetInteger(prefs::kStabilitySystemUncleanShutdownCount);
220 if (count) {
[email protected]8304f61a2014-05-24 12:17:33221 stability_proto->set_unclean_system_shutdown_count(count);
[email protected]c9afed6e2014-02-03 22:12:29222 pref->SetInteger(prefs::kStabilitySystemUncleanShutdownCount, 0);
223 }
224}
225
Steven Holte141462ac2017-07-26 01:35:07226void ChromeOSMetricsProvider::ProvidePreviousSessionData(
[email protected]a00d4132014-05-29 20:16:25227 metrics::ChromeUserMetricsExtension* uma_proto) {
Steven Holte141462ac2017-07-26 01:35:07228 ProvideStabilityMetrics(uma_proto->mutable_system_profile());
Mark Pearson25a36bd2017-09-14 22:39:15229 // The enrollment status and ARC state of a client are not likely to change
230 // between browser restarts. Hence, it's safe and useful to attach these
231 // values to a previous session log.
232 RecordEnrollmentStatus();
233 RecordArcState();
Steven Holte141462ac2017-07-26 01:35:07234}
235
236void ChromeOSMetricsProvider::ProvideCurrentSessionData(
237 metrics::ChromeUserMetricsExtension* uma_proto) {
238 ProvideStabilityMetrics(uma_proto->mutable_system_profile());
[email protected]dbd4e6092014-05-31 01:04:21239 std::vector<SampledProfile> sampled_profiles;
240 if (perf_provider_.GetSampledProfiles(&sampled_profiles)) {
squeae77ab62016-04-20 07:54:01241 for (auto& profile : sampled_profiles) {
242 uma_proto->add_sampled_profile()->Swap(&profile);
[email protected]a00d4132014-05-29 20:16:25243 }
244 }
squeae77ab62016-04-20 07:54:01245
246 if (leak_detector_controller_) {
247 std::vector<metrics::MemoryLeakReportProto> reports;
248 leak_detector_controller_->GetLeakReports(&reports);
249 for (auto& report : reports) {
250 uma_proto->add_memory_leak_report()->Swap(&report);
251 }
252 }
253
kaznacheev9ec12512015-03-11 21:49:37254 RecordEnrollmentStatus();
elijahtaylord88371f22016-11-05 00:07:18255 RecordArcState();
[email protected]a00d4132014-05-29 20:16:25256}
257
[email protected]8304f61a2014-05-24 12:17:33258void ChromeOSMetricsProvider::WriteBluetoothProto(
259 metrics::SystemProfileProto* system_profile_proto) {
260 metrics::SystemProfileProto::Hardware* hardware =
261 system_profile_proto->mutable_hardware();
[email protected]c9afed6e2014-02-03 22:12:29262
[email protected]c9afed6e2014-02-03 22:12:29263 SystemProfileProto::Hardware::Bluetooth* bluetooth =
264 hardware->mutable_bluetooth();
265
266 bluetooth->set_is_present(adapter_->IsPresent());
267 bluetooth->set_is_enabled(adapter_->IsPowered());
268
269 device::BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
[email protected]8304f61a2014-05-24 12:17:33270 for (device::BluetoothAdapter::DeviceList::iterator iter = devices.begin();
271 iter != devices.end();
272 ++iter) {
[email protected]c9afed6e2014-02-03 22:12:29273 device::BluetoothDevice* device = *iter;
[email protected]c81543192014-03-11 22:44:48274 // Don't collect information about LE devices yet.
275 if (!device->IsPaired())
276 continue;
277
278 PairedDevice* paired_device = bluetooth->add_paired_device();
[email protected]c9afed6e2014-02-03 22:12:29279 paired_device->set_bluetooth_class(device->GetBluetoothClass());
280 paired_device->set_type(AsBluetoothDeviceType(device->GetDeviceType()));
281
282 // |address| is xx:xx:xx:xx:xx:xx, extract the first three components and
avi6846aef2015-12-26 01:09:38283 // pack into a uint32_t.
[email protected]c9afed6e2014-02-03 22:12:29284 std::string address = device->GetAddress();
[email protected]8304f61a2014-05-24 12:17:33285 if (address.size() > 9 && address[2] == ':' && address[5] == ':' &&
286 address[8] == ':') {
[email protected]c9afed6e2014-02-03 22:12:29287 std::string vendor_prefix_str;
avi6846aef2015-12-26 01:09:38288 uint64_t vendor_prefix;
[email protected]c9afed6e2014-02-03 22:12:29289
290 base::RemoveChars(address.substr(0, 9), ":", &vendor_prefix_str);
291 DCHECK_EQ(6U, vendor_prefix_str.size());
292 base::HexStringToUInt64(vendor_prefix_str, &vendor_prefix);
293
294 paired_device->set_vendor_prefix(vendor_prefix);
295 }
296
[email protected]c81543192014-03-11 22:44:48297 switch (device->GetVendorIDSource()) {
298 case device::BluetoothDevice::VENDOR_ID_BLUETOOTH:
299 paired_device->set_vendor_id_source(PairedDevice::VENDOR_ID_BLUETOOTH);
300 break;
301 case device::BluetoothDevice::VENDOR_ID_USB:
302 paired_device->set_vendor_id_source(PairedDevice::VENDOR_ID_USB);
303 break;
304 default:
305 paired_device->set_vendor_id_source(PairedDevice::VENDOR_ID_UNKNOWN);
306 }
307
[email protected]c9afed6e2014-02-03 22:12:29308 paired_device->set_vendor_id(device->GetVendorID());
309 paired_device->set_product_id(device->GetProductID());
310 paired_device->set_device_id(device->GetDeviceID());
311 }
312}
313
[email protected]8304f61a2014-05-24 12:17:33314void ChromeOSMetricsProvider::UpdateMultiProfileUserCount(
315 metrics::SystemProfileProto* system_profile_proto) {
[email protected]4d390782014-08-15 09:22:58316 if (user_manager::UserManager::IsInitialized()) {
317 size_t user_count =
318 user_manager::UserManager::Get()->GetLoggedInUsers().size();
[email protected]c9afed6e2014-02-03 22:12:29319
320 // We invalidate the user count if it changed while the log was open.
[email protected]8304f61a2014-05-24 12:17:33321 if (registered_user_count_at_log_initialization_ &&
322 user_count != user_count_at_log_initialization_) {
[email protected]c9afed6e2014-02-03 22:12:29323 user_count = 0;
324 }
325
[email protected]8304f61a2014-05-24 12:17:33326 system_profile_proto->set_multi_profile_user_count(user_count);
[email protected]c9afed6e2014-02-03 22:12:29327 }
328}
329
[email protected]8304f61a2014-05-24 12:17:33330void ChromeOSMetricsProvider::SetBluetoothAdapter(
ortuno4958ca4f2016-02-26 02:15:43331 base::Closure callback,
[email protected]c9afed6e2014-02-03 22:12:29332 scoped_refptr<device::BluetoothAdapter> adapter) {
333 adapter_ = adapter;
ortuno4958ca4f2016-02-26 02:15:43334 callback.Run();
[email protected]c9afed6e2014-02-03 22:12:29335}
kaznacheev9ec12512015-03-11 21:49:37336
Steven Holteb7f8139b2017-08-08 20:00:21337void ChromeOSMetricsProvider::SetHardwareClass(base::Closure callback,
338 std::string hardware_class) {
339 hardware_class_ = hardware_class;
340 callback.Run();
341}
342
kaznacheev9ec12512015-03-11 21:49:37343void ChromeOSMetricsProvider::RecordEnrollmentStatus() {
Mark Pearson25a36bd2017-09-14 22:39:15344 UMA_STABILITY_HISTOGRAM_ENUMERATION(
kaznacheev9ec12512015-03-11 21:49:37345 "UMA.EnrollmentStatus", GetEnrollmentStatus(), ENROLLMENT_STATUS_MAX);
346}
elijahtaylord88371f22016-11-05 00:07:18347
348void ChromeOSMetricsProvider::RecordArcState() {
hidehiko5d944082016-11-18 06:16:04349 arc::ArcSessionManager* arc_session_manager = arc::ArcSessionManager::Get();
350 if (arc_session_manager)
351 arc_session_manager->RecordArcState();
elijahtaylord88371f22016-11-05 00:07:18352}