| Index: chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUma.java
|
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUma.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUma.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..576245b2ba915c66598598da7c0477c9b278f27e
|
| --- /dev/null
|
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUma.java
|
| @@ -0,0 +1,549 @@
|
| +// Copyright 2015 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.
|
| +
|
| +package org.chromium.chrome.browser.contextualsearch;
|
| +
|
| +import org.chromium.base.metrics.RecordHistogram;
|
| +import org.chromium.chrome.browser.compositor.bottombar.contextualsearch.ContextualSearchPanel.PanelState;
|
| +import org.chromium.chrome.browser.compositor.bottombar.contextualsearch.ContextualSearchPanel.StateChangeReason;
|
| +import org.chromium.chrome.browser.preferences.PrefServiceBridge;
|
| +
|
| +import java.util.Collections;
|
| +import java.util.HashMap;
|
| +import java.util.Map;
|
| +import java.util.concurrent.TimeUnit;
|
| +
|
| +/**
|
| + * Centralizes UMA data collection for Contextual Search. All calls must be made from the UI thread.
|
| + */
|
| +public class ContextualSearchUma {
|
| + // Constants used to log UMA "enum" histograms about the Contextual Search's preference state.
|
| + private static final int PREFERENCE_UNINITIALIZED = 0;
|
| + private static final int PREFERENCE_ENABLED = 1;
|
| + private static final int PREFERENCE_DISABLED = 2;
|
| + private static final int PREFERENCE_HISTOGRAM_BOUNDARY = 3;
|
| +
|
| + // Constants used to log UMA "enum" histograms about whether search results were seen.
|
| + private static final int RESULTS_SEEN = 0;
|
| + private static final int RESULTS_NOT_SEEN = 1;
|
| + private static final int RESULTS_SEEN_BOUNDARY = 2;
|
| +
|
| + // Constants used to log UMA "enum" histograms about whether the selection is valid.
|
| + private static final int SELECTION_VALID = 0;
|
| + private static final int SELECTION_INVALID = 1;
|
| + private static final int SELECTION_BOUNDARY = 2;
|
| +
|
| + // Constants used to log UMA "enum" histograms about a request's outcome.
|
| + private static final int REQUEST_NOT_FAILED = 0;
|
| + private static final int REQUEST_FAILED = 1;
|
| + private static final int REQUEST_BOUNDARY = 2;
|
| +
|
| + // Constants used to log UMA "enum" histograms about the panel's state transitions.
|
| + // Entry code: first entry into CLOSED.
|
| + private static final int ENTER_CLOSED_FROM_OTHER = 0;
|
| + private static final int ENTER_CLOSED_FROM_PEEKED_BACK_PRESS = 1;
|
| + private static final int ENTER_CLOSED_FROM_PEEKED_BASE_PAGE_SCROLL = 2;
|
| + private static final int ENTER_CLOSED_FROM_PEEKED_TEXT_SELECT_TAP = 3;
|
| + private static final int ENTER_CLOSED_FROM_EXPANDED_BACK_PRESS = 4;
|
| + private static final int ENTER_CLOSED_FROM_EXPANDED_BASE_PAGE_TAP = 5;
|
| + private static final int ENTER_CLOSED_FROM_EXPANDED_FLING = 6;
|
| + private static final int ENTER_CLOSED_FROM_MAXIMIZED_BACK_PRESS = 7;
|
| + private static final int ENTER_CLOSED_FROM_MAXIMIZED_FLING = 8;
|
| + private static final int ENTER_CLOSED_FROM_MAXIMIZED_TAB_PROMOTION = 9;
|
| + private static final int ENTER_CLOSED_FROM_MAXIMIZED_SERP_NAVIGATION = 10;
|
| + private static final int ENTER_CLOSED_FROM_BOUNDARY = 11;
|
| +
|
| + // Entry code: first entry into PEEKED.
|
| + private static final int ENTER_PEEKED_FROM_OTHER = 0;
|
| + private static final int ENTER_PEEKED_FROM_CLOSED_TEXT_SELECT_TAP = 1;
|
| + private static final int ENTER_PEEKED_FROM_CLOSED_EXT_SELECT_LONG_PRESS = 2;
|
| + private static final int ENTER_PEEKED_FROM_PEEKED_TEXT_SELECT_TAP = 3;
|
| + private static final int ENTER_PEEKED_FROM_PEEKED_TEXT_SELECT_LONG_PRESS = 4;
|
| + private static final int ENTER_PEEKED_FROM_EXPANDED_SEARCH_BAR_TAP = 5;
|
| + private static final int ENTER_PEEKED_FROM_EXPANDED_SWIPE = 6;
|
| + private static final int ENTER_PEEKED_FROM_EXPANDED_FLING = 7;
|
| + private static final int ENTER_PEEKED_FROM_MAXIMIZED_SWIPE = 8;
|
| + private static final int ENTER_PEEKED_FROM_MAXIMIZED_FLING = 9;
|
| + private static final int ENTER_PEEKED_FROM_BOUNDARY = 10;
|
| +
|
| + // Entry code: first entry into EXPANDED.
|
| + private static final int ENTER_EXPANDED_FROM_OTHER = 0;
|
| + private static final int ENTER_EXPANDED_FROM_PEEKED_SEARCH_BAR_TAP = 1;
|
| + private static final int ENTER_EXPANDED_FROM_PEEKED_SWIPE = 2;
|
| + private static final int ENTER_EXPANDED_FROM_PEEKED_FLING = 3;
|
| + private static final int ENTER_EXPANDED_FROM_MAXIMIZED_SWIPE = 4;
|
| + private static final int ENTER_EXPANDED_FROM_MAXIMIZED_FLING = 5;
|
| + private static final int ENTER_EXPANDED_FROM_BOUNDARY = 6;
|
| +
|
| + // Entry code: first entry into MAXIMIZED.
|
| + private static final int ENTER_MAXIMIZED_FROM_OTHER = 0;
|
| + private static final int ENTER_MAXIMIZED_FROM_PEEKED_SWIPE = 1;
|
| + private static final int ENTER_MAXIMIZED_FROM_PEEKED_FLING = 2;
|
| + private static final int ENTER_MAXIMIZED_FROM_EXPANDED_SWIPE = 3;
|
| + private static final int ENTER_MAXIMIZED_FROM_EXPANDED_FLING = 4;
|
| + private static final int ENTER_MAXIMIZED_FROM_EXPANDED_SERP_NAVIGATION = 5;
|
| + private static final int ENTER_MAXIMIZED_FROM_BOUNDARY = 6;
|
| +
|
| + // Exit code: first exit from CLOSED (or UNDEFINED).
|
| + private static final int EXIT_CLOSED_TO_OTHER = 0;
|
| + private static final int EXIT_CLOSED_TO_PEEKED_TEXT_SELECT_TAP = 1;
|
| + private static final int EXIT_CLOSED_TO_PEEKED_TEXT_SELECT_LONG_PRESS = 2;
|
| + private static final int EXIT_CLOSED_TO_BOUNDARY = 3;
|
| +
|
| + // Exit code: first exit from PEEKED.
|
| + private static final int EXIT_PEEKED_TO_OTHER = 0;
|
| + private static final int EXIT_PEEKED_TO_CLOSED_BACK_PRESS = 1;
|
| + private static final int EXIT_PEEKED_TO_CLOSED_BASE_PAGE_SCROLL = 2;
|
| + private static final int EXIT_PEEKED_TO_CLOSED_TEXT_SELECT_TAP = 3;
|
| + private static final int EXIT_PEEKED_TO_PEEKED_TEXT_SELECT_TAP = 4;
|
| + private static final int EXIT_PEEKED_TO_PEEKED_TEXT_SELECT_LONG_PRESS = 5;
|
| + private static final int EXIT_PEEKED_TO_EXPANDED_SEARCH_BAR_TAP = 6;
|
| + private static final int EXIT_PEEKED_TO_EXPANDED_SWIPE = 7;
|
| + private static final int EXIT_PEEKED_TO_EXPANDED_FLING = 8;
|
| + private static final int EXIT_PEEKED_TO_MAXIMIZED_SWIPE = 9;
|
| + private static final int EXIT_PEEKED_TO_MAXIMIZED_FLING = 10;
|
| + private static final int EXIT_PEEKED_TO_BOUNDARY = 11;
|
| +
|
| + // Exit code: first exit from EXPANDED.
|
| + private static final int EXIT_EXPANDED_TO_OTHER = 0;
|
| + private static final int EXIT_EXPANDED_TO_CLOSED_BACK_PRESS = 1;
|
| + private static final int EXIT_EXPANDED_TO_CLOSED_BASE_PAGE_TAP = 2;
|
| + private static final int EXIT_EXPANDED_TO_CLOSED_FLING = 3;
|
| + private static final int EXIT_EXPANDED_TO_PEEKED_SEARCH_BAR_TAP = 4;
|
| + private static final int EXIT_EXPANDED_TO_PEEKED_SWIPE = 5;
|
| + private static final int EXIT_EXPANDED_TO_PEEKED_FLING = 6;
|
| + private static final int EXIT_EXPANDED_TO_MAXIMIZED_SWIPE = 7;
|
| + private static final int EXIT_EXPANDED_TO_MAXIMIZED_FLING = 8;
|
| + private static final int EXIT_EXPANDED_TO_MAXIMIZED_SERP_NAVIGATION = 9;
|
| + private static final int EXIT_EXPANDED_TO_BOUNDARY = 10;
|
| +
|
| + // Exit code: first exit from MAXIMIZED.
|
| + private static final int EXIT_MAXIMIZED_TO_OTHER = 0;
|
| + private static final int EXIT_MAXIMIZED_TO_CLOSED_BACK_PRESS = 1;
|
| + private static final int EXIT_MAXIMIZED_TO_CLOSED_FLING = 2;
|
| + private static final int EXIT_MAXIMIZED_TO_CLOSED_TAB_PROMOTION = 3;
|
| + private static final int EXIT_MAXIMIZED_TO_CLOSED_SERP_NAVIGATION = 4;
|
| + private static final int EXIT_MAXIMIZED_TO_PEEKED_SWIPE = 5;
|
| + private static final int EXIT_MAXIMIZED_TO_PEEKED_FLING = 6;
|
| + private static final int EXIT_MAXIMIZED_TO_EXPANDED_SWIPE = 7;
|
| + private static final int EXIT_MAXIMIZED_TO_EXPANDED_FLING = 8;
|
| + private static final int EXIT_MAXIMIZED_TO_BOUNDARY = 9;
|
| +
|
| + /**
|
| + * Key used in maps from {state, reason} to state entry (exit) logging code.
|
| + */
|
| + static class StateChangeKey {
|
| + final PanelState mState;
|
| + final StateChangeReason mReason;
|
| + final int mHashCode;
|
| +
|
| + StateChangeKey(PanelState state, StateChangeReason reason) {
|
| + mState = state;
|
| + mReason = reason;
|
| + mHashCode = 31 * state.hashCode() + reason.hashCode();
|
| + }
|
| +
|
| + @Override
|
| + public boolean equals(Object obj) {
|
| + if (!(obj instanceof StateChangeKey)) {
|
| + return false;
|
| + }
|
| + if (obj == this) {
|
| + return true;
|
| + }
|
| + StateChangeKey other = (StateChangeKey) obj;
|
| + return mState.equals(other.mState) && mReason.equals(other.mReason);
|
| + }
|
| +
|
| + @Override
|
| + public int hashCode() {
|
| + return mHashCode;
|
| + }
|
| + }
|
| +
|
| + // Entry code map: first entry into CLOSED.
|
| + private static final Map<StateChangeKey, Integer> ENTER_CLOSED_STATE_CHANGE_CODES;
|
| + static {
|
| + Map<StateChangeKey, Integer> codes = new HashMap<StateChangeKey, Integer>();
|
| + codes.put(new StateChangeKey(PanelState.PEEKED, StateChangeReason.BACK_PRESS),
|
| + ENTER_CLOSED_FROM_PEEKED_BACK_PRESS);
|
| + codes.put(new StateChangeKey(PanelState.PEEKED, StateChangeReason.BASE_PAGE_SCROLL),
|
| + ENTER_CLOSED_FROM_PEEKED_BASE_PAGE_SCROLL);
|
| + codes.put(new StateChangeKey(PanelState.PEEKED, StateChangeReason.TEXT_SELECT_TAP),
|
| + ENTER_CLOSED_FROM_PEEKED_TEXT_SELECT_TAP);
|
| + codes.put(new StateChangeKey(PanelState.EXPANDED, StateChangeReason.BACK_PRESS),
|
| + ENTER_CLOSED_FROM_EXPANDED_BACK_PRESS);
|
| + codes.put(new StateChangeKey(PanelState.EXPANDED, StateChangeReason.BASE_PAGE_TAP),
|
| + ENTER_CLOSED_FROM_EXPANDED_BASE_PAGE_TAP);
|
| + codes.put(new StateChangeKey(PanelState.EXPANDED, StateChangeReason.FLING),
|
| + ENTER_CLOSED_FROM_EXPANDED_FLING);
|
| + codes.put(new StateChangeKey(PanelState.MAXIMIZED, StateChangeReason.BACK_PRESS),
|
| + ENTER_CLOSED_FROM_MAXIMIZED_BACK_PRESS);
|
| + codes.put(new StateChangeKey(PanelState.MAXIMIZED, StateChangeReason.FLING),
|
| + ENTER_CLOSED_FROM_MAXIMIZED_FLING);
|
| + codes.put(new StateChangeKey(PanelState.MAXIMIZED, StateChangeReason.TAB_PROMOTION),
|
| + ENTER_CLOSED_FROM_MAXIMIZED_TAB_PROMOTION);
|
| + codes.put(new StateChangeKey(PanelState.MAXIMIZED, StateChangeReason.SERP_NAVIGATION),
|
| + ENTER_CLOSED_FROM_MAXIMIZED_SERP_NAVIGATION);
|
| + ENTER_CLOSED_STATE_CHANGE_CODES = Collections.unmodifiableMap(codes);
|
| + }
|
| +
|
| + // Entry code map: first entry into PEEKED.
|
| + private static final Map<StateChangeKey, Integer> ENTER_PEEKED_STATE_CHANGE_CODES;
|
| + static {
|
| + Map<StateChangeKey, Integer> codes = new HashMap<StateChangeKey, Integer>();
|
| + // Note: we don't distinguish entering PEEKED from UNDEFINED / CLOSED.
|
| + codes.put(new StateChangeKey(PanelState.UNDEFINED, StateChangeReason.TEXT_SELECT_TAP),
|
| + ENTER_PEEKED_FROM_CLOSED_TEXT_SELECT_TAP);
|
| + codes.put(new StateChangeKey(PanelState.UNDEFINED,
|
| + StateChangeReason.TEXT_SELECT_LONG_PRESS),
|
| + ENTER_PEEKED_FROM_CLOSED_EXT_SELECT_LONG_PRESS);
|
| + codes.put(new StateChangeKey(PanelState.CLOSED, StateChangeReason.TEXT_SELECT_TAP),
|
| + ENTER_PEEKED_FROM_CLOSED_TEXT_SELECT_TAP);
|
| + codes.put(new StateChangeKey(PanelState.CLOSED, StateChangeReason.TEXT_SELECT_LONG_PRESS),
|
| + ENTER_PEEKED_FROM_CLOSED_EXT_SELECT_LONG_PRESS);
|
| + codes.put(new StateChangeKey(PanelState.PEEKED, StateChangeReason.TEXT_SELECT_TAP),
|
| + ENTER_PEEKED_FROM_PEEKED_TEXT_SELECT_TAP);
|
| + codes.put(new StateChangeKey(PanelState.PEEKED, StateChangeReason.TEXT_SELECT_LONG_PRESS),
|
| + ENTER_PEEKED_FROM_PEEKED_TEXT_SELECT_LONG_PRESS);
|
| + codes.put(new StateChangeKey(PanelState.EXPANDED, StateChangeReason.SEARCH_BAR_TAP),
|
| + ENTER_PEEKED_FROM_EXPANDED_SEARCH_BAR_TAP);
|
| + codes.put(new StateChangeKey(PanelState.EXPANDED, StateChangeReason.SWIPE),
|
| + ENTER_PEEKED_FROM_EXPANDED_SWIPE);
|
| + codes.put(new StateChangeKey(PanelState.EXPANDED, StateChangeReason.FLING),
|
| + ENTER_PEEKED_FROM_EXPANDED_FLING);
|
| + codes.put(new StateChangeKey(PanelState.MAXIMIZED, StateChangeReason.SWIPE),
|
| + ENTER_PEEKED_FROM_MAXIMIZED_SWIPE);
|
| + codes.put(new StateChangeKey(PanelState.MAXIMIZED, StateChangeReason.FLING),
|
| + ENTER_PEEKED_FROM_MAXIMIZED_FLING);
|
| + ENTER_PEEKED_STATE_CHANGE_CODES = Collections.unmodifiableMap(codes);
|
| + }
|
| +
|
| + // Entry code map: first entry into EXPANDED.
|
| + private static final Map<StateChangeKey, Integer> ENTER_EXPANDED_STATE_CHANGE_CODES;
|
| + static {
|
| + Map<StateChangeKey, Integer> codes = new HashMap<StateChangeKey, Integer>();
|
| + codes.put(new StateChangeKey(PanelState.PEEKED, StateChangeReason.SEARCH_BAR_TAP),
|
| + ENTER_EXPANDED_FROM_PEEKED_SEARCH_BAR_TAP);
|
| + codes.put(new StateChangeKey(PanelState.PEEKED, StateChangeReason.SWIPE),
|
| + ENTER_EXPANDED_FROM_PEEKED_SWIPE);
|
| + codes.put(new StateChangeKey(PanelState.PEEKED, StateChangeReason.FLING),
|
| + ENTER_EXPANDED_FROM_PEEKED_FLING);
|
| + codes.put(new StateChangeKey(PanelState.MAXIMIZED, StateChangeReason.SWIPE),
|
| + ENTER_EXPANDED_FROM_MAXIMIZED_SWIPE);
|
| + codes.put(new StateChangeKey(PanelState.MAXIMIZED, StateChangeReason.FLING),
|
| + ENTER_EXPANDED_FROM_MAXIMIZED_FLING);
|
| + ENTER_EXPANDED_STATE_CHANGE_CODES = Collections.unmodifiableMap(codes);
|
| + }
|
| +
|
| + // Entry code map: first entry into MAXIMIZED.
|
| + private static final Map<StateChangeKey, Integer> ENTER_MAXIMIZED_STATE_CHANGE_CODES;
|
| + static {
|
| + Map<StateChangeKey, Integer> codes = new HashMap<StateChangeKey, Integer>();
|
| + codes.put(new StateChangeKey(PanelState.PEEKED, StateChangeReason.SWIPE),
|
| + ENTER_MAXIMIZED_FROM_PEEKED_SWIPE);
|
| + codes.put(new StateChangeKey(PanelState.PEEKED, StateChangeReason.FLING),
|
| + ENTER_MAXIMIZED_FROM_PEEKED_FLING);
|
| + codes.put(new StateChangeKey(PanelState.EXPANDED, StateChangeReason.SWIPE),
|
| + ENTER_MAXIMIZED_FROM_EXPANDED_SWIPE);
|
| + codes.put(new StateChangeKey(PanelState.EXPANDED, StateChangeReason.FLING),
|
| + ENTER_MAXIMIZED_FROM_EXPANDED_FLING);
|
| + codes.put(new StateChangeKey(PanelState.EXPANDED, StateChangeReason.SERP_NAVIGATION),
|
| + ENTER_MAXIMIZED_FROM_EXPANDED_SERP_NAVIGATION);
|
| + ENTER_MAXIMIZED_STATE_CHANGE_CODES = Collections.unmodifiableMap(codes);
|
| + }
|
| +
|
| + // Exit code map: first exit from CLOSED.
|
| + private static final Map<StateChangeKey, Integer> EXIT_CLOSED_TO_STATE_CHANGE_CODES;
|
| + static {
|
| + Map<StateChangeKey, Integer> codes = new HashMap<StateChangeKey, Integer>();
|
| + codes.put(new StateChangeKey(PanelState.PEEKED, StateChangeReason.TEXT_SELECT_TAP),
|
| + EXIT_CLOSED_TO_PEEKED_TEXT_SELECT_TAP);
|
| + codes.put(new StateChangeKey(PanelState.PEEKED, StateChangeReason.TEXT_SELECT_LONG_PRESS),
|
| + EXIT_CLOSED_TO_PEEKED_TEXT_SELECT_LONG_PRESS);
|
| + EXIT_CLOSED_TO_STATE_CHANGE_CODES = Collections.unmodifiableMap(codes);
|
| + }
|
| +
|
| + // Exit code map: first exit from PEEKED.
|
| + private static final Map<StateChangeKey, Integer> EXIT_PEEKED_TO_STATE_CHANGE_CODES;
|
| + static {
|
| + Map<StateChangeKey, Integer> codes = new HashMap<StateChangeKey, Integer>();
|
| + codes.put(new StateChangeKey(PanelState.CLOSED, StateChangeReason.BACK_PRESS),
|
| + EXIT_PEEKED_TO_CLOSED_BACK_PRESS);
|
| + codes.put(new StateChangeKey(PanelState.CLOSED, StateChangeReason.BASE_PAGE_SCROLL),
|
| + EXIT_PEEKED_TO_CLOSED_BASE_PAGE_SCROLL);
|
| + codes.put(new StateChangeKey(PanelState.CLOSED, StateChangeReason.BASE_PAGE_TAP),
|
| + EXIT_PEEKED_TO_CLOSED_TEXT_SELECT_TAP);
|
| + codes.put(new StateChangeKey(PanelState.PEEKED, StateChangeReason.TEXT_SELECT_TAP),
|
| + EXIT_PEEKED_TO_PEEKED_TEXT_SELECT_TAP);
|
| + codes.put(new StateChangeKey(PanelState.PEEKED, StateChangeReason.TEXT_SELECT_LONG_PRESS),
|
| + EXIT_PEEKED_TO_PEEKED_TEXT_SELECT_LONG_PRESS);
|
| + codes.put(new StateChangeKey(PanelState.EXPANDED, StateChangeReason.SEARCH_BAR_TAP),
|
| + EXIT_PEEKED_TO_EXPANDED_SEARCH_BAR_TAP);
|
| + codes.put(new StateChangeKey(PanelState.EXPANDED, StateChangeReason.SWIPE),
|
| + EXIT_PEEKED_TO_EXPANDED_SWIPE);
|
| + codes.put(new StateChangeKey(PanelState.EXPANDED, StateChangeReason.FLING),
|
| + EXIT_PEEKED_TO_EXPANDED_FLING);
|
| + codes.put(new StateChangeKey(PanelState.MAXIMIZED, StateChangeReason.SWIPE),
|
| + EXIT_PEEKED_TO_MAXIMIZED_SWIPE);
|
| + codes.put(new StateChangeKey(PanelState.MAXIMIZED, StateChangeReason.FLING),
|
| + EXIT_PEEKED_TO_MAXIMIZED_FLING);
|
| + EXIT_PEEKED_TO_STATE_CHANGE_CODES = Collections.unmodifiableMap(codes);
|
| + }
|
| +
|
| + // Exit code map: first exit from EXPANDED.
|
| + private static final Map<StateChangeKey, Integer> EXIT_EXPANDED_TO_STATE_CHANGE_CODES;
|
| + static {
|
| + Map<StateChangeKey, Integer> codes = new HashMap<StateChangeKey, Integer>();
|
| + codes.put(new StateChangeKey(PanelState.CLOSED, StateChangeReason.BACK_PRESS),
|
| + EXIT_EXPANDED_TO_CLOSED_BACK_PRESS);
|
| + codes.put(new StateChangeKey(PanelState.CLOSED, StateChangeReason.BASE_PAGE_TAP),
|
| + EXIT_EXPANDED_TO_CLOSED_BASE_PAGE_TAP);
|
| + codes.put(new StateChangeKey(PanelState.CLOSED, StateChangeReason.FLING),
|
| + EXIT_EXPANDED_TO_CLOSED_FLING);
|
| + codes.put(new StateChangeKey(PanelState.PEEKED, StateChangeReason.SEARCH_BAR_TAP),
|
| + EXIT_EXPANDED_TO_PEEKED_SEARCH_BAR_TAP);
|
| + codes.put(new StateChangeKey(PanelState.PEEKED, StateChangeReason.SWIPE),
|
| + EXIT_EXPANDED_TO_PEEKED_SWIPE);
|
| + codes.put(new StateChangeKey(PanelState.PEEKED, StateChangeReason.FLING),
|
| + EXIT_EXPANDED_TO_PEEKED_FLING);
|
| + codes.put(new StateChangeKey(PanelState.MAXIMIZED, StateChangeReason.SWIPE),
|
| + EXIT_EXPANDED_TO_MAXIMIZED_SWIPE);
|
| + codes.put(new StateChangeKey(PanelState.MAXIMIZED, StateChangeReason.FLING),
|
| + EXIT_EXPANDED_TO_MAXIMIZED_FLING);
|
| + codes.put(new StateChangeKey(PanelState.MAXIMIZED, StateChangeReason.SERP_NAVIGATION),
|
| + EXIT_EXPANDED_TO_MAXIMIZED_SERP_NAVIGATION);
|
| + EXIT_EXPANDED_TO_STATE_CHANGE_CODES = Collections.unmodifiableMap(codes);
|
| + }
|
| +
|
| + // Exit code map: first exit from MAXIMIZED.
|
| + private static final Map<StateChangeKey, Integer> EXIT_MAXIMIZED_TO_STATE_CHANGE_CODES;
|
| + static {
|
| + Map<StateChangeKey, Integer> codes = new HashMap<StateChangeKey, Integer>();
|
| + codes.put(new StateChangeKey(PanelState.CLOSED, StateChangeReason.BACK_PRESS),
|
| + EXIT_MAXIMIZED_TO_CLOSED_BACK_PRESS);
|
| + codes.put(new StateChangeKey(PanelState.CLOSED, StateChangeReason.FLING),
|
| + EXIT_MAXIMIZED_TO_CLOSED_FLING);
|
| + codes.put(new StateChangeKey(PanelState.CLOSED, StateChangeReason.TAB_PROMOTION),
|
| + EXIT_MAXIMIZED_TO_CLOSED_TAB_PROMOTION);
|
| + codes.put(new StateChangeKey(PanelState.CLOSED, StateChangeReason.SERP_NAVIGATION),
|
| + EXIT_MAXIMIZED_TO_CLOSED_SERP_NAVIGATION);
|
| + codes.put(new StateChangeKey(PanelState.PEEKED, StateChangeReason.SWIPE),
|
| + EXIT_MAXIMIZED_TO_PEEKED_SWIPE);
|
| + codes.put(new StateChangeKey(PanelState.PEEKED, StateChangeReason.FLING),
|
| + EXIT_MAXIMIZED_TO_PEEKED_FLING);
|
| + codes.put(new StateChangeKey(PanelState.EXPANDED, StateChangeReason.SWIPE),
|
| + EXIT_MAXIMIZED_TO_EXPANDED_SWIPE);
|
| + codes.put(new StateChangeKey(PanelState.EXPANDED, StateChangeReason.FLING),
|
| + EXIT_MAXIMIZED_TO_EXPANDED_FLING);
|
| + EXIT_MAXIMIZED_TO_STATE_CHANGE_CODES = Collections.unmodifiableMap(codes);
|
| + }
|
| +
|
| + /**
|
| + * Logs the state of the Contextual Search preference. This function should be called if the
|
| + * Contextual Search feature is enabled, and will track the different preference settings
|
| + * (disabled, enabled or uninitialized). Calling more than once is fine.
|
| + */
|
| + public static void logPreferenceState() {
|
| + RecordHistogram.recordEnumeratedHistogram("Search.ContextualSearchPreferenceState",
|
| + getPreferenceValue(), PREFERENCE_HISTOGRAM_BOUNDARY);
|
| + }
|
| +
|
| + /**
|
| + * Logs changes to the Contextual Search preference, aside from those resulting from the first
|
| + * run flow.
|
| + * @param enabled Whether the preference is being enabled or disabled.
|
| + */
|
| + public static void logPreferenceChange(boolean enabled) {
|
| + RecordHistogram.recordEnumeratedHistogram("Search.ContextualSearchPreferenceStateChange",
|
| + enabled ? PREFERENCE_ENABLED : PREFERENCE_DISABLED, PREFERENCE_HISTOGRAM_BOUNDARY);
|
| + }
|
| +
|
| + /**
|
| + * Logs the outcome of a first run flow.
|
| + */
|
| + public static void logFirstRunFlowOutcome() {
|
| + RecordHistogram.recordEnumeratedHistogram("Search.ContextualSearchFirstRunFlowOutcome",
|
| + getPreferenceValue(), PREFERENCE_HISTOGRAM_BOUNDARY);
|
| + }
|
| +
|
| + /**
|
| + * Logs the duration of a Contextual Search.
|
| + * @param wereResultsSeen Whether search results were seen.
|
| + * @param isChained Whether the Contextual Search ended with the start of another.
|
| + * @param durationMs The duration of the contextual search in milliseconds.
|
| + */
|
| + public static void logDuration(boolean wereResultsSeen, boolean isChained, long durationMs) {
|
| + if (wereResultsSeen) {
|
| + RecordHistogram.recordTimesHistogram("Search.ContextualSearchDurationSeen",
|
| + durationMs, TimeUnit.MILLISECONDS);
|
| + } else if (isChained) {
|
| + RecordHistogram.recordTimesHistogram("Search.ContextualSearchDurationUnseenChained",
|
| + durationMs, TimeUnit.MILLISECONDS);
|
| + } else {
|
| + RecordHistogram.recordTimesHistogram("Search.ContextualSearchDurationUnseen",
|
| + durationMs, TimeUnit.MILLISECONDS);
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Logs whether the first run flow's panel was seen during the contextual search. This should
|
| + * only be called when the user exits the contextual search still in the undecided state.
|
| + * @param wasPanelSeen Whether the first run flow's panel was seen.
|
| + */
|
| + public static void logFirstRunPanelSeen(boolean wasPanelSeen) {
|
| + RecordHistogram.recordEnumeratedHistogram("Search.ContextualSearchFirstRunPanelSeen",
|
| + wasPanelSeen ? RESULTS_SEEN : RESULTS_NOT_SEEN, RESULTS_SEEN_BOUNDARY);
|
| + }
|
| +
|
| + /**
|
| + * Logs whether search results were seen during the contextual search.
|
| + * @param wereResultsSeen Whether search results were seen.
|
| + */
|
| + public static void logResultsSeen(boolean wereResultsSeen) {
|
| + RecordHistogram.recordEnumeratedHistogram("Search.ContextualSearchResultsSeen",
|
| + wereResultsSeen ? RESULTS_SEEN : RESULTS_NOT_SEEN, RESULTS_SEEN_BOUNDARY);
|
| + }
|
| +
|
| + /**
|
| + * Logs whether a selection is valid.
|
| + * @param isSelectionValid Whether the selection is valid.
|
| + */
|
| + public static void logSelectionIsValid(boolean isSelectionValid) {
|
| + RecordHistogram.recordEnumeratedHistogram("Search.ContextualSearchSelectionValid",
|
| + isSelectionValid ? SELECTION_VALID : SELECTION_INVALID, SELECTION_BOUNDARY);
|
| + }
|
| +
|
| + /**
|
| + * Logs whether a normal priority search request failed.
|
| + * @param isFailure Whether the request failed.
|
| + */
|
| + public static void logNormalPrioritySearchRequestOutcome(boolean isFailure) {
|
| + RecordHistogram.recordEnumeratedHistogram(
|
| + "Search.ContextualSearchNormalPrioritySearchRequestStatus",
|
| + isFailure ? REQUEST_FAILED : REQUEST_NOT_FAILED, REQUEST_BOUNDARY);
|
| + }
|
| +
|
| + /**
|
| + * Logs whether a low priority search request failed.
|
| + * @param isFailure Whether the request failed.
|
| + */
|
| + public static void logLowPrioritySearchRequestOutcome(boolean isFailure) {
|
| + RecordHistogram.recordEnumeratedHistogram(
|
| + "Search.ContextualSearchLowPrioritySearchRequestStatus",
|
| + isFailure ? REQUEST_FAILED : REQUEST_NOT_FAILED, REQUEST_BOUNDARY);
|
| + }
|
| +
|
| + /**
|
| + * Logs whether a fallback search request failed.
|
| + * @param isFailure Whether the request failed.
|
| + */
|
| + public static void logFallbackSearchRequestOutcome(boolean isFailure) {
|
| + RecordHistogram.recordEnumeratedHistogram(
|
| + "Search.ContextualSearchFallbackSearchRequestStatus",
|
| + isFailure ? REQUEST_FAILED : REQUEST_NOT_FAILED, REQUEST_BOUNDARY);
|
| + }
|
| +
|
| + /**
|
| + * Logs how a state was entered for the first time within a Contextual Search.
|
| + * @param fromState The state to transition from.
|
| + * @param toState The state to transition to.
|
| + * @param reason The reason for the state transition.
|
| + */
|
| + public static void logFirstStateEntry(PanelState fromState, PanelState toState,
|
| + StateChangeReason reason) {
|
| + int code;
|
| + switch (toState) {
|
| + case CLOSED:
|
| + code = getStateChangeCode(fromState, reason,
|
| + ENTER_CLOSED_STATE_CHANGE_CODES, ENTER_CLOSED_FROM_OTHER);
|
| + RecordHistogram.recordEnumeratedHistogram(
|
| + "Search.ContextualSearchEnterClosed",
|
| + code, ENTER_CLOSED_FROM_BOUNDARY);
|
| + break;
|
| + case PEEKED:
|
| + code = getStateChangeCode(fromState, reason,
|
| + ENTER_PEEKED_STATE_CHANGE_CODES, ENTER_PEEKED_FROM_OTHER);
|
| + RecordHistogram.recordEnumeratedHistogram(
|
| + "Search.ContextualSearchEnterPeeked",
|
| + code, ENTER_PEEKED_FROM_BOUNDARY);
|
| + break;
|
| + case EXPANDED:
|
| + code = getStateChangeCode(fromState, reason,
|
| + ENTER_EXPANDED_STATE_CHANGE_CODES, ENTER_EXPANDED_FROM_OTHER);
|
| + RecordHistogram.recordEnumeratedHistogram(
|
| + "Search.ContextualSearchEnterExpanded",
|
| + code, ENTER_EXPANDED_FROM_BOUNDARY);
|
| + break;
|
| + case MAXIMIZED:
|
| + code = getStateChangeCode(fromState, reason,
|
| + ENTER_MAXIMIZED_STATE_CHANGE_CODES, ENTER_MAXIMIZED_FROM_OTHER);
|
| + RecordHistogram.recordEnumeratedHistogram(
|
| + "Search.ContextualSearchEnterMaximized",
|
| + code, ENTER_MAXIMIZED_FROM_BOUNDARY);
|
| + break;
|
| + default:
|
| + break;
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Logs how a state was exited for the first time within a Contextual Search.
|
| + * @param fromState The state to transition from.
|
| + * @param toState The state to transition to.
|
| + * @param reason The reason for the state transition.
|
| + */
|
| + public static void logFirstStateExit(PanelState fromState, PanelState toState,
|
| + StateChangeReason reason) {
|
| + int code;
|
| + switch (fromState) {
|
| + case UNDEFINED:
|
| + case CLOSED:
|
| + code = getStateChangeCode(toState, reason,
|
| + EXIT_CLOSED_TO_STATE_CHANGE_CODES, EXIT_CLOSED_TO_OTHER);
|
| + RecordHistogram.recordEnumeratedHistogram(
|
| + "Search.ContextualSearchExitClosed", code, EXIT_CLOSED_TO_BOUNDARY);
|
| + break;
|
| + case PEEKED:
|
| + code = getStateChangeCode(toState, reason,
|
| + EXIT_PEEKED_TO_STATE_CHANGE_CODES, EXIT_PEEKED_TO_OTHER);
|
| + RecordHistogram.recordEnumeratedHistogram(
|
| + "Search.ContextualSearchExitPeeked", code, EXIT_PEEKED_TO_BOUNDARY);
|
| + break;
|
| + case EXPANDED:
|
| + code = getStateChangeCode(toState, reason,
|
| + EXIT_EXPANDED_TO_STATE_CHANGE_CODES, EXIT_EXPANDED_TO_OTHER);
|
| + RecordHistogram.recordEnumeratedHistogram(
|
| + "Search.ContextualSearchExitExpanded", code, EXIT_EXPANDED_TO_BOUNDARY);
|
| + break;
|
| + case MAXIMIZED:
|
| + code = getStateChangeCode(toState, reason,
|
| + EXIT_MAXIMIZED_TO_STATE_CHANGE_CODES, EXIT_MAXIMIZED_TO_OTHER);
|
| + RecordHistogram.recordEnumeratedHistogram(
|
| + "Search.ContextualSearchExitMaximized", code, EXIT_MAXIMIZED_TO_BOUNDARY);
|
| + break;
|
| + default:
|
| + break;
|
| + }
|
| + }
|
| +
|
| + private static int getStateChangeCode(PanelState state, StateChangeReason reason,
|
| + Map<StateChangeKey, Integer> stateChangeCodes, int defaultCode) {
|
| + Integer code = stateChangeCodes.get(new StateChangeKey(state, reason));
|
| + if (code != null) {
|
| + return code;
|
| + }
|
| + return defaultCode;
|
| + }
|
| +
|
| + private static int getPreferenceValue() {
|
| + PrefServiceBridge preferences = PrefServiceBridge.getInstance();
|
| + if (preferences.isContextualSearchUninitialized()) {
|
| + return PREFERENCE_UNINITIALIZED;
|
| + } else if (preferences.isContextualSearchDisabled()) {
|
| + return PREFERENCE_DISABLED;
|
| + }
|
| + return PREFERENCE_ENABLED;
|
| + }
|
| +}
|
|
|