Home | History | Annotate | Download | only in chromeos
      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/base/events/event_constants.h"
     14 #include "ui/base/events/event_utils.h"
     15 #include "ui/base/x/device_data_manager.h"
     16 
     17 // Enum type for CrOS gesture lib UMA
     18 enum UMACrosGestureMetricsType{
     19   // To give an estimated number of all interested events.
     20   UMA_CROS_GESTURE_METRICS_ALL_EVENTS,
     21   UMA_CROS_GESTURE_METRICS_NOISY_GROUND,
     22   // NOTE: Add states only immediately above this line. Make sure to
     23   // update the enum list in tools/metrics/histograms/histograms.xml
     24   // accordingly.
     25   UMA_CROS_GESTURE_METRICS_COUNT
     26 };
     27 
     28 namespace chromeos {
     29 
     30 DeviceUMA* DeviceUMA::GetInstance() {
     31   return Singleton<DeviceUMA>::get();
     32 }
     33 
     34 DeviceUMA::DeviceUMA()
     35     :is_observing_(false) {
     36   AddMessageLoopObserver();
     37 }
     38 
     39 DeviceUMA::~DeviceUMA() {
     40   RemoveMessageLoopObserver();
     41 }
     42 
     43 void DeviceUMA::Stop() {
     44   RemoveMessageLoopObserver();
     45 }
     46 
     47 void DeviceUMA::AddMessageLoopObserver() {
     48   if (!is_observing_) {
     49     base::MessageLoopForUI::current()->AddObserver(this);
     50     is_observing_ = true;
     51   }
     52 }
     53 
     54 void DeviceUMA::RemoveMessageLoopObserver() {
     55   if (is_observing_) {
     56     base::MessageLoopForUI::current()->RemoveObserver(this);
     57     is_observing_ = false;
     58   }
     59 }
     60 
     61 base::EventStatus DeviceUMA::WillProcessEvent(
     62     const base::NativeEvent& event) {
     63   CheckIncomingEvent(event);
     64   return base::EVENT_CONTINUE;
     65 }
     66 
     67 void DeviceUMA::DidProcessEvent(
     68     const base::NativeEvent& event) {
     69 }
     70 
     71 void DeviceUMA::CheckTouchpadEvent(const base::NativeEvent& native_event) {
     72   XIDeviceEvent* xiev =
     73       static_cast<XIDeviceEvent*>(native_event->xcookie.data);
     74   // We take only the slave event since there is no need to count twice.
     75   if (xiev->deviceid != xiev->sourceid)
     76     return;
     77   UMA_HISTOGRAM_ENUMERATION("Touchpad.Metrics",
     78                             UMA_CROS_GESTURE_METRICS_ALL_EVENTS,
     79                             UMA_CROS_GESTURE_METRICS_COUNT);
     80 
     81   // Check for the CrOS touchpad metrics gesture
     82   ui::DeviceDataManager *manager = ui::DeviceDataManager::GetInstance();
     83   if (manager->IsCMTMetricsEvent(native_event)) {
     84     ui::GestureMetricsType type;
     85     float data1, data2;
     86     manager->GetMetricsData(native_event, &type, &data1, &data2);
     87 
     88     // We currently track only the noisy ground issue. Please see
     89     // http://crbug.com/237683.
     90     if (type == ui::kGestureMetricsTypeNoisyGround) {
     91       UMA_HISTOGRAM_ENUMERATION("Touchpad.Metrics",
     92                                 UMA_CROS_GESTURE_METRICS_NOISY_GROUND,
     93                                 UMA_CROS_GESTURE_METRICS_COUNT);
     94     }
     95   }
     96 }
     97 
     98 void DeviceUMA::CheckIncomingEvent(const base::NativeEvent& event) {
     99   switch (event->type) {
    100     case GenericEvent: {
    101       if (ui::DeviceDataManager::GetInstance()->IsXIDeviceEvent(event) &&
    102           ui::IsTouchpadEvent(event))
    103         CheckTouchpadEvent(event);
    104       break;
    105     }
    106     default:
    107       break;
    108   }
    109   return;
    110 }
    111 
    112 }  // namespace chromeos
    113