1// Copyright 2013 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 "chrome/browser/chromeos/device_uma.h"
6
7#include <X11/extensions/XInput.h>
8#include <X11/extensions/XInput2.h>
9
10#include "base/logging.h"
11#include "base/memory/singleton.h"
12#include "base/metrics/histogram.h"
13#include "ui/events/event_constants.h"
14#include "ui/events/event_utils.h"
15#include "ui/events/platform/platform_event_source.h"
16#include "ui/events/x/device_data_manager_x11.h"
17
18// Enum type for CrOS gesture lib UMA
19enum UMACrosGestureMetricsType{
20  // To give an estimated number of all interested events.
21  UMA_CROS_GESTURE_METRICS_ALL_EVENTS,
22  UMA_CROS_GESTURE_METRICS_NOISY_GROUND,
23  // NOTE: Add states only immediately above this line. Make sure to
24  // update the enum list in tools/metrics/histograms/histograms.xml
25  // accordingly.
26  UMA_CROS_GESTURE_METRICS_COUNT
27};
28
29namespace chromeos {
30
31DeviceUMA* DeviceUMA::GetInstance() {
32  return Singleton<DeviceUMA>::get();
33}
34
35DeviceUMA::DeviceUMA()
36    : stopped_(false) {
37  ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(this);
38}
39
40DeviceUMA::~DeviceUMA() {
41  Stop();
42}
43
44void DeviceUMA::Stop() {
45  if (stopped_)
46    return;
47  ui::PlatformEventSource::GetInstance()->RemovePlatformEventObserver(this);
48  stopped_ = true;
49}
50
51void DeviceUMA::WillProcessEvent(const ui::PlatformEvent& event) {
52  CheckIncomingEvent(event);
53}
54
55void DeviceUMA::DidProcessEvent(const ui::PlatformEvent& event) {
56}
57
58void DeviceUMA::CheckTouchpadEvent(XEvent* native_event) {
59  XIDeviceEvent* xiev =
60      static_cast<XIDeviceEvent*>(native_event->xcookie.data);
61  // We take only the slave event since there is no need to count twice.
62  if (xiev->deviceid != xiev->sourceid)
63    return;
64  UMA_HISTOGRAM_ENUMERATION("Touchpad.Metrics",
65                            UMA_CROS_GESTURE_METRICS_ALL_EVENTS,
66                            UMA_CROS_GESTURE_METRICS_COUNT);
67
68  // Check for the CrOS touchpad metrics gesture
69  ui::DeviceDataManagerX11 *manager = ui::DeviceDataManagerX11::GetInstance();
70  if (manager->IsCMTMetricsEvent(native_event)) {
71    ui::GestureMetricsType type;
72    float data1, data2;
73    manager->GetMetricsData(native_event, &type, &data1, &data2);
74
75    // We currently track only the noisy ground issue. Please see
76    // http://crbug.com/237683.
77    if (type == ui::kGestureMetricsTypeNoisyGround) {
78      UMA_HISTOGRAM_ENUMERATION("Touchpad.Metrics",
79                                UMA_CROS_GESTURE_METRICS_NOISY_GROUND,
80                                UMA_CROS_GESTURE_METRICS_COUNT);
81    }
82  }
83}
84
85void DeviceUMA::CheckIncomingEvent(XEvent* event) {
86  switch (event->type) {
87    case GenericEvent: {
88      ui::DeviceDataManagerX11* devices =
89          ui::DeviceDataManagerX11::GetInstance();
90      if (devices->IsXIDeviceEvent(event) &&
91          devices->IsTouchpadXInputEvent(event)) {
92        CheckTouchpadEvent(event);
93      }
94      break;
95    }
96    default:
97      break;
98  }
99  return;
100}
101
102}  // namespace chromeos
103