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.
5 #include "ash/metrics/user_metrics_recorder.h"
7 #include "ash/shelf/shelf_layout_manager.h"
8 #include "ash/shelf/shelf_view.h"
9 #include "ash/shelf/shelf_widget.h"
10 #include "ash/shell.h"
11 #include "ash/shell_window_ids.h"
12 #include "ash/wm/window_state.h"
13 #include "base/metrics/histogram.h"
14 #include "base/metrics/user_metrics.h"
15 #include "ui/aura/window.h"
21 // Time in seconds between calls to "RecordPeriodicMetrics".
22 const int kAshPeriodicMetricsTimeInSeconds
= 30 * 60;
24 enum ActiveWindowStateType
{
25 ACTIVE_WINDOW_STATE_TYPE_NO_ACTIVE_WINDOW
,
26 ACTIVE_WINDOW_STATE_TYPE_OTHER
,
27 ACTIVE_WINDOW_STATE_TYPE_MAXIMIZED
,
28 ACTIVE_WINDOW_STATE_TYPE_FULLSCREEN
,
29 ACTIVE_WINDOW_STATE_TYPE_SNAPPED
,
30 ACTIVE_WINDOW_STATE_TYPE_DOCKED
,
31 ACTIVE_WINDOW_STATE_TYPE_COUNT
34 ActiveWindowStateType
GetActiveWindowState() {
35 ActiveWindowStateType active_window_state_type
=
36 ACTIVE_WINDOW_STATE_TYPE_NO_ACTIVE_WINDOW
;
37 wm::WindowState
* active_window_state
= ash::wm::GetActiveWindowState();
38 if (active_window_state
) {
39 switch (active_window_state
->GetStateType()) {
40 case wm::WINDOW_STATE_TYPE_MAXIMIZED
:
41 active_window_state_type
= ACTIVE_WINDOW_STATE_TYPE_MAXIMIZED
;
43 case wm::WINDOW_STATE_TYPE_FULLSCREEN
:
44 active_window_state_type
= ACTIVE_WINDOW_STATE_TYPE_FULLSCREEN
;
46 case wm::WINDOW_STATE_TYPE_LEFT_SNAPPED
:
47 case wm::WINDOW_STATE_TYPE_RIGHT_SNAPPED
:
48 active_window_state_type
= ACTIVE_WINDOW_STATE_TYPE_SNAPPED
;
50 case wm::WINDOW_STATE_TYPE_DOCKED
:
51 case wm::WINDOW_STATE_TYPE_DOCKED_MINIMIZED
:
52 active_window_state_type
= ACTIVE_WINDOW_STATE_TYPE_DOCKED
;
54 case wm::WINDOW_STATE_TYPE_DEFAULT
:
55 case wm::WINDOW_STATE_TYPE_NORMAL
:
56 case wm::WINDOW_STATE_TYPE_MINIMIZED
:
57 case wm::WINDOW_STATE_TYPE_INACTIVE
:
58 case wm::WINDOW_STATE_TYPE_END
:
59 case wm::WINDOW_STATE_TYPE_AUTO_POSITIONED
:
60 active_window_state_type
= ACTIVE_WINDOW_STATE_TYPE_OTHER
;
64 return active_window_state_type
;
67 // Array of window container ids that contain visible windows to be counted for
68 // UMA statistics. Note the containers are ordered from top most visible
69 // container to the lowest to allow the |GetNumVisibleWindows| method to short
70 // circuit when processing a maximized or fullscreen window.
71 int kVisibleWindowContainerIds
[] = {kShellWindowId_PanelContainer
,
72 kShellWindowId_DockedContainer
,
73 kShellWindowId_AlwaysOnTopContainer
,
74 kShellWindowId_DefaultContainer
};
76 // Returns an approximate count of how many windows are currently visible in the
77 // primary root window.
78 int GetNumVisibleWindowsInPrimaryDisplay() {
79 int visible_window_count
= 0;
80 bool maximized_or_fullscreen_window_present
= false;
82 for (const int& current_container_id
: kVisibleWindowContainerIds
) {
83 if (maximized_or_fullscreen_window_present
)
86 const aura::Window::Windows
& children
=
87 Shell::GetContainer(Shell::GetInstance()->GetPrimaryRootWindow(),
88 current_container_id
)->children();
89 // Reverse iterate over the child windows so that they are processed in
90 // visible stacking order.
91 for (aura::Window::Windows::const_reverse_iterator it
= children
.rbegin(),
92 rend
= children
.rend();
94 const aura::Window
* child_window
= *it
;
95 const wm::WindowState
* child_window_state
=
96 wm::GetWindowState(child_window
);
98 if (!child_window
->IsVisible() || child_window_state
->IsMinimized())
101 // Only count activatable windows for 2 reasons:
102 // 1. Ensures that a browser window and its transient, modal child will
103 // only count as 1 visible window.
104 // 2. Prevents counting some windows in the
105 // kShellWindowId_DockedContainer that were not opened by the user.
106 if (child_window_state
->CanActivate())
107 ++visible_window_count
;
109 // Stop counting windows that will be hidden by maximized or fullscreen
110 // windows. Only windows in the kShellWindowId_DefaultContainer and
111 // kShellWindowId_AlwaysOnTopContainer can be maximized or fullscreened
112 // and completely obscure windows beneath them.
113 if ((kShellWindowId_DefaultContainer
== current_container_id
||
114 kShellWindowId_AlwaysOnTopContainer
== current_container_id
) &&
115 child_window_state
->IsMaximizedOrFullscreen()) {
116 maximized_or_fullscreen_window_present
= true;
121 return visible_window_count
;
126 UserMetricsRecorder::UserMetricsRecorder() {
127 timer_
.Start(FROM_HERE
,
128 base::TimeDelta::FromSeconds(kAshPeriodicMetricsTimeInSeconds
),
130 &UserMetricsRecorder::RecordPeriodicMetrics
);
133 UserMetricsRecorder::~UserMetricsRecorder() {
137 void UserMetricsRecorder::RecordUserMetricsAction(UserMetricsAction action
) {
139 case ash::UMA_ACCEL_KEYBOARD_BRIGHTNESS_DOWN_F6
:
141 base::UserMetricsAction("Accel_KeyboardBrightnessDown_F6"));
143 case ash::UMA_ACCEL_KEYBOARD_BRIGHTNESS_UP_F7
:
145 base::UserMetricsAction("Accel_KeyboardBrightnessUp_F7"));
147 case ash::UMA_ACCEL_LOCK_SCREEN_LOCK_BUTTON
:
149 base::UserMetricsAction("Accel_LockScreen_LockButton"));
151 case ash::UMA_ACCEL_LOCK_SCREEN_POWER_BUTTON
:
153 base::UserMetricsAction("Accel_LockScreen_PowerButton"));
155 case ash::UMA_ACCEL_MAXIMIZE_RESTORE_F4
:
157 base::UserMetricsAction("Accel_Maximize_Restore_F4"));
159 case ash::UMA_ACCEL_PREVWINDOW_F5
:
160 base::RecordAction(base::UserMetricsAction("Accel_PrevWindow_F5"));
162 case ash::UMA_ACCEL_EXIT_FIRST_Q
:
163 base::RecordAction(base::UserMetricsAction("Accel_Exit_First_Q"));
165 case ash::UMA_ACCEL_EXIT_SECOND_Q
:
166 base::RecordAction(base::UserMetricsAction("Accel_Exit_Second_Q"));
168 case ash::UMA_ACCEL_RESTART_POWER_BUTTON
:
170 base::UserMetricsAction("Accel_Restart_PowerButton"));
172 case ash::UMA_ACCEL_SHUT_DOWN_POWER_BUTTON
:
174 base::UserMetricsAction("Accel_ShutDown_PowerButton"));
176 case ash::UMA_CLOSE_THROUGH_CONTEXT_MENU
:
177 base::RecordAction(base::UserMetricsAction("CloseFromContextMenu"));
179 case ash::UMA_DRAG_MAXIMIZE_LEFT
:
180 base::RecordAction(base::UserMetricsAction("WindowDrag_MaximizeLeft"));
182 case ash::UMA_DRAG_MAXIMIZE_RIGHT
:
183 base::RecordAction(base::UserMetricsAction("WindowDrag_MaximizeRight"));
185 case ash::UMA_GESTURE_OVERVIEW
:
186 base::RecordAction(base::UserMetricsAction("Gesture_Overview"));
188 case ash::UMA_LAUNCHER_BUTTON_PRESSED_WITH_MOUSE
:
190 base::UserMetricsAction("Launcher_ButtonPressed_Mouse"));
192 case ash::UMA_LAUNCHER_BUTTON_PRESSED_WITH_TOUCH
:
194 base::UserMetricsAction("Launcher_ButtonPressed_Touch"));
196 case ash::UMA_LAUNCHER_CLICK_ON_APP
:
197 base::RecordAction(base::UserMetricsAction("Launcher_ClickOnApp"));
199 case ash::UMA_LAUNCHER_CLICK_ON_APPLIST_BUTTON
:
201 base::UserMetricsAction("Launcher_ClickOnApplistButton"));
203 case ash::UMA_LAUNCHER_LAUNCH_TASK
:
204 base::RecordAction(base::UserMetricsAction("Launcher_LaunchTask"));
206 case UMA_MAXIMIZE_MODE_DISABLED
:
207 base::RecordAction(base::UserMetricsAction("Touchview_Disabled"));
209 case UMA_MAXIMIZE_MODE_ENABLED
:
210 base::RecordAction(base::UserMetricsAction("Touchview_Enabled"));
212 case UMA_MAXIMIZE_MODE_INITIALLY_DISABLED
:
214 base::UserMetricsAction("Touchview_Initially_Disabled"));
216 case ash::UMA_MOUSE_DOWN
:
217 base::RecordAction(base::UserMetricsAction("Mouse_Down"));
219 case ash::UMA_PANEL_MINIMIZE_CAPTION_CLICK
:
221 base::UserMetricsAction("Panel_Minimize_Caption_Click"));
223 case ash::UMA_PANEL_MINIMIZE_CAPTION_GESTURE
:
225 base::UserMetricsAction("Panel_Minimize_Caption_Gesture"));
227 case ash::UMA_SHELF_ALIGNMENT_SET_BOTTOM
:
229 base::UserMetricsAction("Shelf_AlignmentSetBottom"));
231 case ash::UMA_SHELF_ALIGNMENT_SET_LEFT
:
233 base::UserMetricsAction("Shelf_AlignmentSetLeft"));
235 case ash::UMA_SHELF_ALIGNMENT_SET_RIGHT
:
237 base::UserMetricsAction("Shelf_AlignmentSetRight"));
239 case ash::UMA_STATUS_AREA_AUDIO_CURRENT_INPUT_DEVICE
:
241 base::UserMetricsAction("StatusArea_Audio_CurrentInputDevice"));
243 case ash::UMA_STATUS_AREA_AUDIO_CURRENT_OUTPUT_DEVICE
:
245 base::UserMetricsAction("StatusArea_Audio_CurrentOutputDevice"));
247 case ash::UMA_STATUS_AREA_AUDIO_SWITCH_INPUT_DEVICE
:
249 base::UserMetricsAction("StatusArea_Audio_SwitchInputDevice"));
251 case ash::UMA_STATUS_AREA_AUDIO_SWITCH_OUTPUT_DEVICE
:
253 base::UserMetricsAction("StatusArea_Audio_SwitchOutputDevice"));
255 case ash::UMA_STATUS_AREA_BRIGHTNESS_CHANGED
:
257 base::UserMetricsAction("StatusArea_BrightnessChanged"));
259 case ash::UMA_STATUS_AREA_BLUETOOTH_CONNECT_KNOWN_DEVICE
:
261 base::UserMetricsAction("StatusArea_Bluetooth_Connect_Known"));
263 case ash::UMA_STATUS_AREA_BLUETOOTH_CONNECT_UNKNOWN_DEVICE
:
265 base::UserMetricsAction("StatusArea_Bluetooth_Connect_Unknown"));
267 case ash::UMA_STATUS_AREA_BLUETOOTH_DISABLED
:
269 base::UserMetricsAction("StatusArea_Bluetooth_Disabled"));
271 case ash::UMA_STATUS_AREA_BLUETOOTH_ENABLED
:
273 base::UserMetricsAction("StatusArea_Bluetooth_Enabled"));
275 case ash::UMA_STATUS_AREA_CAPS_LOCK_DETAILED
:
277 base::UserMetricsAction("StatusArea_CapsLock_Detailed"));
279 case ash::UMA_STATUS_AREA_CAPS_LOCK_DISABLED_BY_CLICK
:
281 base::UserMetricsAction("StatusArea_CapsLock_DisabledByClick"));
283 case ash::UMA_STATUS_AREA_CAPS_LOCK_ENABLED_BY_CLICK
:
285 base::UserMetricsAction("StatusArea_CapsLock_EnabledByClick"));
287 case ash::UMA_STATUS_AREA_CAPS_LOCK_POPUP
:
289 base::UserMetricsAction("StatusArea_CapsLock_Popup"));
291 case ash::UMA_STATUS_AREA_CONNECT_TO_CONFIGURED_NETWORK
:
293 base::UserMetricsAction("StatusArea_Network_ConnectConfigured"));
295 case ash::UMA_STATUS_AREA_CONNECT_TO_UNCONFIGURED_NETWORK
:
297 base::UserMetricsAction("StatusArea_Network_ConnectUnconfigured"));
299 case ash::UMA_STATUS_AREA_CONNECT_TO_VPN
:
301 base::UserMetricsAction("StatusArea_VPN_ConnectToNetwork"));
303 case ash::UMA_STATUS_AREA_CHANGED_VOLUME_MENU
:
305 base::UserMetricsAction("StatusArea_Volume_ChangedMenu"));
307 case ash::UMA_STATUS_AREA_CHANGED_VOLUME_POPUP
:
309 base::UserMetricsAction("StatusArea_Volume_ChangedPopup"));
311 case ash::UMA_STATUS_AREA_DETAILED_ACCESSABILITY
:
313 base::UserMetricsAction("StatusArea_Accessability_DetailedView"));
315 case ash::UMA_STATUS_AREA_DETAILED_AUDIO_VIEW
:
317 base::UserMetricsAction("StatusArea_Audio_Detailed"));
319 case ash::UMA_STATUS_AREA_DETAILED_BLUETOOTH_VIEW
:
321 base::UserMetricsAction("StatusArea_Bluetooth_Detailed"));
323 case ash::UMA_STATUS_AREA_DETAILED_BRIGHTNESS_VIEW
:
325 base::UserMetricsAction("StatusArea_Brightness_Detailed"));
327 case ash::UMA_STATUS_AREA_DETAILED_DRIVE_VIEW
:
329 base::UserMetricsAction("StatusArea_Drive_Detailed"));
331 case ash::UMA_STATUS_AREA_DETAILED_NETWORK_VIEW
:
333 base::UserMetricsAction("StatusArea_Network_Detailed"));
335 case ash::UMA_STATUS_AREA_DETAILED_VPN_VIEW
:
337 base::UserMetricsAction("StatusArea_VPN_Detailed"));
339 case ash::UMA_STATUS_AREA_DISABLE_AUTO_CLICK
:
341 base::UserMetricsAction("StatusArea_AutoClickDisabled"));
343 case ash::UMA_STATUS_AREA_DISABLE_HIGH_CONTRAST
:
345 base::UserMetricsAction("StatusArea_HighContrastDisabled"));
347 case ash::UMA_STATUS_AREA_DISABLE_LARGE_CURSOR
:
349 base::UserMetricsAction("StatusArea_LargeCursorDisabled"));
351 case ash::UMA_STATUS_AREA_DISABLE_MAGNIFIER
:
353 base::UserMetricsAction("StatusArea_MagnifierDisabled"));
355 case ash::UMA_STATUS_AREA_DISABLE_SPOKEN_FEEDBACK
:
357 base::UserMetricsAction("StatusArea_SpokenFeedbackDisabled"));
359 case ash::UMA_STATUS_AREA_DISABLE_VIRTUAL_KEYBOARD
:
361 base::UserMetricsAction("StatusArea_VirtualKeyboardDisabled"));
363 case ash::UMA_STATUS_AREA_DISABLE_WIFI
:
365 base::UserMetricsAction("StatusArea_Network_WifiDisabled"));
367 case ash::UMA_STATUS_AREA_DRIVE_CANCEL_OPERATION
:
369 base::UserMetricsAction("StatusArea_Drive_CancelOperation"));
371 case ash::UMA_STATUS_AREA_DRIVE_SETTINGS
:
373 base::UserMetricsAction("StatusArea_Drive_Settings"));
375 case ash::UMA_STATUS_AREA_ENABLE_AUTO_CLICK
:
377 base::UserMetricsAction("StatusArea_AutoClickEnabled"));
379 case ash::UMA_STATUS_AREA_ENABLE_HIGH_CONTRAST
:
381 base::UserMetricsAction("StatusArea_HighContrastEnabled"));
383 case ash::UMA_STATUS_AREA_ENABLE_LARGE_CURSOR
:
385 base::UserMetricsAction("StatusArea_LargeCursorEnabled"));
387 case ash::UMA_STATUS_AREA_ENABLE_MAGNIFIER
:
389 base::UserMetricsAction("StatusArea_MagnifierEnabled"));
391 case ash::UMA_STATUS_AREA_ENABLE_SPOKEN_FEEDBACK
:
393 base::UserMetricsAction("StatusArea_SpokenFeedbackEnabled"));
395 case ash::UMA_STATUS_AREA_ENABLE_VIRTUAL_KEYBOARD
:
397 base::UserMetricsAction("StatusArea_VirtualKeyboardEnabled"));
399 case ash::UMA_STATUS_AREA_ENABLE_WIFI
:
401 base::UserMetricsAction("StatusArea_Network_WifiEnabled"));
403 case ash::UMA_STATUS_AREA_IME_SHOW_DETAILED
:
405 base::UserMetricsAction("StatusArea_IME_Detailed"));
407 case ash::UMA_STATUS_AREA_IME_SWITCH_MODE
:
409 base::UserMetricsAction("StatusArea_IME_SwitchMode"));
411 case ash::UMA_STATUS_AREA_MENU_OPENED
:
413 base::UserMetricsAction("StatusArea_MenuOpened"));
415 case ash::UMA_STATUS_AREA_NETWORK_JOIN_OTHER_CLICKED
:
417 base::UserMetricsAction("StatusArea_Network_JoinOther"));
419 case ash::UMA_STATUS_AREA_NETWORK_SETTINGS_CLICKED
:
421 base::UserMetricsAction("StatusArea_Network_Settings"));
423 case ash::UMA_STATUS_AREA_SHOW_NETWORK_CONNECTION_DETAILS
:
425 base::UserMetricsAction("StatusArea_Network_ConnectionDetails"));
427 case ash::UMA_STATUS_AREA_SHOW_VPN_CONNECTION_DETAILS
:
429 base::UserMetricsAction("StatusArea_VPN_ConnectionDetails"));
431 case ash::UMA_STATUS_AREA_SIGN_OUT
:
433 base::UserMetricsAction("StatusArea_SignOut"));
435 case ash::UMA_STATUS_AREA_VPN_ADD_BUILT_IN_CLICKED
:
436 base::RecordAction(base::UserMetricsAction("StatusArea_VPN_AddBuiltIn"));
438 case ash::UMA_STATUS_AREA_VPN_ADD_THIRD_PARTY_CLICKED
:
440 base::UserMetricsAction("StatusArea_VPN_AddThirdParty"));
442 case ash::UMA_STATUS_AREA_VPN_DISCONNECT_CLICKED
:
443 base::RecordAction(base::UserMetricsAction("StatusArea_VPN_Disconnect"));
445 case ash::UMA_STATUS_AREA_VPN_SETTINGS_CLICKED
:
447 base::UserMetricsAction("StatusArea_VPN_Settings"));
449 case ash::UMA_TOGGLE_MAXIMIZE_CAPTION_CLICK
:
451 base::UserMetricsAction("Caption_ClickTogglesMaximize"));
453 case ash::UMA_TOGGLE_MAXIMIZE_CAPTION_GESTURE
:
455 base::UserMetricsAction("Caption_GestureTogglesMaximize"));
457 case ash::UMA_TOGGLE_SINGLE_AXIS_MAXIMIZE_BORDER_CLICK
:
459 base::UserMetricsAction(
460 "WindowBorder_ClickTogglesSingleAxisMaximize"));
462 case ash::UMA_TOUCHPAD_GESTURE_OVERVIEW
:
464 base::UserMetricsAction("Touchpad_Gesture_Overview"));
466 case ash::UMA_TOUCHSCREEN_TAP_DOWN
:
467 base::RecordAction(base::UserMetricsAction("Touchscreen_Down"));
469 case ash::UMA_TRAY_HELP
:
470 base::RecordAction(base::UserMetricsAction("Tray_Help"));
472 case ash::UMA_TRAY_LOCK_SCREEN
:
473 base::RecordAction(base::UserMetricsAction("Tray_LockScreen"));
475 case ash::UMA_TRAY_SHUT_DOWN
:
476 base::RecordAction(base::UserMetricsAction("Tray_ShutDown"));
478 case ash::UMA_WINDOW_APP_CLOSE_BUTTON_CLICK
:
479 base::RecordAction(base::UserMetricsAction("AppCloseButton_Clk"));
481 case ash::UMA_WINDOW_CLOSE_BUTTON_CLICK
:
482 base::RecordAction(base::UserMetricsAction("CloseButton_Clk"));
484 case ash::UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_EXIT_FULLSCREEN
:
485 base::RecordAction(base::UserMetricsAction("MaxButton_Clk_ExitFS"));
487 case ash::UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_RESTORE
:
489 base::UserMetricsAction("MaxButton_Clk_Restore"));
491 case ash::UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_MAXIMIZE
:
493 base::UserMetricsAction("MaxButton_Clk_Maximize"));
495 case ash::UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_MINIMIZE
:
496 base::RecordAction(base::UserMetricsAction("MinButton_Clk"));
498 case ash::UMA_WINDOW_MAXIMIZE_BUTTON_MAXIMIZE_LEFT
:
499 base::RecordAction(base::UserMetricsAction("MaxButton_MaxLeft"));
501 case ash::UMA_WINDOW_MAXIMIZE_BUTTON_MAXIMIZE_RIGHT
:
502 base::RecordAction(base::UserMetricsAction("MaxButton_MaxRight"));
504 case ash::UMA_WINDOW_OVERVIEW
:
506 base::UserMetricsAction("WindowSelector_Overview"));
508 case ash::UMA_WINDOW_OVERVIEW_ENTER_KEY
:
510 base::UserMetricsAction("WindowSelector_OverviewEnterKey"));
512 case ash::UMA_WINDOW_CYCLE
:
514 base::UserMetricsAction("WindowCycleController_Cycle"));
519 void UserMetricsRecorder::RecordPeriodicMetrics() {
520 ShelfLayoutManager
* manager
=
521 ShelfLayoutManager::ForShelf(Shell::GetPrimaryRootWindow());
523 UMA_HISTOGRAM_ENUMERATION("Ash.ShelfAlignmentOverTime",
524 manager
->SelectValueForShelfAlignment(
525 SHELF_ALIGNMENT_UMA_ENUM_VALUE_BOTTOM
,
526 SHELF_ALIGNMENT_UMA_ENUM_VALUE_LEFT
,
527 SHELF_ALIGNMENT_UMA_ENUM_VALUE_RIGHT
,
529 SHELF_ALIGNMENT_UMA_ENUM_VALUE_COUNT
);
532 UMA_HISTOGRAM_COUNTS_100("Ash.NumberOfVisibleWindowsInPrimaryDisplay",
533 GetNumVisibleWindowsInPrimaryDisplay());
535 UMA_HISTOGRAM_ENUMERATION("Ash.ActiveWindowShowTypeOverTime",
536 GetActiveWindowState(),
537 ACTIVE_WINDOW_STATE_TYPE_COUNT
);