diff options
-rw-r--r-- | chrome/browser/chromeos/chrome_browser_main_chromeos.cc | 14 | ||||
-rw-r--r-- | chrome/browser/chromeos/device_uma.cc | 111 | ||||
-rw-r--r-- | chrome/browser/chromeos/device_uma.h | 53 | ||||
-rw-r--r-- | chrome/chrome_browser_chromeos.gypi | 8 | ||||
-rw-r--r-- | tools/metrics/histograms/histograms.xml | 17 | ||||
-rw-r--r-- | ui/aura/root_window_host_x11.cc | 2 | ||||
-rw-r--r-- | ui/base/events/event.cc | 1 | ||||
-rw-r--r-- | ui/base/events/event_constants.h | 4 | ||||
-rw-r--r-- | ui/base/x/device_data_manager.cc | 46 | ||||
-rw-r--r-- | ui/base/x/device_data_manager.h | 19 | ||||
-rw-r--r-- | ui/base/x/events_x.cc | 3 |
11 files changed, 277 insertions, 1 deletions
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc index d34fd61..dd0ad54 100644 --- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc +++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc @@ -120,6 +120,11 @@ #include "net/url_request/url_request.h" #include "net/url_request/url_request_context_getter.h" +// Exclude X11 dependents for ozone +#if defined(USE_X11) +#include "chrome/browser/chromeos/device_uma.h" +#endif + namespace chromeos { namespace { @@ -721,6 +726,11 @@ void ChromeBrowserMainPartsChromeos::PreBrowserStart() { // reasons, see http://crosbug.com/24833. XInputHierarchyChangedEventListener::GetInstance(); +#if defined(USE_X11) + // Start the CrOS input device UMA watcher + DeviceUMA::GetInstance(); +#endif + // -- This used to be in ChromeBrowserMainParts::PreMainMessageLoopRun() // -- immediately after ChildProcess::WaitForDebugger(). @@ -791,6 +801,10 @@ void ChromeBrowserMainPartsChromeos::PostMainMessageLoopRun() { // Singletons are finally destroyed in AtExitManager. XInputHierarchyChangedEventListener::GetInstance()->Stop(); +#if defined(USE_X11) + DeviceUMA::GetInstance()->Stop(); +#endif + // SystemKeyEventListener::Shutdown() is always safe to call, // even if Initialize() wasn't called. SystemKeyEventListener::Shutdown(); diff --git a/chrome/browser/chromeos/device_uma.cc b/chrome/browser/chromeos/device_uma.cc new file mode 100644 index 0000000..2f852bb --- /dev/null +++ b/chrome/browser/chromeos/device_uma.cc @@ -0,0 +1,111 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/device_uma.h" + +#include <X11/extensions/XInput.h> +#include <X11/extensions/XInput2.h> + +#include "base/logging.h" +#include "base/memory/singleton.h" +#include "base/metrics/histogram.h" +#include "ui/base/events/event_constants.h" +#include "ui/base/events/event_utils.h" +#include "ui/base/x/device_data_manager.h" + +// Enum type for CrOS gesture lib UMA +enum UMACrosGestureMetricsType{ + // To give an estimated number of all interested events. + UMA_CROS_GESTURE_METRICS_ALL_EVENTS, + UMA_CROS_GESTURE_METRICS_NOISY_GROUND, + // NOTE: Add states only immediately above this line. Make sure to + // update the enum list in tools/metrics/histograms/histograms.xml + // accordingly. + UMA_CROS_GESTURE_METRICS_COUNT +}; + +namespace chromeos { + +DeviceUMA* DeviceUMA::GetInstance() { + return Singleton<DeviceUMA>::get(); +} + +DeviceUMA::DeviceUMA() + :is_observing_(false) { + AddMessageLoopObserver(); +} + +DeviceUMA::~DeviceUMA() { + RemoveMessageLoopObserver(); +} + +void DeviceUMA::Stop() { + RemoveMessageLoopObserver(); +} + +void DeviceUMA::AddMessageLoopObserver() { + if (!is_observing_) { + base::MessageLoopForUI::current()->AddObserver(this); + is_observing_ = true; + } +} + +void DeviceUMA::RemoveMessageLoopObserver() { + if (is_observing_) { + base::MessageLoopForUI::current()->RemoveObserver(this); + is_observing_ = false; + } +} + +base::EventStatus DeviceUMA::WillProcessEvent( + const base::NativeEvent& event) { + CheckIncomingEvent(event); + return base::EVENT_CONTINUE; +} + +void DeviceUMA::DidProcessEvent( + const base::NativeEvent& event) { +} + +void DeviceUMA::CheckTouchpadEvent(const base::NativeEvent& native_event) { + XIDeviceEvent* xiev = + static_cast<XIDeviceEvent*>(native_event->xcookie.data); + // We take only the slave event since there is no need to count twice. + if (xiev->deviceid != xiev->sourceid) + return; + UMA_HISTOGRAM_ENUMERATION("Touchpad.Metrics", + UMA_CROS_GESTURE_METRICS_ALL_EVENTS, + UMA_CROS_GESTURE_METRICS_COUNT); + + // Check for the CrOS touchpad metrics gesture + ui::DeviceDataManager *manager = ui::DeviceDataManager::GetInstance(); + if (manager->IsCMTMetricsEvent(native_event)) { + ui::GestureMetricsType type; + float data1, data2; + manager->GetMetricsData(native_event, &type, &data1, &data2); + + // We currently track only the noisy ground issue. Please see + // http://crbug.com/237683. + if (type == ui::kGestureMetricsTypeNoisyGround) { + UMA_HISTOGRAM_ENUMERATION("Touchpad.Metrics", + UMA_CROS_GESTURE_METRICS_NOISY_GROUND, + UMA_CROS_GESTURE_METRICS_COUNT); + } + } +} + +void DeviceUMA::CheckIncomingEvent(const base::NativeEvent& event) { + switch (event->type) { + case GenericEvent: { + if (ui::IsTouchpadEvent(event)) + CheckTouchpadEvent(event); + break; + } + default: + break; + } + return; +} + +} // namespace chromeos diff --git a/chrome/browser/chromeos/device_uma.h b/chrome/browser/chromeos/device_uma.h new file mode 100644 index 0000000..77f7543 --- /dev/null +++ b/chrome/browser/chromeos/device_uma.h @@ -0,0 +1,53 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_DEVICE_UMA_H_ +#define CHROME_BROWSER_CHROMEOS_DEVICE_UMA_H_ + +#include "base/basictypes.h" +#include "base/event_types.h" +#include "base/message_loop.h" + +template <typename T> struct DefaultSingletonTraits; + +namespace chromeos { + +// A class to record devices' input event details via the UMA system +class DeviceUMA : public base::MessageLoopForUI::Observer { + public: + // Getting instance starts the class automatically if it hasn't been + // started before. + static DeviceUMA* GetInstance(); + + void Stop(); + + private: + friend struct DefaultSingletonTraits<DeviceUMA>; + + DeviceUMA(); + virtual ~DeviceUMA(); + + // Start and stop observing events. + void AddMessageLoopObserver(); + void RemoveMessageLoopObserver(); + + // MessageLoopForUI::Observer overrides. + virtual base::EventStatus WillProcessEvent( + const base::NativeEvent& event) OVERRIDE; + virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE; + + // Check CrOS touchpad events to see if the metrics gesture is present + void CheckTouchpadEvent(const base::NativeEvent& event); + + // Check the incoming events for interesting patterns that we care about. + void CheckIncomingEvent(const base::NativeEvent& event); + + bool is_observing_; + + DISALLOW_COPY_AND_ASSIGN(DeviceUMA); +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_DEVICE_UMA_H_ diff --git a/chrome/chrome_browser_chromeos.gypi b/chrome/chrome_browser_chromeos.gypi index 6872360..9bbfca7 100644 --- a/chrome/chrome_browser_chromeos.gypi +++ b/chrome/chrome_browser_chromeos.gypi @@ -211,6 +211,8 @@ 'browser/chromeos/dbus/proxy_resolution_service_provider.cc', 'browser/chromeos/dbus/proxy_resolution_service_provider.h', 'browser/chromeos/device_hierarchy_observer.h', + 'browser/chromeos/device_uma.cc', + 'browser/chromeos/device_uma.h', 'browser/chromeos/drive/change_list_loader.cc', 'browser/chromeos/drive/change_list_loader.h', 'browser/chromeos/drive/change_list_loader_observer.h', @@ -823,6 +825,12 @@ 'browser/chromeos/extensions/wallpaper_private_api.h', ], }], + ['use_x11==0', { + 'sources!': [ + 'browser/chromeos/device_uma.cc', + 'browser/chromeos/device_uma.h', + ], + }], ['use_cras==1', { 'cflags': [ '<!@(<(pkg-config) --cflags libcras)', diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 454e7c7..27b364f 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml @@ -11167,6 +11167,13 @@ other types of suffix sets. <summary>Tracks touchpad device state.</summary> </histogram> +<histogram name="Touchpad.Metrics" enum="TouchpadProblemType"> + <summary> + Tracks unusual CrOS touchpad operational states (e.g. running into the noisy + ground issue). This is sampled at every touchpad event. + </summary> +</histogram> + <histogram name="Touchpad.NaturalScroll.Changed" enum="BooleanEnabled"> <summary>Tracks touchpad natural scroll setting changes by the user.</summary> </histogram> @@ -17882,6 +17889,16 @@ other types of suffix sets. </int> </enum> +<enum name="TouchpadProblemType" type="int"> + <int value="0" label="All events"> + All observed input events from touchpad. Serves as a reference. + </int> + <int value="1" label="Noisy Ground"> + The touchpad noise events (e.g. abrupt cursor jumps) caused by the noisy + ground. + </int> +</enum> + <enum name="TranslateError" type="int"> <int value="0" label="No error"/> <int value="1" label="Network error"/> diff --git a/ui/aura/root_window_host_x11.cc b/ui/aura/root_window_host_x11.cc index f827373..6606ea2 100644 --- a/ui/aura/root_window_host_x11.cc +++ b/ui/aura/root_window_host_x11.cc @@ -1027,6 +1027,8 @@ void RootWindowHostX11::DispatchXI2Event(const base::NativeEvent& event) { delegate_->OnHostScrollEvent(&scrollev); break; } + case ui::ET_UMA_DATA: + break; case ui::ET_UNKNOWN: break; default: diff --git a/ui/base/events/event.cc b/ui/base/events/event.cc index 40b5639..b69780c 100644 --- a/ui/base/events/event.cc +++ b/ui/base/events/event.cc @@ -95,6 +95,7 @@ std::string EventTypeName(ui::EventType type) { CASE_TYPE(ET_SCROLL_FLING_START); CASE_TYPE(ET_SCROLL_FLING_CANCEL); CASE_TYPE(ET_CANCEL_MODE); + CASE_TYPE(ET_UMA_DATA); case ui::ET_LAST: NOTREACHED(); return std::string(); // Don't include default, so that we get an error when new type is added. } diff --git a/ui/base/events/event_constants.h b/ui/base/events/event_constants.h index e91c779..481579e 100644 --- a/ui/base/events/event_constants.h +++ b/ui/base/events/event_constants.h @@ -58,6 +58,10 @@ enum EventType { // drop or menus, should stop. ET_CANCEL_MODE, + // Sent by the CrOS gesture library for interesting patterns that we want + // to track with the UMA system. + ET_UMA_DATA, + // Must always be last. User namespace starts above this value. // See ui::RegisterCustomEventType(). ET_LAST diff --git a/ui/base/x/device_data_manager.cc b/ui/base/x/device_data_manager.cc index 0332d75..7707518 100644 --- a/ui/base/x/device_data_manager.cc +++ b/ui/base/x/device_data_manager.cc @@ -41,6 +41,11 @@ #define AXIS_LABEL_PROP_ABS_FINGER_COUNT "Abs Finger Count" +// Cros metrics gesture from touchpad +#define AXIS_LABEL_PROP_ABS_METRICS_TYPE "Abs Metrics Type" +#define AXIS_LABEL_PROP_ABS_DBL_METRICS_DATA1 "Abs Dbl Metrics Data 1" +#define AXIS_LABEL_PROP_ABS_DBL_METRICS_DATA2 "Abs Dbl Metrics Data 2" + // Touchscreen multi-touch #define AXIS_LABEL_ABS_MT_TOUCH_MAJOR "Abs MT Touch Major" #define AXIS_LABEL_ABS_MT_TOUCH_MINOR "Abs MT Touch Minor" @@ -63,6 +68,9 @@ const char* kCachedAtoms[] = { AXIS_LABEL_PROP_ABS_DBL_FLING_VX, AXIS_LABEL_PROP_ABS_DBL_FLING_VY, AXIS_LABEL_PROP_ABS_FLING_STATE, + AXIS_LABEL_PROP_ABS_METRICS_TYPE, + AXIS_LABEL_PROP_ABS_DBL_METRICS_DATA1, + AXIS_LABEL_PROP_ABS_DBL_METRICS_DATA2, AXIS_LABEL_PROP_ABS_FINGER_COUNT, AXIS_LABEL_ABS_MT_TOUCH_MAJOR, AXIS_LABEL_ABS_MT_TOUCH_MINOR, @@ -285,7 +293,8 @@ bool DeviceDataManager::IsCMTDeviceEvent( bool DeviceDataManager::IsCMTGestureEvent( const base::NativeEvent& native_event) const { return (IsScrollEvent(native_event) || - IsFlingEvent(native_event)); + IsFlingEvent(native_event) || + IsCMTMetricsEvent(native_event)); } bool DeviceDataManager::HasEventData( @@ -317,6 +326,18 @@ bool DeviceDataManager::IsFlingEvent( HasEventData(xiev, DT_CMT_FLING_STATE)); } +bool DeviceDataManager::IsCMTMetricsEvent( + const base::NativeEvent& native_event) const { + if (!IsCMTDeviceEvent(native_event)) + return false; + + XIDeviceEvent* xiev = + static_cast<XIDeviceEvent*>(native_event->xcookie.data); + return (HasEventData(xiev, DT_CMT_METRICS_TYPE) && + HasEventData(xiev, DT_CMT_METRICS_DATA1) && + HasEventData(xiev, DT_CMT_METRICS_DATA2)); +} + bool DeviceDataManager::HasGestureTimes( const base::NativeEvent& native_event) const { if (!IsCMTDeviceEvent(native_event)) @@ -385,6 +406,29 @@ void DeviceDataManager::GetFlingData(const base::NativeEvent& native_event, *vy_ordinal = data[DT_CMT_ORDINAL_Y] * natural_scroll_factor; } +void DeviceDataManager::GetMetricsData(const base::NativeEvent& native_event, + GestureMetricsType* type, + float* data1, float* data2) { + *type = kGestureMetricsTypeUnknown; + *data1 = 0; + *data2 = 0; + + EventData data; + GetEventRawData(*native_event, &data); + + if (data.find(DT_CMT_METRICS_TYPE) != data.end()) { + int val = static_cast<int>(data[DT_CMT_METRICS_TYPE]); + if (val == 0) + *type = kGestureMetricsTypeNoisyGround; + else + *type = kGestureMetricsTypeUnknown; + } + if (data.find(DT_CMT_METRICS_DATA1) != data.end()) + *data1 = data[DT_CMT_METRICS_DATA1]; + if (data.find(DT_CMT_METRICS_DATA2) != data.end()) + *data2 = data[DT_CMT_METRICS_DATA2]; +} + void DeviceDataManager::GetGestureTimes(const base::NativeEvent& native_event, double* start_time, double* end_time) { diff --git a/ui/base/x/device_data_manager.h b/ui/base/x/device_data_manager.h index 27f468a..950cca1 100644 --- a/ui/base/x/device_data_manager.h +++ b/ui/base/x/device_data_manager.h @@ -23,6 +23,12 @@ typedef union _XEvent XEvent; namespace ui { +// CrOS touchpad metrics gesture types +enum GestureMetricsType { + kGestureMetricsTypeNoisyGround = 0, + kGestureMetricsTypeUnknown, +}; + // A class that extracts and tracks the input events data. It currently handles // mouse, touchpad and touchscreen devices. class UI_EXPORT DeviceDataManager { @@ -47,6 +53,11 @@ class UI_EXPORT DeviceDataManager { DT_CMT_FLING_Y, // Fling amount on the Y (vertical) direction. DT_CMT_FLING_STATE, // The state of fling gesture (whether the user just // start flinging or that he/she taps down). + DT_CMT_METRICS_TYPE, // Metrics type of the metrics gesture, which are + // used to wrap interesting patterns that we would + // like to track via the UMA system. + DT_CMT_METRICS_DATA1, // Complementary data 1 of the metrics gesture. + DT_CMT_METRICS_DATA2, // Complementary data 2 of the metrics gesture. DT_CMT_FINGER_COUNT, // Finger counts in the current gesture. A same type // of gesture can have very different meanings based // on that (e.g. 2f scroll v.s. 3f swipe). @@ -140,6 +151,7 @@ class UI_EXPORT DeviceDataManager { // Returns true if the event is of the specific type, false if not. bool IsScrollEvent(const base::NativeEvent& native_event) const; bool IsFlingEvent(const base::NativeEvent& native_event) const; + bool IsCMTMetricsEvent(const base::NativeEvent& native_event) const; // Returns true if the event has CMT start/end timestamps. bool HasGestureTimes(const base::NativeEvent& native_event) const; @@ -163,6 +175,13 @@ class UI_EXPORT DeviceDataManager { float* vy_ordinal, bool* is_cancel); + // Extract data from a CrOS metrics gesture event. User must first verify + // the event type with IsCMTMetricsEvent. Pointers shouldn't be NULL. + void GetMetricsData(const base::NativeEvent& native_event, + GestureMetricsType* type, + float* data1, + float* data2); + // Extract the start/end timestamps from CMT events. User must first verify // the event with HasGestureTimes. Pointers shouldn't be NULL. void GetGestureTimes(const base::NativeEvent& native_event, diff --git a/ui/base/x/events_x.cc b/ui/base/x/events_x.cc index c625ec9..ed26b93 100644 --- a/ui/base/x/events_x.cc +++ b/ui/base/x/events_x.cc @@ -344,6 +344,9 @@ EventType EventTypeFromNative(const base::NativeEvent& native_event) { } else if (DeviceDataManager::GetInstance()->IsScrollEvent( native_event)) { return IsTouchpadEvent(native_event) ? ET_SCROLL : ET_MOUSEWHEEL; + } else if (DeviceDataManager::GetInstance()->IsCMTMetricsEvent( + native_event)) { + return ET_UMA_DATA; } else if (GetButtonMaskForX2Event(xievent)) { return ET_MOUSE_DRAGGED; } else { |