Shorten and clean ContextualSearchFieldTrial.java

Before: file contains many similar methods and variable definitions.

After: there are created tables for integer and boolean values indexed by @IntDef, which are handled by two methods. It makes code and APK shorter.

Change-Id: I549b288f53a7644601179b1477e8a05d2e9b2de7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1565311
Commit-Queue: Marcin Wiącek <marcin@mwiacek.com>
Reviewed-by: Donn Denman <donnd@chromium.org>
Cr-Commit-Position: refs/heads/master@{#652704}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/BarOverlapTapSuppression.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/BarOverlapTapSuppression.java
index 52c5890..15cb293 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/BarOverlapTapSuppression.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/BarOverlapTapSuppression.java
@@ -5,6 +5,7 @@
 package org.chromium.chrome.browser.contextualsearch;
 
 import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial.ContextualSearchSwitch;
 import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
 import org.chromium.chrome.browser.tab.Tab;
 
@@ -30,7 +31,8 @@
         // after isCoordinateInsideBar(x, y).
         mPxToDp = selectionController.getPxToDp();
         mActivity = selectionController.getActivity();
-        mIsEnabled = ContextualSearchFieldTrial.isBarOverlapSuppressionEnabled();
+        mIsEnabled = ContextualSearchFieldTrial.getSwitch(
+                ContextualSearchSwitch.IS_BAR_OVERLAP_SUPPRESSION_ENABLED);
         mIsConditionSatisfied = doesBarOverlap(y);
     }
 
@@ -48,7 +50,8 @@
 
     @Override
     protected void logResultsSeen(boolean wasSearchContentViewSeen, boolean wasActivatedByTap) {
-        if (ContextualSearchFieldTrial.isBarOverlapCollectionEnabled()) {
+        if (ContextualSearchFieldTrial.getSwitch(
+                    ContextualSearchSwitch.IS_BAR_OVERLAP_COLLECTION_ENABLED)) {
             ContextualSearchUma.logBarOverlapResultsSeen(
                     wasSearchContentViewSeen, wasActivatedByTap, mIsConditionSatisfied);
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchEntityHeuristic.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchEntityHeuristic.java
index 8e71a8dc..5cb67902 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchEntityHeuristic.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchEntityHeuristic.java
@@ -8,6 +8,7 @@
 
 import org.chromium.base.CollectionUtil;
 import org.chromium.base.VisibleForTesting;
+import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial.ContextualSearchSwitch;
 
 import java.util.HashSet;
 import java.util.Locale;
@@ -59,7 +60,9 @@
      *        out the words around what has been tapped.
      */
     ContextualSearchEntityHeuristic(ContextualSearchContext contextualSearchContext) {
-        this(contextualSearchContext, ContextualSearchFieldTrial.isNotAnEntitySuppressionEnabled());
+        this(contextualSearchContext,
+                ContextualSearchFieldTrial.getSwitch(
+                        ContextualSearchSwitch.IS_NOT_AN_ENTITY_SUPPRESSION_ENABLED));
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java
index c58ff75..639e0cb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.contextualsearch;
 
+import android.support.annotation.IntDef;
 import android.text.TextUtils;
 
 import org.chromium.base.CommandLine;
@@ -13,6 +14,9 @@
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.components.variations.VariationsAssociatedData;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * Provides Field Trial support for the Contextual Search application within Chrome for Android.
  */
@@ -21,114 +25,244 @@
     private static final String DISABLED_PARAM = "disabled";
     private static final String ENABLED_VALUE = "true";
 
-    static final String MANDATORY_PROMO_ENABLED = "mandatory_promo_enabled";
-    static final String MANDATORY_PROMO_LIMIT = "mandatory_promo_limit";
-    static final int MANDATORY_PROMO_DEFAULT_LIMIT = 10;
-
-    private static final String DISABLE_SEARCH_TERM_RESOLUTION = "disable_search_term_resolution";
-    private static final String WAIT_AFTER_TAP_DELAY_MS = "wait_after_tap_delay_ms";
-
-    // ------------
-    // Translation.
-    // ------------
-    // All these members are private, except for usage by testing.
-    // Master switch, needed to disable all translate code for Contextual Search in case of an
-    // emergency.
-    @VisibleForTesting
-    static final String DISABLE_TRANSLATION = "disable_translation";
-    // Enables usage of English as the target language even when it's the primary UI language.
-    @VisibleForTesting
-    static final String ENABLE_ENGLISH_TARGET_TRANSLATION =
-            "enable_english_target_translation";
-
-    // ---------------------------------------------
-    // Features for suppression or machine learning.
-    // ---------------------------------------------
-    // TODO(donnd): remove all supporting code once short-lived data collection is done.
-    private static final String SCREEN_TOP_SUPPRESSION_DPS = "screen_top_suppression_dps";
-    private static final String ENABLE_BAR_OVERLAP_COLLECTION = "enable_bar_overlap_collection";
-    private static final String BAR_OVERLAP_SUPPRESSION_ENABLED = "enable_bar_overlap_suppression";
-    private static final String WORD_EDGE_SUPPRESSION_ENABLED = "enable_word_edge_suppression";
-    private static final String SHORT_WORD_SUPPRESSION_ENABLED = "enable_short_word_suppression";
-    private static final String NOT_LONG_WORD_SUPPRESSION_ENABLED =
-            "enable_not_long_word_suppression";
-    private static final String SHORT_TEXT_RUN_SUPPRESSION_ENABLED =
-            "enable_short_text_run_suppression";
-    private static final String SMALL_TEXT_SUPPRESSION_ENABLED = "enable_small_text_suppression";
-    static final String ENGAGEMENT_SUPPRESSION_ENABLED = "enable_engagement_suppression";
-    @VisibleForTesting
-    static final String NOT_AN_ENTITY_SUPPRESSION_ENABLED = "enable_not_an_entity_suppression";
-    // The threshold for tap suppression based on duration.
-    private static final String TAP_DURATION_THRESHOLD_MS = "tap_duration_threshold_ms";
-    // The threshold for tap suppression based on a recent scroll.
-    private static final String RECENT_SCROLL_DURATION_MS = "recent_scroll_duration_ms";
-
-    private static final String MINIMUM_SELECTION_LENGTH = "minimum_selection_length";
-
-    // -----------------
-    // Disable switches.
-    // -----------------
-    // Safety switch for disabling online-detection.  Also used to disable detection when running
-    // tests.
-    @VisibleForTesting
-    static final String ONLINE_DETECTION_DISABLED = "disable_online_detection";
-    private static final String DISABLE_AMP_AS_SEPARATE_TAB = "disable_amp_as_separate_tab";
-    // Disable logging for Machine Learning
-    private static final String DISABLE_UKM_RANKER_LOGGING = "disable_ukm_ranker_logging";
-
-    // ----------------------
-    // Privacy-related flags.
-    // ----------------------
-    private static final String DISABLE_SEND_HOME_COUNTRY = "disable_send_home_country";
-    private static final String DISABLE_PAGE_CONTENT_NOTIFICATION =
-            "disable_page_content_notification";
+    private static final int MANDATORY_PROMO_DEFAULT_LIMIT = 10;
 
     // Cached values to avoid repeated and redundant JNI operations.
-    // TODO(donnd): consider creating a single Map to cache these static values.
     private static Boolean sEnabled;
-    private static Boolean sDisableSearchTermResolution;
-    private static Boolean sIsMandatoryPromoEnabled;
-    private static Integer sMandatoryPromoLimit;
-    private static Boolean sIsTranslationDisabled;
-    private static Boolean sIsEnglishTargetTranslationEnabled;
-    private static Integer sScreenTopSuppressionDps;
-    private static Boolean sIsBarOverlapCollectionEnabled;
-    private static Boolean sIsBarOverlapSuppressionEnabled;
-    private static Boolean sIsWordEdgeSuppressionEnabled;
-    private static Boolean sIsShortWordSuppressionEnabled;
-    private static Boolean sIsNotLongWordSuppressionEnabled;
-    private static Boolean sIsNotAnEntitySuppressionEnabled;
-    private static Boolean sIsEngagementSuppressionEnabled;
-    private static Boolean sIsShortTextRunSuppressionEnabled;
-    private static Boolean sIsSmallTextSuppressionEnabled;
-    private static Integer sMinimumSelectionLength;
-    private static Boolean sIsOnlineDetectionDisabled;
-    private static Boolean sIsAmpAsSeparateTabDisabled;
-    private static Boolean sContextualSearchMlTapSuppressionEnabled;
-    private static Boolean sContextualSearchSecondTapMlOverrideEnabled;
-    private static Boolean sContextualSearchTapDisableOverrideEnabled;
-    private static Boolean sIsSendHomeCountryDisabled;
-    private static Boolean sIsPageContentNotificationDisabled;
-    private static Boolean sIsUkmRankerLoggingDisabled;
-    private static Integer sWaitAfterTapDelayMs;
-    private static Integer sTapDurationThresholdMs;
-    private static Integer sRecentScrollDurationMs;
+    private static Boolean[] sSwitches = new Boolean[ContextualSearchSwitch.NUM_ENTRIES];
+    private static Integer[] sSettings = new Integer[ContextualSearchSetting.NUM_ENTRIES];
 
+    // TODO(donnd): remove all supporting code once short-lived data collection is done.
+    @IntDef({ContextualSearchSwitch.IS_SEARCH_TERM_RESOLUTION_DISABLED,
+            ContextualSearchSwitch.IS_MANDATORY_PROMO_ENABLED,
+            ContextualSearchSwitch.IS_TRANSLATION_DISABLED,
+            ContextualSearchSwitch.IS_ENGLISH_TARGET_TRANSLATION_ENABLED,
+            ContextualSearchSwitch.IS_BAR_OVERLAP_COLLECTION_ENABLED,
+            ContextualSearchSwitch.IS_BAR_OVERLAP_SUPPRESSION_ENABLED,
+            ContextualSearchSwitch.IS_WORD_EDGE_SUPPRESSION_ENABLED,
+            ContextualSearchSwitch.IS_SHORT_WORD_SUPPRESSION_ENABLED,
+            ContextualSearchSwitch.IS_NOT_LONG_WORD_SUPPRESSION_ENABLED,
+            ContextualSearchSwitch.IS_NOT_AN_ENTITY_SUPPRESSION_ENABLED,
+            ContextualSearchSwitch.IS_ENGAGEMENT_SUPPRESSION_ENABLED,
+            ContextualSearchSwitch.IS_SHORT_TEXT_RUN_SUPPRESSION_ENABLED,
+            ContextualSearchSwitch.IS_SMALL_TEXT_SUPPRESSION_ENABLED,
+            ContextualSearchSwitch.IS_ONLINE_DETECTION_DISABLED,
+            ContextualSearchSwitch.IS_AMP_AS_SEPARATE_TAB_DISABLED,
+            ContextualSearchSwitch.IS_CONTEXTUAL_SEARCH_ML_TAP_SUPPRESSION_ENABLED,
+            ContextualSearchSwitch.IS_CONTEXTUAL_SEARCH_SECOND_TAP_ML_OVERRIDE_ENABLED,
+            ContextualSearchSwitch.IS_CONTEXTUAL_SEARCH_TAP_DISABLE_OVERRIDE_ENABLED,
+            ContextualSearchSwitch.IS_SEND_HOME_COUNTRY_DISABLED,
+            ContextualSearchSwitch.IS_PAGE_CONTENT_NOTIFICATION_DISABLED,
+            ContextualSearchSwitch.IS_UKM_RANKER_LOGGING_DISABLED})
+    @Retention(RetentionPolicy.SOURCE)
     /**
-     * Don't instantiate.
+     * Boolean Switch values that are backed by either a Feature or a Variations parameter.
+     * Values are used for indexing ContextualSearchSwitchNames - should start from 0 and can't
+     * have gaps.
      */
-    private ContextualSearchFieldTrial() {}
+    @interface ContextualSearchSwitch {
+        int IS_SEARCH_TERM_RESOLUTION_DISABLED = 0;
+        int IS_MANDATORY_PROMO_ENABLED = 1;
+        /**
+         * Whether all translate code is disabled (master switch, needed to disable all translate
+         * code for Contextual Search in case of an emergency).
+         */
+        int IS_TRANSLATION_DISABLED = 2;
+        /**
+         * Whether English-target translation should be enabled (default is disabled for 'en').
+         * Enables usage of English as the target language even when it's the primary UI language.
+         */
+        int IS_ENGLISH_TARGET_TRANSLATION_ENABLED = 3;
+        /** Whether collecting data on Bar overlap is enabled. */
+        int IS_BAR_OVERLAP_COLLECTION_ENABLED = 4;
+        /**
+         * Whether triggering is suppressed by a selection nearly overlapping the normal
+         * Bar peeking location.
+         */
+        int IS_BAR_OVERLAP_SUPPRESSION_ENABLED = 5;
+        /** Whether triggering is suppressed by a tap that's near the edge of a word. */
+        int IS_WORD_EDGE_SUPPRESSION_ENABLED = 6;
+        /** Whether triggering is suppressed by a tap that's in a short word. */
+        int IS_SHORT_WORD_SUPPRESSION_ENABLED = 7;
+        /** Whether triggering is suppressed by a tap that's not in a long word. */
+        int IS_NOT_LONG_WORD_SUPPRESSION_ENABLED = 8;
+        /** Whether triggering is suppressed for a tap that's not on an entity. */
+        int IS_NOT_AN_ENTITY_SUPPRESSION_ENABLED = 9;
+        /** Whether triggering is suppressed due to lack of engagement with the feature. */
+        int IS_ENGAGEMENT_SUPPRESSION_ENABLED = 10;
+        /** Whether triggering is suppressed for a tap that has a short element run-length. */
+        int IS_SHORT_TEXT_RUN_SUPPRESSION_ENABLED = 11;
+        /** Whether triggering is suppressed for a tap on small-looking text. */
+        int IS_SMALL_TEXT_SUPPRESSION_ENABLED = 12;
+        /**
+         * Whether detection of device-online should be disabled (default false).
+         * (safety switch for disabling online-detection also used to disable detection when
+         * running tests).
+         */
+        // TODO(donnd): Convert to test-only after launch and we have confidence it's robust.
+        int IS_ONLINE_DETECTION_DISABLED = 13;
+        /**
+         * Whether to disable auto-promotion of clicks in the AMP carousel into a
+         * separate Tab.
+         */
+        int IS_AMP_AS_SEPARATE_TAB_DISABLED = 14;
+        /** Whether or not ML-based Tap suppression is enabled. */
+        int IS_CONTEXTUAL_SEARCH_ML_TAP_SUPPRESSION_ENABLED = 15;
+        /** Whether or not to override an ML-based Tap suppression on a second tap. */
+        int IS_CONTEXTUAL_SEARCH_SECOND_TAP_ML_OVERRIDE_ENABLED = 16;
+        /**
+         * Whether or not to override tap-disable for users that have never opened the
+         * panel.
+         */
+        int IS_CONTEXTUAL_SEARCH_TAP_DISABLE_OVERRIDE_ENABLED = 17;
+        /** Whether sending the "home country" to Google is disabled. */
+        int IS_SEND_HOME_COUNTRY_DISABLED = 18;
+        /**
+         * Whether sending the page content notifications to observers (e.g. icing for
+         * conversational search) is disabled.
+         */
+        int IS_PAGE_CONTENT_NOTIFICATION_DISABLED = 19;
+        /** Whether logging for Machine Learning is disabled. */
+        int IS_UKM_RANKER_LOGGING_DISABLED = 20;
+
+        int NUM_ENTRIES = 21;
+    }
+
+    @VisibleForTesting
+    static final String ONLINE_DETECTION_DISABLED = "disable_online_detection";
+    @VisibleForTesting
+    static final String TRANSLATION_DISABLED = "disable_translation";
+
+    // Indexed by ContextualSearchSwitch
+    private static final String[] ContextualSearchSwitchNames = {
+            "disable_search_term_resolution", // DISABLE_SEARCH_TERM_RESOLUTION
+            "mandatory_promo_enabled", // IS_MANDATORY_PROMO_ENABLED
+            TRANSLATION_DISABLED, // IS_TRANSLATION_DISABLED
+            "enable_english_target_translation", // IS_ENGLISH_TARGET_TRANSLATION_ENABLED
+            "enable_bar_overlap_collection", // IS_BAR_OVERLAP_COLLECTION_ENABLED
+            "enable_bar_overlap_suppression", // IS_BAR_OVERLAP_SUPPRESSION_ENABLED
+            "enable_word_edge_suppression", // IS_WORD_EDGE_SUPPRESSION_ENABLED
+            "enable_short_word_suppression", //  IS_SHORT_WORD_SUPPRESSION_ENABLED
+            "enable_not_long_word_suppression", // IS_NOT_LONG_WORD_SUPPRESSION_ENABLED
+            "enable_not_an_entity_suppression", //  IS_NOT_AN_ENTITY_SUPPRESSION_ENABLED
+            "enable_engagement_suppression", // IS_ENGAGEMENT_SUPPRESSION_ENABLED
+            "enable_short_text_run_suppression", // IS_SHORT_TEXT_RUN_SUPPRESSION_ENABLED
+            "enable_small_text_suppression", // IS_SMALL_TEXT_SUPPRESSION_ENABLED
+            ONLINE_DETECTION_DISABLED, // IS_ONLINE_DETECTION_DISABLED
+            "disable_amp_as_separate_tab", // IS_AMP_AS_SEPARATE_TAB_DISABLED
+            "", // empty (switch related to Chrome Feature CONTEXTUAL_SEARCH_ML_TAP_SUPPRESSION)
+            "", // empty (switch related to Chrome Feature CONTEXTUAL_SEARCH_SECOND_TAP)
+            "", // empty (switch related to Chrome Feature CONTEXTUAL_SEARCH_TAP_DISABLE_OVERRIDE)
+            "disable_send_home_country", //  IS_SEND_HOME_COUNTRY_DISABLED
+            "disable_page_content_notification", // IS_PAGE_CONTENT_NOTIFICATION_DISABLED
+            "disable_ukm_ranker_logging" // IS_UKM_RANKER_LOGGING_DISABLED
+    };
+
+    @IntDef({ContextualSearchSetting.MANDATORY_PROMO_LIMIT,
+            ContextualSearchSetting.SCREEN_TOP_SUPPRESSION_DPS,
+            ContextualSearchSetting.MINIMUM_SELECTION_LENGTH,
+            ContextualSearchSetting.WAIT_AFTER_TAP_DELAY_MS,
+            ContextualSearchSetting.TAP_DURATION_THRESHOLD_MS,
+            ContextualSearchSetting.RECENT_SCROLL_DURATION_MS})
+    @Retention(RetentionPolicy.SOURCE)
+    /**
+     * These are integer Setting values that are backed by a Variation Param.
+     * Values are used for indexing ContextualSearchSwitchStrings - should start from 0 and can't
+     * have gaps.
+     */
+    @interface ContextualSearchSetting {
+        /** The number of times the Promo should be seen before it becomes mandatory. */
+        int MANDATORY_PROMO_LIMIT = 0;
+        /**
+         * A Y value limit that will suppress a Tap near the top of the screen.
+         * (any Y value less than the limit will suppress the Tap trigger).
+         */
+        int SCREEN_TOP_SUPPRESSION_DPS = 1;
+        /** The minimum valid selection length. */
+        int MINIMUM_SELECTION_LENGTH = 2;
+        /**
+         * An amount to delay after a Tap gesture is recognized, in case some user gesture
+         * immediately follows that would prevent the UI from showing.
+         * The classic example is a scroll, which might be a signal that the previous tap was
+         * accidental.
+         */
+        int WAIT_AFTER_TAP_DELAY_MS = 3;
+        /**
+         * A threshold for the duration of a tap gesture for categorization as brief or
+         * lengthy (the maximum amount of time in milliseconds for a tap gesture that's still
+         * considered a very brief duration tap).
+         */
+        int TAP_DURATION_THRESHOLD_MS = 4;
+        /**
+         * The duration to use for suppressing Taps after a recent scroll, or {@code 0} if no
+         * suppression is configured (the period of time after a scroll when tap triggering is
+         * suppressed).
+         */
+        int RECENT_SCROLL_DURATION_MS = 5;
+
+        int NUM_ENTRIES = 6;
+    }
+
+    // Indexed by ContextualSearchSetting
+    private static final String[] ContextualSearchSettingNames = {
+            "mandatory_promo_limit", // MANDATORY_PROMO_LIMIT
+            "screen_top_suppression_dps", // SCREEN_TOP_SUPPRESSION_DPS
+            "minimum_selection_length", // MINIMUM_SELECTION_LENGTH
+            "wait_after_tap_delay_ms", // WAIT_AFTER_TAP_DELAY_MS
+            "tap_duration_threshold_ms", // TAP_DURATION_THRESHOLD_MS
+            "recent_scroll_duration_ms" // RECENT_SCROLL_DURATION_MS
+    };
+
+    private ContextualSearchFieldTrial() {
+        assert ContextualSearchSwitchNames.length == ContextualSearchSwitch.NUM_ENTRIES;
+        assert ContextualSearchSettingNames.length == ContextualSearchSetting.NUM_ENTRIES;
+    }
 
     /**
-     * Checks the current Variations parameters associated with the active group as well as the
-     * Chrome preference to determine if the service is enabled.
-     * @return Whether Contextual Search is enabled or not.
+     * Current Variations parameters associated with the ContextualSearch Field Trial or a
+     * Chrome Feature to determine if the service is enabled
+     * (whether Contextual Search is enabled or not).
      */
     public static boolean isEnabled() {
         if (sEnabled == null) sEnabled = detectEnabled();
         return sEnabled.booleanValue();
     }
 
+    static boolean getSwitch(@ContextualSearchSwitch int value) {
+        if (sSwitches[value] == null) {
+            String feature = null;
+            if (value == ContextualSearchSwitch.IS_CONTEXTUAL_SEARCH_ML_TAP_SUPPRESSION_ENABLED) {
+                feature = ChromeFeatureList.CONTEXTUAL_SEARCH_ML_TAP_SUPPRESSION;
+            } else if (value
+                    == ContextualSearchSwitch.IS_CONTEXTUAL_SEARCH_SECOND_TAP_ML_OVERRIDE_ENABLED) {
+                feature = ChromeFeatureList.CONTEXTUAL_SEARCH_SECOND_TAP;
+            } else if (value
+                    == ContextualSearchSwitch.IS_CONTEXTUAL_SEARCH_TAP_DISABLE_OVERRIDE_ENABLED) {
+                feature = ChromeFeatureList.CONTEXTUAL_SEARCH_TAP_DISABLE_OVERRIDE;
+            } else {
+                assert !TextUtils.isEmpty(ContextualSearchSwitchNames[value]);
+            }
+            sSwitches[value] = feature != null
+                    ? ChromeFeatureList.isEnabled(feature)
+                    : getBooleanParam(ContextualSearchSwitchNames[value]);
+        }
+        return sSwitches[value].booleanValue();
+    }
+
+    static int getValue(@ContextualSearchSetting int value) {
+        if (sSettings[value] == null) {
+            sSettings[value] = getIntParamValueOrDefault(ContextualSearchSettingNames[value],
+                    value == ContextualSearchSetting.MANDATORY_PROMO_LIMIT
+                            ? MANDATORY_PROMO_DEFAULT_LIMIT
+                            : 0);
+        }
+        return sSettings[value].intValue();
+    }
+
+    // --------------------------------------------------------------------------------------------
+    // Helpers.
+    // --------------------------------------------------------------------------------------------
+
     private static boolean detectEnabled() {
         if (SysUtils.isLowEndDevice()) return false;
 
@@ -149,305 +283,10 @@
     }
 
     /**
-     * @return Whether the search term resolution is disabled.
-     */
-    static boolean isSearchTermResolutionDisabled() {
-        if (sDisableSearchTermResolution == null) {
-            sDisableSearchTermResolution = getBooleanParam(DISABLE_SEARCH_TERM_RESOLUTION);
-        }
-        return sDisableSearchTermResolution.booleanValue();
-    }
-
-    /**
-     * @return Whether the Mandatory Promo is enabled.
-     */
-    static boolean isMandatoryPromoEnabled() {
-        if (sIsMandatoryPromoEnabled == null) {
-            sIsMandatoryPromoEnabled = getBooleanParam(MANDATORY_PROMO_ENABLED);
-        }
-        return sIsMandatoryPromoEnabled.booleanValue();
-    }
-
-    /**
-     * @return The number of times the Promo should be seen before it becomes mandatory.
-     */
-    static int getMandatoryPromoLimit() {
-        if (sMandatoryPromoLimit == null) {
-            sMandatoryPromoLimit = getIntParamValueOrDefault(
-                    MANDATORY_PROMO_LIMIT,
-                    MANDATORY_PROMO_DEFAULT_LIMIT);
-        }
-        return sMandatoryPromoLimit.intValue();
-    }
-
-    /**
-     * @return Whether all translate code is disabled.
-     */
-    static boolean isTranslationDisabled() {
-        if (sIsTranslationDisabled == null) {
-            sIsTranslationDisabled = getBooleanParam(DISABLE_TRANSLATION);
-        }
-        return sIsTranslationDisabled.booleanValue();
-    }
-
-    /**
-     * @return Whether English-target translation should be enabled (default is disabled for 'en').
-     */
-    static boolean isEnglishTargetTranslationEnabled() {
-        if (sIsEnglishTargetTranslationEnabled == null) {
-            sIsEnglishTargetTranslationEnabled = getBooleanParam(ENABLE_ENGLISH_TARGET_TRANSLATION);
-        }
-        return sIsEnglishTargetTranslationEnabled.booleanValue();
-    }
-
-    /**
-     * Gets a Y value limit that will suppress a Tap near the top of the screen.
-     * Any Y value less than the limit will suppress the Tap trigger.
-     * @return The Y value triggering limit in DPs, a value of zero will not limit.
-     */
-    static int getScreenTopSuppressionDps() {
-        if (sScreenTopSuppressionDps == null) {
-            sScreenTopSuppressionDps = getIntParamValueOrDefault(SCREEN_TOP_SUPPRESSION_DPS, 0);
-        }
-        return sScreenTopSuppressionDps.intValue();
-    }
-
-    /**
-     * @return Whether collecting data on Bar overlap is enabled.
-     */
-    static boolean isBarOverlapCollectionEnabled() {
-        if (sIsBarOverlapCollectionEnabled == null) {
-            sIsBarOverlapCollectionEnabled = getBooleanParam(ENABLE_BAR_OVERLAP_COLLECTION);
-        }
-        return sIsBarOverlapCollectionEnabled.booleanValue();
-    }
-
-    /**
-     * @return Whether triggering is suppressed by a selection nearly overlapping the normal
-     *         Bar peeking location.
-     */
-    static boolean isBarOverlapSuppressionEnabled() {
-        if (sIsBarOverlapSuppressionEnabled == null) {
-            sIsBarOverlapSuppressionEnabled = getBooleanParam(BAR_OVERLAP_SUPPRESSION_ENABLED);
-        }
-        return sIsBarOverlapSuppressionEnabled.booleanValue();
-    }
-
-    /**
-     * @return Whether triggering is suppressed by a tap that's near the edge of a word.
-     */
-    static boolean isWordEdgeSuppressionEnabled() {
-        if (sIsWordEdgeSuppressionEnabled == null) {
-            sIsWordEdgeSuppressionEnabled = getBooleanParam(WORD_EDGE_SUPPRESSION_ENABLED);
-        }
-        return sIsWordEdgeSuppressionEnabled.booleanValue();
-    }
-
-    /**
-     * @return Whether triggering is suppressed by a tap that's in a short word.
-     */
-    static boolean isShortWordSuppressionEnabled() {
-        if (sIsShortWordSuppressionEnabled == null) {
-            sIsShortWordSuppressionEnabled = getBooleanParam(SHORT_WORD_SUPPRESSION_ENABLED);
-        }
-        return sIsShortWordSuppressionEnabled.booleanValue();
-    }
-
-    /**
-     * @return Whether triggering is suppressed by a tap that's not in a long word.
-     */
-    static boolean isNotLongWordSuppressionEnabled() {
-        if (sIsNotLongWordSuppressionEnabled == null) {
-            sIsNotLongWordSuppressionEnabled = getBooleanParam(NOT_LONG_WORD_SUPPRESSION_ENABLED);
-        }
-        return sIsNotLongWordSuppressionEnabled.booleanValue();
-    }
-
-    /**
-     * @return Whether triggering is suppressed for a tap that's not on an entity.
-     */
-    static boolean isNotAnEntitySuppressionEnabled() {
-        if (sIsNotAnEntitySuppressionEnabled == null) {
-            sIsNotAnEntitySuppressionEnabled = getBooleanParam(NOT_AN_ENTITY_SUPPRESSION_ENABLED);
-        }
-        return sIsNotAnEntitySuppressionEnabled.booleanValue();
-    }
-
-    /**
-     * @return Whether triggering is suppressed due to lack of engagement with the feature.
-     */
-    static boolean isEngagementSuppressionEnabled() {
-        if (sIsEngagementSuppressionEnabled == null) {
-            sIsEngagementSuppressionEnabled = getBooleanParam(ENGAGEMENT_SUPPRESSION_ENABLED);
-        }
-        return sIsEngagementSuppressionEnabled.booleanValue();
-    }
-
-    /**
-     * @return Whether triggering is suppressed for a tap that has a short element run-length.
-     */
-    static boolean isShortTextRunSuppressionEnabled() {
-        if (sIsShortTextRunSuppressionEnabled == null) {
-            sIsShortTextRunSuppressionEnabled = getBooleanParam(SHORT_TEXT_RUN_SUPPRESSION_ENABLED);
-        }
-        return sIsShortTextRunSuppressionEnabled.booleanValue();
-    }
-
-    /**
-     * @return Whether triggering is suppressed for a tap on small-looking text.
-     */
-    static boolean isSmallTextSuppressionEnabled() {
-        if (sIsSmallTextSuppressionEnabled == null) {
-            sIsSmallTextSuppressionEnabled = getBooleanParam(SMALL_TEXT_SUPPRESSION_ENABLED);
-        }
-        return sIsSmallTextSuppressionEnabled.booleanValue();
-    }
-
-    /**
-     * @return The minimum valid selection length.
-     */
-    static int getMinimumSelectionLength() {
-        if (sMinimumSelectionLength == null) {
-            sMinimumSelectionLength = getIntParamValueOrDefault(MINIMUM_SELECTION_LENGTH, 0);
-        }
-        return sMinimumSelectionLength.intValue();
-    }
-
-    /**
-     * @return Whether to disable auto-promotion of clicks in the AMP carousel into a separate Tab.
-     */
-    static boolean isAmpAsSeparateTabDisabled() {
-        if (sIsAmpAsSeparateTabDisabled == null) {
-            sIsAmpAsSeparateTabDisabled = getBooleanParam(DISABLE_AMP_AS_SEPARATE_TAB);
-        }
-        return sIsAmpAsSeparateTabDisabled;
-    }
-
-    /**
-     * @return Whether detection of device-online should be disabled (default false).
-     */
-    static boolean isOnlineDetectionDisabled() {
-        // TODO(donnd): Convert to test-only after launch and we have confidence it's robust.
-        if (sIsOnlineDetectionDisabled == null) {
-            sIsOnlineDetectionDisabled = getBooleanParam(ONLINE_DETECTION_DISABLED);
-        }
-        return sIsOnlineDetectionDisabled;
-    }
-
-    /**
-     * @return Whether sending the "home country" to Google is disabled.
-     */
-    static boolean isSendHomeCountryDisabled() {
-        if (sIsSendHomeCountryDisabled == null) {
-            sIsSendHomeCountryDisabled = getBooleanParam(DISABLE_SEND_HOME_COUNTRY);
-        }
-        return sIsSendHomeCountryDisabled.booleanValue();
-    }
-
-    /**
-     * @return Whether sending the page content notifications to observers (e.g. icing for
-     *         conversational search) is disabled.
-     */
-    static boolean isPageContentNotificationDisabled() {
-        if (sIsPageContentNotificationDisabled == null) {
-            sIsPageContentNotificationDisabled = getBooleanParam(DISABLE_PAGE_CONTENT_NOTIFICATION);
-        }
-        return sIsPageContentNotificationDisabled.booleanValue();
-    }
-
-    /**
-     * @return Whether or not logging to Ranker via UKM is disabled.
-     */
-    static boolean isUkmRankerLoggingDisabled() {
-        if (sIsUkmRankerLoggingDisabled == null) {
-            sIsUkmRankerLoggingDisabled = getBooleanParam(DISABLE_UKM_RANKER_LOGGING);
-        }
-        return sIsUkmRankerLoggingDisabled;
-    }
-
-    /**
-     * Gets an amount to delay after a Tap gesture is recognized, in case some user gesture
-     * immediately follows that would prevent the UI from showing.
-     * The classic example is a scroll, which might be a signal that the previous tap was
-     * accidental.
-     * @return The delay in MS after the Tap before showing any UI.
-     */
-    static int getWaitAfterTapDelayMs() {
-        if (sWaitAfterTapDelayMs == null) {
-            sWaitAfterTapDelayMs = getIntParamValueOrDefault(WAIT_AFTER_TAP_DELAY_MS, 0);
-        }
-        return sWaitAfterTapDelayMs.intValue();
-    }
-
-    /**
-     * Gets a threshold for the duration of a tap gesture for categorization as brief or lengthy.
-     * @return The maximum amount of time in milliseconds for a tap gesture that's still considered
-     *         a very brief duration tap.
-     */
-    static int getTapDurationThresholdMs() {
-        if (sTapDurationThresholdMs == null) {
-            sTapDurationThresholdMs = getIntParamValueOrDefault(TAP_DURATION_THRESHOLD_MS, 0);
-        }
-        return sTapDurationThresholdMs.intValue();
-    }
-
-    /**
-     * Gets the duration to use for suppressing Taps after a recent scroll, or {@code 0} if no
-     * suppression is configured.
-     * @return The period of time after a scroll when tap triggering is suppressed.
-     */
-    static int getRecentScrollDurationMs() {
-        if (sRecentScrollDurationMs == null) {
-            sRecentScrollDurationMs = getIntParamValueOrDefault(RECENT_SCROLL_DURATION_MS, 0);
-        }
-        return sRecentScrollDurationMs.intValue();
-    }
-
-    // ---------------------------
-    // Feature-controlled Switches
-    // ---------------------------
-
-    /**
-     * @return Whether or not ML-based Tap suppression is enabled.
-     */
-    static boolean isContextualSearchMlTapSuppressionEnabled() {
-        if (sContextualSearchMlTapSuppressionEnabled == null) {
-            sContextualSearchMlTapSuppressionEnabled = ChromeFeatureList.isEnabled(
-                    ChromeFeatureList.CONTEXTUAL_SEARCH_ML_TAP_SUPPRESSION);
-        }
-        return sContextualSearchMlTapSuppressionEnabled;
-    }
-
-    /**
-     * @return Whether or not to override an ML-based Tap suppression on a second tap.
-     */
-    static boolean isContextualSearchSecondTapMlOverrideEnabled() {
-        if (sContextualSearchSecondTapMlOverrideEnabled == null) {
-            sContextualSearchSecondTapMlOverrideEnabled =
-                    ChromeFeatureList.isEnabled(ChromeFeatureList.CONTEXTUAL_SEARCH_SECOND_TAP);
-        }
-        return sContextualSearchSecondTapMlOverrideEnabled;
-    }
-
-    /**
-     * @return Whether or not to override tap-disable for users that have never opened the panel.
-     */
-    static boolean isContextualSearchTapDisableOverrideEnabled() {
-        if (sContextualSearchTapDisableOverrideEnabled == null) {
-            sContextualSearchTapDisableOverrideEnabled = ChromeFeatureList.isEnabled(
-                    ChromeFeatureList.CONTEXTUAL_SEARCH_TAP_DISABLE_OVERRIDE);
-        }
-        return sContextualSearchTapDisableOverrideEnabled;
-    }
-
-    // --------------------------------------------------------------------------------------------
-    // Helpers.
-    // --------------------------------------------------------------------------------------------
-
-    /**
-     * Gets a boolean Finch parameter, assuming the <paramName>="true" format.  Also checks for a
-     * command-line switch with the same name, for easy local testing.
-     * @param paramName The name of the Finch parameter (or command-line switch) to get a value for.
+     * Gets a boolean Finch parameter, assuming the <paramName>="true" format.  Also checks for
+     * a command-line switch with the same name, for easy local testing.
+     * @param paramName The name of the Finch parameter (or command-line switch) to get a value
+     *                  for.
      * @return Whether the Finch param is defined with a value "true", if there's a command-line
      *         flag present with any value.
      */
@@ -460,9 +299,11 @@
     }
 
     /**
-     * Returns an integer value for a Finch parameter, or the default value if no parameter exists
-     * in the current configuration.  Also checks for a command-line switch with the same name.
-     * @param paramName The name of the Finch parameter (or command-line switch) to get a value for.
+     * Returns an integer value for a Finch parameter, or the default value if no parameter
+     * exists in the current configuration.  Also checks for a command-line switch with the same
+     * name.
+     * @param paramName The name of the Finch parameter (or command-line switch) to get a value
+     *                  for.
      * @param defaultValue The default value to return when there's no param or switch.
      * @return An integer value -- either the param or the default.
      */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
index 6fbf216..4341ae7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
@@ -25,6 +25,8 @@
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.StateChangeReason;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelContentViewDelegate;
 import org.chromium.chrome.browser.compositor.bottombar.contextualsearch.ContextualSearchPanel;
+import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial.ContextualSearchSetting;
+import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial.ContextualSearchSwitch;
 import org.chromium.chrome.browser.contextualsearch.ContextualSearchInternalStateController.InternalState;
 import org.chromium.chrome.browser.contextualsearch.ContextualSearchSelectionController.SelectionType;
 import org.chromium.chrome.browser.contextualsearch.ResolvedSearchTerm.CardTag;
@@ -948,7 +950,8 @@
         assert surroundingText != null;
         int startOffset = mContext.getSelectionStartOffset();
         int endOffset = mContext.getSelectionEndOffset();
-        if (!ContextualSearchFieldTrial.isPageContentNotificationDisabled()) {
+        if (!ContextualSearchFieldTrial.getSwitch(
+                    ContextualSearchSwitch.IS_PAGE_CONTENT_NOTIFICATION_DISABLED)) {
             GSAContextDisplaySelection selection = new GSAContextDisplaySelection(
                     mContext.getEncoding(), surroundingText, startOffset, endOffset);
             notifyShowContextualSearch(selection);
@@ -1018,7 +1021,8 @@
         public void onMainFrameNavigation(String url, boolean isExternalUrl, boolean isFailure) {
             assert mSearchPanel != null;
             if (isExternalUrl) {
-                if (!ContextualSearchFieldTrial.isAmpAsSeparateTabDisabled()
+                if (!ContextualSearchFieldTrial.getSwitch(
+                            ContextualSearchSwitch.IS_AMP_AS_SEPARATE_TAB_DISABLED)
                         && mPolicy.isAmpUrl(url) && mSearchPanel.didTouchContent()) {
                     onExternalNavigation(url);
                 }
@@ -1176,9 +1180,7 @@
 
     @Override
     public void logCurrentState() {
-        if (ContextualSearchFieldTrial.isEnabled()) {
-            mPolicy.logCurrentState();
-        }
+        if (ContextualSearchFieldTrial.isEnabled()) mPolicy.logCurrentState();
     }
 
     /** @return Whether the given HTTP result code represents a failure or not. */
@@ -1412,8 +1414,10 @@
         // If there's a wait-after-tap experiment then we may want to delay a bit longer for
         // the user to take an action like scrolling that will reset our internal state.
         long delayBeforeFinishingWorkMs = 0;
-        if (ContextualSearchFieldTrial.getWaitAfterTapDelayMs() > 0 && tapTimeNanoseconds > 0) {
-            delayBeforeFinishingWorkMs = ContextualSearchFieldTrial.getWaitAfterTapDelayMs()
+        if (ContextualSearchFieldTrial.getValue(ContextualSearchSetting.WAIT_AFTER_TAP_DELAY_MS) > 0
+                && tapTimeNanoseconds > 0) {
+            delayBeforeFinishingWorkMs = ContextualSearchFieldTrial.getValue(
+                                                 ContextualSearchSetting.WAIT_AFTER_TAP_DELAY_MS)
                     - (System.nanoTime() - tapTimeNanoseconds) / NANOSECONDS_IN_A_MILLISECOND;
         }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java
index 8faeaeec..45521c2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java
@@ -16,6 +16,8 @@
 import org.chromium.chrome.browser.ChromeVersionInfo;
 import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.compositor.bottombar.contextualsearch.ContextualSearchPanel;
+import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial.ContextualSearchSetting;
+import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial.ContextualSearchSwitch;
 import org.chromium.chrome.browser.contextualsearch.ContextualSearchSelectionController.SelectionType;
 import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
@@ -113,11 +115,12 @@
      * @return Whether a Tap gesture is currently supported as a trigger for the feature.
      */
     boolean isTapSupported() {
-        if (!isUserUndecided()
-                || ContextualSearchFieldTrial.isContextualSearchTapDisableOverrideEnabled()) {
-            return true;
-        }
-        return getPromoTapsRemaining() != 0;
+        return (!isUserUndecided()
+                       || ContextualSearchFieldTrial.getSwitch(
+                               ContextualSearchSwitch
+                                       .IS_CONTEXTUAL_SEARCH_TAP_DISABLE_OVERRIDE_ENABLED))
+                ? true
+                : (getPromoTapsRemaining() != 0);
     }
 
     /**
@@ -140,7 +143,8 @@
      */
     boolean shouldPreviousTapResolve() {
         if (isMandatoryPromoAvailable()
-                || ContextualSearchFieldTrial.isSearchTermResolutionDisabled()) {
+                || ContextualSearchFieldTrial.getSwitch(
+                        ContextualSearchSwitch.IS_SEARCH_TERM_RESOLUTION_DISABLED)) {
             return false;
         }
 
@@ -165,11 +169,14 @@
      * @return Whether the Mandatory Promo is enabled.
      */
     boolean isMandatoryPromoAvailable() {
-        if (!isUserUndecided() || !ContextualSearchFieldTrial.isMandatoryPromoEnabled()) {
+        if (!isUserUndecided()
+                || !ContextualSearchFieldTrial.getSwitch(
+                        ContextualSearchSwitch.IS_MANDATORY_PROMO_ENABLED)) {
             return false;
         }
 
-        return getPromoOpenCount() >= ContextualSearchFieldTrial.getMandatoryPromoLimit();
+        return getPromoOpenCount() >= ContextualSearchFieldTrial.getValue(
+                       ContextualSearchSetting.MANDATORY_PROMO_LIMIT);
     }
 
     /**
@@ -450,7 +457,7 @@
      * @return Whether any translation feature for Contextual Search is enabled.
      */
     boolean isTranslationDisabled() {
-        return ContextualSearchFieldTrial.isTranslationDisabled();
+        return ContextualSearchFieldTrial.getSwitch(ContextualSearchSwitch.IS_TRANSLATION_DISABLED);
     }
 
     /**
@@ -458,7 +465,9 @@
      *         available or privacy-enabled.
      */
     String getHomeCountry(Context context) {
-        if (ContextualSearchFieldTrial.isSendHomeCountryDisabled()) return "";
+        if (ContextualSearchFieldTrial.getSwitch(
+                    ContextualSearchSwitch.IS_SEND_HOME_COUNTRY_DISABLED))
+            return "";
 
         TelephonyManager telephonyManager =
                 (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRankerLoggerImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRankerLoggerImpl.java
index c5a11199..9fcd60b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRankerLoggerImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRankerLoggerImpl.java
@@ -7,6 +7,7 @@
 import android.support.annotation.Nullable;
 
 import org.chromium.base.VisibleForTesting;
+import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial.ContextualSearchSwitch;
 import org.chromium.content_public.browser.WebContents;
 
 import java.util.Collections;
@@ -254,7 +255,8 @@
 
     /** Whether actually writing data is enabled.  If not, we may do nothing, or just print. */
     private boolean isEnabled() {
-        return !ContextualSearchFieldTrial.isUkmRankerLoggingDisabled();
+        return !ContextualSearchFieldTrial.getSwitch(
+                ContextualSearchSwitch.IS_UKM_RANKER_LOGGING_DISABLED);
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionController.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionController.java
index 10c04d1..8674c668 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionController.java
@@ -13,6 +13,8 @@
 import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel;
+import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial.ContextualSearchSetting;
+import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial.ContextualSearchSwitch;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.content_public.browser.GestureStateListener;
 import org.chromium.content_public.browser.SelectionPopupController;
@@ -130,7 +132,8 @@
         mContainsWordPattern = Pattern.compile(CONTAINS_WORD_PATTERN);
         // TODO(donnd): remove when behind-the-flag bug fixed (crbug.com/786589).
         Log.i(TAG, "Tap suppression enabled: %s",
-                ContextualSearchFieldTrial.isContextualSearchMlTapSuppressionEnabled());
+                ContextualSearchFieldTrial.getSwitch(
+                        ContextualSearchSwitch.IS_CONTEXTUAL_SEARCH_ML_TAP_SUPPRESSION_ENABLED));
     }
 
     /**
@@ -410,7 +413,8 @@
         boolean shouldOverrideMlTapSuppression = tapHeuristics.shouldOverrideMlTapSuppression();
 
         // Make sure Tap Suppression features are consistent.
-        assert !ContextualSearchFieldTrial.isContextualSearchMlTapSuppressionEnabled()
+        assert !ContextualSearchFieldTrial.getSwitch(
+                ContextualSearchSwitch.IS_CONTEXTUAL_SEARCH_ML_TAP_SUPPRESSION_ENABLED)
                 || interactionRecorder.isQueryEnabled()
             : "Tap Suppression requires the Ranker Query feature to be enabled!";
 
@@ -426,7 +430,8 @@
 
         // Make the suppression decision and act upon it.
         boolean shouldSuppressTapBasedOnRanker = (tapPrediction == AssistRankerPrediction.SUPPRESS)
-                && ContextualSearchFieldTrial.isContextualSearchMlTapSuppressionEnabled()
+                && ContextualSearchFieldTrial.getSwitch(
+                        ContextualSearchSwitch.IS_CONTEXTUAL_SEARCH_ML_TAP_SUPPRESSION_ENABLED)
                 && !shouldOverrideMlTapSuppression;
         if (shouldSuppressTapBasedOnHeuristics || shouldSuppressTapBasedOnRanker) {
             Log.i(TAG, "Tap suppressed due to Ranker: %s, heuristics: %s",
@@ -527,7 +532,8 @@
         boolean isValid = isValidSelection(selection);
 
         if (mSelectionType == SelectionType.TAP) {
-            int minSelectionLength = ContextualSearchFieldTrial.getMinimumSelectionLength();
+            int minSelectionLength = ContextualSearchFieldTrial.getValue(
+                    ContextualSearchSetting.MINIMUM_SELECTION_LENGTH);
             if (selection.length() < minSelectionLength) {
                 isValid = false;
                 ContextualSearchUma.logSelectionLengthSuppression(true);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTabHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTabHelper.java
index c34b3cb0..1a24499 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTabHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTabHelper.java
@@ -13,6 +13,7 @@
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.StateChangeReason;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelManager.OverlayPanelManagerObserver;
 import org.chromium.chrome.browser.compositor.layouts.LayoutManager;
+import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial.ContextualSearchSwitch;
 import org.chromium.chrome.browser.firstrun.FirstRunStatus;
 import org.chromium.chrome.browser.fullscreen.FullscreenOptions;
 import org.chromium.chrome.browser.locale.LocaleManager;
@@ -385,9 +386,10 @@
 
     /** @return Whether the device is online, or we have disabled online-detection. */
     private boolean isDeviceOnline(ContextualSearchManager manager) {
-        if (ContextualSearchFieldTrial.isOnlineDetectionDisabled()) return true;
-
-        return manager.isDeviceOnline();
+        return ContextualSearchFieldTrial.getSwitch(
+                       ContextualSearchSwitch.IS_ONLINE_DETECTION_DISABLED)
+                ? true
+                : manager.isDeviceOnline();
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/EngagementSuppression.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/EngagementSuppression.java
index 6e59902..5f03a106 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/EngagementSuppression.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/EngagementSuppression.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.contextualsearch;
 
+import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial.ContextualSearchSwitch;
 import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
 
 /**
@@ -19,7 +20,8 @@
      */
     EngagementSuppression() {
         mPreferenceManager = ChromePreferenceManager.getInstance();
-        mIsEnabled = ContextualSearchFieldTrial.isEngagementSuppressionEnabled();
+        mIsEnabled = ContextualSearchFieldTrial.getSwitch(
+                ContextualSearchSwitch.IS_ENGAGEMENT_SUPPRESSION_ENABLED);
         // Used for manual testing; suppress when we've had an entity impression but no open,
         // OR had a Quick Action presented but none taken and at least one ignored.
         boolean hadEntityImpression =
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/NearTopTapSuppression.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/NearTopTapSuppression.java
index 39689b2..0e79e4a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/NearTopTapSuppression.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/NearTopTapSuppression.java
@@ -4,6 +4,8 @@
 
 package org.chromium.chrome.browser.contextualsearch;
 
+import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial.ContextualSearchSetting;
+
 /**
  * Heuristic for Tap suppression near the top of the content view area.
  * Handles logging of results seen and the condition state.
@@ -21,7 +23,8 @@
      * @param selectionController The {@link ContextualSearchSelectionController}.
      */
     NearTopTapSuppression(ContextualSearchSelectionController selectionController, int y) {
-        mExperiementThresholdDps = ContextualSearchFieldTrial.getScreenTopSuppressionDps();
+        mExperiementThresholdDps = ContextualSearchFieldTrial.getValue(
+                ContextualSearchSetting.SCREEN_TOP_SUPPRESSION_DPS);
         mYDp = (int) (y * selectionController.getPxToDp());
         mIsConditionSatisfied = mYDp < mExperiementThresholdDps;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/RecentScrollTapSuppression.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/RecentScrollTapSuppression.java
index b9c8df0..615eb9e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/RecentScrollTapSuppression.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/RecentScrollTapSuppression.java
@@ -5,6 +5,7 @@
 package org.chromium.chrome.browser.contextualsearch;
 
 import org.chromium.base.TimeUtils;
+import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial.ContextualSearchSetting;
 
 /**
  * Heuristic for Tap suppression after a recent scroll action.
@@ -32,7 +33,8 @@
         } else {
             mDurationSinceRecentScrollMs = 0;
         }
-        int experimentThreshold = ContextualSearchFieldTrial.getRecentScrollDurationMs();
+        int experimentThreshold = ContextualSearchFieldTrial.getValue(
+                ContextualSearchSetting.RECENT_SCROLL_DURATION_MS);
         mRecentScrollDurationThreshold = experimentThreshold > 0
                 ? experimentThreshold
                 : DEFAULT_RECENT_SCROLL_SUPPRESSION_DURATION_MS;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/SecondTapMlOverride.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/SecondTapMlOverride.java
index 3b558fc..a2edcd6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/SecondTapMlOverride.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/SecondTapMlOverride.java
@@ -4,6 +4,8 @@
 
 package org.chromium.chrome.browser.contextualsearch;
 
+import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial.ContextualSearchSwitch;
+
 /**
  * Heuristic that allows a second tap near a previous ML-suppressed tap to override suppression.
  */
@@ -27,8 +29,8 @@
      */
     SecondTapMlOverride(ContextualSearchSelectionController controller,
             ContextualSearchTapState previousTapState, int x, int y) {
-        mIsSecondTapEnabled =
-                ContextualSearchFieldTrial.isContextualSearchSecondTapMlOverrideEnabled();
+        mIsSecondTapEnabled = ContextualSearchFieldTrial.getSwitch(
+                ContextualSearchSwitch.IS_CONTEXTUAL_SEARCH_SECOND_TAP_ML_OVERRIDE_ENABLED);
         mPxToDp = controller.getPxToDp();
 
         mIsConditionSatisfied = previousTapState != null && previousTapState.wasMlSuppressed()
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ShortTextRunSuppression.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ShortTextRunSuppression.java
index b135ee8..9563d9d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ShortTextRunSuppression.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ShortTextRunSuppression.java
@@ -4,6 +4,8 @@
 
 package org.chromium.chrome.browser.contextualsearch;
 
+import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial.ContextualSearchSwitch;
+
 /**
  * Implements a policy that a Tap on a word that's part of a short text run should be suppressed.
  * Computes the ratio of the tapped word to the entire run of text in the element (which includes
@@ -28,7 +30,8 @@
      * @param elementRunLength The length of the text in the element tapped, in characters.
      */
     ShortTextRunSuppression(ContextualSearchContext contextualSearchContext, int elementRunLength) {
-        mIsSuppressionEnabled = ContextualSearchFieldTrial.isShortTextRunSuppressionEnabled();
+        mIsSuppressionEnabled = ContextualSearchFieldTrial.getSwitch(
+                ContextualSearchSwitch.IS_SHORT_TEXT_RUN_SUPPRESSION_ENABLED);
         mWordElementRatioDecile = wordElementRatio(contextualSearchContext, elementRunLength);
         mIsConditionSatisfied = mWordElementRatioDecile >= LARGE_WORD_ELEMENT_RATIO;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/SmallTextSuppression.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/SmallTextSuppression.java
index 3294de6..97df706 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/SmallTextSuppression.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/SmallTextSuppression.java
@@ -4,6 +4,8 @@
 
 package org.chromium.chrome.browser.contextualsearch;
 
+import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial.ContextualSearchSwitch;
+
 /**
  * Implements a policy that a Tap on a relatively small font should be ignored.
  */
@@ -22,7 +24,8 @@
      * @param fontSizeDips The size of the font from Blink in dips.
      */
     SmallTextSuppression(int fontSizeDips) {
-        mIsSuppressionEnabled = ContextualSearchFieldTrial.isSmallTextSuppressionEnabled();
+        mIsSuppressionEnabled = ContextualSearchFieldTrial.getSwitch(
+                ContextualSearchSwitch.IS_SMALL_TEXT_SUPPRESSION_ENABLED);
         mIsConditionSatisfied = isConditionSatisfied(fontSizeDips);
         mDecilizedFontSize = decilizedFontSize(fontSizeDips);
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/TapDurationSuppression.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/TapDurationSuppression.java
index a3b33a1..06ccf88 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/TapDurationSuppression.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/TapDurationSuppression.java
@@ -4,6 +4,8 @@
 
 package org.chromium.chrome.browser.contextualsearch;
 
+import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial.ContextualSearchSetting;
+
 /**
  * Provides a signal for the duration of a Tap being either brief or lengthy.
  * This signal could be used for suppression of taps below some threshold, so we aggregate-log too.
@@ -22,7 +24,8 @@
      */
     TapDurationSuppression(int tapDurationMs) {
         mTapDurationMs = tapDurationMs;
-        mTapDurationThresholdMs = ContextualSearchFieldTrial.getTapDurationThresholdMs();
+        mTapDurationThresholdMs = ContextualSearchFieldTrial.getValue(
+                ContextualSearchSetting.TAP_DURATION_THRESHOLD_MS);
         int tapDurationThreshold = mTapDurationThresholdMs != 0 ? mTapDurationThresholdMs
                                                                 : DEFAULT_TAP_DURATION_THRESHOLD_MS;
         mIsConditionSatisfied = tapDurationMs < tapDurationThreshold;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/TapWordEdgeSuppression.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/TapWordEdgeSuppression.java
index cfbcf59..12f910e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/TapWordEdgeSuppression.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/TapWordEdgeSuppression.java
@@ -6,6 +6,8 @@
 
 import android.text.TextUtils;
 
+import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial.ContextualSearchSwitch;
+
 /**
  * Implements the policy that a Tap relatively far away from the middle of a word should be
  * ignored.  When a Tap is close to the middle of the word tapped it's treated normally.
@@ -25,7 +27,8 @@
      *        out what part of the word has been tapped.
      */
     TapWordEdgeSuppression(ContextualSearchContext contextualSearchContext) {
-        mIsSuppressionEnabled = ContextualSearchFieldTrial.isWordEdgeSuppressionEnabled();
+        mIsSuppressionEnabled = ContextualSearchFieldTrial.getSwitch(
+                ContextualSearchSwitch.IS_WORD_EDGE_SUPPRESSION_ENABLED);
         mIsConditionSatisfied = isTapNearWordEdge(contextualSearchContext);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/TapWordLengthSuppression.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/TapWordLengthSuppression.java
index 47f44e8f..11e60572 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/TapWordLengthSuppression.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/TapWordLengthSuppression.java
@@ -6,6 +6,8 @@
 
 import android.text.TextUtils;
 
+import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial.ContextualSearchSwitch;
+
 /**
  * Implements signals for Taps on short and long words.
  * This signal could be used for suppression when the word is short, so we aggregate-log too.
@@ -28,9 +30,10 @@
      */
     TapWordLengthSuppression(ContextualSearchContext contextualSearchContext) {
         mWordTapped = contextualSearchContext.getWordTapped();
-        mIsShortWordSuppressionEnabled = ContextualSearchFieldTrial.isShortWordSuppressionEnabled();
-        mIsNotLongWordSuppressionEnabled =
-                ContextualSearchFieldTrial.isNotLongWordSuppressionEnabled();
+        mIsShortWordSuppressionEnabled = ContextualSearchFieldTrial.getSwitch(
+                ContextualSearchSwitch.IS_SHORT_WORD_SUPPRESSION_ENABLED);
+        mIsNotLongWordSuppressionEnabled = ContextualSearchFieldTrial.getSwitch(
+                ContextualSearchSwitch.IS_NOT_LONG_WORD_SUPPRESSION_ENABLED);
         mIsShortWordConditionSatisfied = isTapOnShortWord();
         mIsLongWordConditionSatisfied = isTapOnLongWord();
     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
index 060551d..8a6f548 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
@@ -2667,7 +2667,7 @@
     @Test
     @SmallTest
     @Feature({"ContextualSearch"})
-    @CommandLineFlags.Add(ContextualSearchFieldTrial.DISABLE_TRANSLATION + "=true")
+    @CommandLineFlags.Add(ContextualSearchFieldTrial.TRANSLATION_DISABLED + "=true")
     public void testTapDisabled() throws InterruptedException, TimeoutException {
         // Tapping a German word would normally trigger translation, but not with the above flag.
         simulateTapSearch("german");
@@ -2710,7 +2710,7 @@
     @Test
     @SmallTest
     @Feature({"ContextualSearch"})
-    @CommandLineFlags.Add(ContextualSearchFieldTrial.DISABLE_TRANSLATION + "=true")
+    @CommandLineFlags.Add(ContextualSearchFieldTrial.TRANSLATION_DISABLED + "=true")
     public void testLongpressTranslateDisabledDoesNotTranslate()
             throws InterruptedException, TimeoutException {
         // When disabled, LongPress on any word should not trigger translation.