15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/metrics/chromeos_metrics_provider.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/prefs/pref_registry_simple.h"
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/prefs/pref_service.h"
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/string_util.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/browser_process.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/common/pref_names.h"
14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chromeos/system/statistics_provider.h"
15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "components/metrics/metrics_service.h"
16010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "components/metrics/proto/chrome_user_metrics_extension.pb.h"
176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "components/user_manager/user_manager.h"
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "device/bluetooth/bluetooth_adapter.h"
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "device/bluetooth/bluetooth_adapter_factory.h"
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "device/bluetooth/bluetooth_device.h"
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/events/event_utils.h"
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/gfx/screen.h"
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
25c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#if defined(USE_X11)
26c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ui/events/x/touch_factory_x11.h"
27c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#endif  // defined(USE_X11)
28c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using metrics::ChromeUserMetricsExtension;
3046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)using metrics::SampledProfile;
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using metrics::SystemProfileProto;
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)typedef SystemProfileProto::Hardware::Bluetooth::PairedDevice PairedDevice;
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PairedDevice::Type AsBluetoothDeviceType(
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    device::BluetoothDevice::DeviceType device_type) {
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  switch (device_type) {
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case device::BluetoothDevice::DEVICE_UNKNOWN:
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return PairedDevice::DEVICE_UNKNOWN;
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case device::BluetoothDevice::DEVICE_COMPUTER:
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return PairedDevice::DEVICE_COMPUTER;
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case device::BluetoothDevice::DEVICE_PHONE:
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return PairedDevice::DEVICE_PHONE;
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case device::BluetoothDevice::DEVICE_MODEM:
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return PairedDevice::DEVICE_MODEM;
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case device::BluetoothDevice::DEVICE_AUDIO:
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return PairedDevice::DEVICE_AUDIO;
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case device::BluetoothDevice::DEVICE_CAR_AUDIO:
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return PairedDevice::DEVICE_CAR_AUDIO;
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case device::BluetoothDevice::DEVICE_VIDEO:
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return PairedDevice::DEVICE_VIDEO;
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case device::BluetoothDevice::DEVICE_PERIPHERAL:
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return PairedDevice::DEVICE_PERIPHERAL;
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case device::BluetoothDevice::DEVICE_JOYSTICK:
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return PairedDevice::DEVICE_JOYSTICK;
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case device::BluetoothDevice::DEVICE_GAMEPAD:
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return PairedDevice::DEVICE_GAMEPAD;
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case device::BluetoothDevice::DEVICE_KEYBOARD:
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return PairedDevice::DEVICE_KEYBOARD;
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case device::BluetoothDevice::DEVICE_MOUSE:
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return PairedDevice::DEVICE_MOUSE;
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case device::BluetoothDevice::DEVICE_TABLET:
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return PairedDevice::DEVICE_TABLET;
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case device::BluetoothDevice::DEVICE_KEYBOARD_MOUSE_COMBO:
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return PairedDevice::DEVICE_KEYBOARD_MOUSE_COMBO;
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NOTREACHED();
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return PairedDevice::DEVICE_UNKNOWN;
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WriteExternalTouchscreensProto(SystemProfileProto::Hardware* hardware) {
74c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#if defined(USE_X11)
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::set<std::pair<int, int> > touchscreen_ids =
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ui::TouchFactory::GetInstance()->GetTouchscreenIds();
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (std::set<std::pair<int, int> >::iterator it = touchscreen_ids.begin();
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       it != touchscreen_ids.end();
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       ++it) {
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SystemProfileProto::Hardware::TouchScreen* touchscreen =
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        hardware->add_external_touchscreen();
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    touchscreen->set_vendor_id(it->first);
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    touchscreen->set_product_id(it->second);
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
85c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#endif  // defined(USE_X11)
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void IncrementPrefValue(const char* path) {
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  PrefService* pref = g_browser_process->local_state();
90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(pref);
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int value = pref->GetInteger(path);
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  pref->SetInteger(path, value + 1);
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ChromeOSMetricsProvider::ChromeOSMetricsProvider()
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : registered_user_count_at_log_initialization_(false),
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      user_count_at_log_initialization_(0),
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      weak_ptr_factory_(this) {
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ChromeOSMetricsProvider::~ChromeOSMetricsProvider() {
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ChromeOSMetricsProvider::RegisterPrefs(PrefRegistrySimple* registry) {
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  registry->RegisterIntegerPref(prefs::kStabilityOtherUserCrashCount, 0);
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  registry->RegisterIntegerPref(prefs::kStabilityKernelCrashCount, 0);
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  registry->RegisterIntegerPref(prefs::kStabilitySystemUncleanShutdownCount, 0);
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ChromeOSMetricsProvider::LogCrash(const std::string& crash_type) {
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (crash_type == "user")
116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    IncrementPrefValue(prefs::kStabilityOtherUserCrashCount);
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  else if (crash_type == "kernel")
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    IncrementPrefValue(prefs::kStabilityKernelCrashCount);
119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  else if (crash_type == "uncleanshutdown")
120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    IncrementPrefValue(prefs::kStabilitySystemUncleanShutdownCount);
121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  else
122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    NOTREACHED() << "Unexpected Chrome OS crash type " << crash_type;
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Wake up metrics logs sending if necessary now that new
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // log data is available.
126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  g_browser_process->metrics_service()->OnApplicationNotIdle();
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ChromeOSMetricsProvider::OnDidCreateMetricsLog() {
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  registered_user_count_at_log_initialization_ = false;
1316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (user_manager::UserManager::IsInitialized()) {
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    registered_user_count_at_log_initialization_ = true;
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    user_count_at_log_initialization_ =
1346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        user_manager::UserManager::Get()->GetLoggedInUsers().size();
135c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ChromeOSMetricsProvider::InitTaskGetHardwareClass(
139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const base::Closure& callback) {
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Run the (potentially expensive) task on the FILE thread to avoid blocking
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // the UI thread.
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  content::BrowserThread::PostTaskAndReply(
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      content::BrowserThread::FILE,
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      FROM_HERE,
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&ChromeOSMetricsProvider::InitTaskGetHardwareClassOnFileThread,
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()),
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      callback);
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ChromeOSMetricsProvider::InitTaskGetHardwareClassOnFileThread() {
151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  chromeos::system::StatisticsProvider::GetInstance()->GetMachineStatistic(
153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      "hardware_class", &hardware_class_);
154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ChromeOSMetricsProvider::ProvideSystemProfileMetrics(
157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    metrics::SystemProfileProto* system_profile_proto) {
158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  WriteBluetoothProto(system_profile_proto);
159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  UpdateMultiProfileUserCount(system_profile_proto);
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  metrics::SystemProfileProto::Hardware* hardware =
162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      system_profile_proto->mutable_hardware();
163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  hardware->set_hardware_class(hardware_class_);
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Display::TouchSupport has_touch = ui::GetInternalDisplayTouchSupport();
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (has_touch == gfx::Display::TOUCH_SUPPORT_AVAILABLE)
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    hardware->set_internal_display_supports_touch(true);
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  else if (has_touch == gfx::Display::TOUCH_SUPPORT_UNAVAILABLE)
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    hardware->set_internal_display_supports_touch(false);
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  WriteExternalTouchscreensProto(hardware);
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ChromeOSMetricsProvider::ProvideStabilityMetrics(
173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    metrics::SystemProfileProto* system_profile_proto) {
174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  metrics::SystemProfileProto::Stability* stability_proto =
175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      system_profile_proto->mutable_stability();
176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  PrefService* pref = g_browser_process->local_state();
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int count = pref->GetInteger(prefs::kStabilityOtherUserCrashCount);
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (count) {
179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    stability_proto->set_other_user_crash_count(count);
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pref->SetInteger(prefs::kStabilityOtherUserCrashCount, 0);
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  count = pref->GetInteger(prefs::kStabilityKernelCrashCount);
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (count) {
185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    stability_proto->set_kernel_crash_count(count);
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pref->SetInteger(prefs::kStabilityKernelCrashCount, 0);
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  count = pref->GetInteger(prefs::kStabilitySystemUncleanShutdownCount);
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (count) {
191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    stability_proto->set_unclean_system_shutdown_count(count);
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pref->SetInteger(prefs::kStabilitySystemUncleanShutdownCount, 0);
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ChromeOSMetricsProvider::ProvideGeneralMetrics(
197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    metrics::ChromeUserMetricsExtension* uma_proto) {
19846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  std::vector<SampledProfile> sampled_profiles;
19946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (perf_provider_.GetSampledProfiles(&sampled_profiles)) {
20046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    for (std::vector<SampledProfile>::iterator iter = sampled_profiles.begin();
20146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)         iter != sampled_profiles.end();
202cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)         ++iter) {
20346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      uma_proto->add_sampled_profile()->Swap(&(*iter));
204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ChromeOSMetricsProvider::WriteBluetoothProto(
209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    metrics::SystemProfileProto* system_profile_proto) {
210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  metrics::SystemProfileProto::Hardware* hardware =
211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      system_profile_proto->mutable_hardware();
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // BluetoothAdapterFactory::GetAdapter is synchronous on Chrome OS; if that
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // changes this will fail at the DCHECK().
215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  device::BluetoothAdapterFactory::GetAdapter(base::Bind(
216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      &ChromeOSMetricsProvider::SetBluetoothAdapter, base::Unretained(this)));
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(adapter_.get());
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SystemProfileProto::Hardware::Bluetooth* bluetooth =
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      hardware->mutable_bluetooth();
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bluetooth->set_is_present(adapter_->IsPresent());
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bluetooth->set_is_enabled(adapter_->IsPowered());
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  device::BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (device::BluetoothAdapter::DeviceList::iterator iter = devices.begin();
227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       iter != devices.end();
228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       ++iter) {
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    device::BluetoothDevice* device = *iter;
230a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Don't collect information about LE devices yet.
231a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!device->IsPaired())
232a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      continue;
233a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
234a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    PairedDevice* paired_device = bluetooth->add_paired_device();
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    paired_device->set_bluetooth_class(device->GetBluetoothClass());
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    paired_device->set_type(AsBluetoothDeviceType(device->GetDeviceType()));
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // |address| is xx:xx:xx:xx:xx:xx, extract the first three components and
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // pack into a uint32.
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::string address = device->GetAddress();
241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (address.size() > 9 && address[2] == ':' && address[5] == ':' &&
242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        address[8] == ':') {
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      std::string vendor_prefix_str;
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      uint64 vendor_prefix;
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::RemoveChars(address.substr(0, 9), ":", &vendor_prefix_str);
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DCHECK_EQ(6U, vendor_prefix_str.size());
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::HexStringToUInt64(vendor_prefix_str, &vendor_prefix);
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      paired_device->set_vendor_prefix(vendor_prefix);
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    switch (device->GetVendorIDSource()) {
254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      case device::BluetoothDevice::VENDOR_ID_BLUETOOTH:
255a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        paired_device->set_vendor_id_source(PairedDevice::VENDOR_ID_BLUETOOTH);
256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        break;
257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      case device::BluetoothDevice::VENDOR_ID_USB:
258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        paired_device->set_vendor_id_source(PairedDevice::VENDOR_ID_USB);
259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        break;
260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      default:
261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        paired_device->set_vendor_id_source(PairedDevice::VENDOR_ID_UNKNOWN);
262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
263a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    paired_device->set_vendor_id(device->GetVendorID());
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    paired_device->set_product_id(device->GetProductID());
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    paired_device->set_device_id(device->GetDeviceID());
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
270cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ChromeOSMetricsProvider::UpdateMultiProfileUserCount(
271cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    metrics::SystemProfileProto* system_profile_proto) {
2726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (user_manager::UserManager::IsInitialized()) {
2736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    size_t user_count =
2746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        user_manager::UserManager::Get()->GetLoggedInUsers().size();
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // We invalidate the user count if it changed while the log was open.
277cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (registered_user_count_at_log_initialization_ &&
278cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        user_count != user_count_at_log_initialization_) {
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      user_count = 0;
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    system_profile_proto->set_multi_profile_user_count(user_count);
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
286cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ChromeOSMetricsProvider::SetBluetoothAdapter(
2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_refptr<device::BluetoothAdapter> adapter) {
2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  adapter_ = adapter;
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
290