Bug 1246130 - Gather onboarding telemetry experiments separately from other active experiments. r=margaret
authorChenxia Liu <liuche@mozilla.com>
Tue, 16 Feb 2016 19:08:43 -0800
changeset 321616 84a0355fb1c86dcc32401fb136636e5a7acf12ba
parent 321615 800b8a648489394189bb15777dafb26e7d240ae9
child 321617 93a1dd50eb45914bfb84a397da1d265e479aee4a
push id5913
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 16:57:49 +0000
treeherdermozilla-beta@dcaf0a6fa115 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmargaret
bugs1246130
milestone47.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1246130 - Gather onboarding telemetry experiments separately from other active experiments. r=margaret MozReview-Commit-ID: KPqdlzoqTBH
mobile/android/base/java/org/mozilla/gecko/firstrun/FirstrunPagerConfig.java
mobile/android/base/java/org/mozilla/gecko/telemetry/TelemetryPingGenerator.java
mobile/android/base/java/org/mozilla/gecko/util/Experiments.java
mobile/android/base/moz.build
--- a/mobile/android/base/java/org/mozilla/gecko/firstrun/FirstrunPagerConfig.java
+++ b/mobile/android/base/java/org/mozilla/gecko/firstrun/FirstrunPagerConfig.java
@@ -3,18 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.firstrun;
 
 import android.content.Context;
 import android.os.Bundle;
 import android.util.Log;
-import com.keepsafe.switchboard.SwitchBoard;
-import org.mozilla.gecko.AppConstants;
+import org.mozilla.gecko.GeckoSharedPrefs;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.Telemetry;
 import org.mozilla.gecko.TelemetryContract;
 import org.mozilla.gecko.util.Experiments;
 
 import java.util.LinkedList;
 import java.util.List;
 
@@ -23,56 +22,43 @@ public class FirstrunPagerConfig {
 
     public static final String KEY_IMAGE = "imageRes";
     public static final String KEY_TEXT = "textRes";
     public static final String KEY_SUBTEXT = "subtextRes";
 
    public static List<FirstrunPanelConfig> getDefault(Context context) {
         final List<FirstrunPanelConfig> panels = new LinkedList<>();
 
-        if (isInExperimentLocal(context, Experiments.ONBOARDING2_A)) {
+        if (Experiments.isInExperimentLocal(context, Experiments.ONBOARDING2_A)) {
             panels.add(new FirstrunPanelConfig(WelcomePanel.class.getName(), WelcomePanel.TITLE_RES));
             Telemetry.startUISession(TelemetryContract.Session.EXPERIMENT, Experiments.ONBOARDING2_A);
-        } else if (isInExperimentLocal(context, Experiments.ONBOARDING2_B)) {
+            GeckoSharedPrefs.forProfile(context).edit().putString(Experiments.PREF_ONBOARDING_VERSION, Experiments.ONBOARDING2_A).apply();
+        } else if (Experiments.isInExperimentLocal(context, Experiments.ONBOARDING2_B)) {
             panels.add(SimplePanelConfigs.urlbarPanelConfig);
             panels.add(SimplePanelConfigs.bookmarksPanelConfig);
             panels.add(SimplePanelConfigs.syncPanelConfig);
             panels.add(new FirstrunPanelConfig(SyncPanel.class.getName(), SyncPanel.TITLE_RES));
             Telemetry.startUISession(TelemetryContract.Session.EXPERIMENT, Experiments.ONBOARDING2_B);
-        } else if (isInExperimentLocal(context, Experiments.ONBOARDING2_C)) {
+            GeckoSharedPrefs.forProfile(context).edit().putString(Experiments.PREF_ONBOARDING_VERSION, Experiments.ONBOARDING2_B).apply();
+        } else if (Experiments.isInExperimentLocal(context, Experiments.ONBOARDING2_C)) {
             panels.add(SimplePanelConfigs.urlbarPanelConfig);
             panels.add(SimplePanelConfigs.bookmarksPanelConfig);
             panels.add(SimplePanelConfigs.dataPanelConfig);
             panels.add(SimplePanelConfigs.syncPanelConfig);
             panels.add(new FirstrunPanelConfig(SyncPanel.class.getName(), SyncPanel.TITLE_RES));
             Telemetry.startUISession(TelemetryContract.Session.EXPERIMENT, Experiments.ONBOARDING2_C);
+            GeckoSharedPrefs.forProfile(context).edit().putString(Experiments.PREF_ONBOARDING_VERSION, Experiments.ONBOARDING2_C).apply();
         } else {
             Log.d(LOGTAG, "Not in an experiment!");
             panels.add(new FirstrunPanelConfig(WelcomePanel.class.getName(), WelcomePanel.TITLE_RES));
         }
 
         return panels;
     }
 
-    /*
-     * Wrapper method for using local bucketing rather than server-side.
-     * This needs to match the server-side bucketing used on mozilla-switchboard.herokuapp.com.
-     */
-    private static boolean isInExperimentLocal(Context context, String name) {
-        if (AppConstants.MOZ_SWITCHBOARD) {
-            if (SwitchBoard.isInBucket(context, 0, 33)) {
-                return Experiments.ONBOARDING2_A.equals(name);
-            } else if (SwitchBoard.isInBucket(context, 33, 66)) {
-                return Experiments.ONBOARDING2_B.equals(name);
-            } else if (SwitchBoard.isInBucket(context, 66, 100)) {
-                return Experiments.ONBOARDING2_C.equals(name);
-            }
-        }
-        return false;
-    }
 
     public static List<FirstrunPanelConfig> getRestricted() {
         final List<FirstrunPanelConfig> panels = new LinkedList<>();
         panels.add(new FirstrunPanelConfig(RestrictedWelcomePanel.class.getName(), RestrictedWelcomePanel.TITLE_RES));
         return panels;
     }
 
     public static class FirstrunPanelConfig {
--- a/mobile/android/base/java/org/mozilla/gecko/telemetry/TelemetryPingGenerator.java
+++ b/mobile/android/base/java/org/mozilla/gecko/telemetry/TelemetryPingGenerator.java
@@ -3,22 +3,21 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.telemetry;
 
 import android.content.Context;
 import android.os.Build;
 
-import com.keepsafe.switchboard.SwitchBoard;
-
 import org.mozilla.gecko.AppConstants;
 import org.mozilla.gecko.Locales;
 import org.mozilla.gecko.sync.ExtendedJSONObject;
 import org.mozilla.gecko.telemetry.TelemetryConstants.CorePing;
+import org.mozilla.gecko.util.Experiments;
 import org.mozilla.gecko.util.StringUtils;
 
 import java.io.IOException;
 import java.util.Locale;
 
 /**
  * A class with static methods to generate the various Java-created Telemetry pings to upload to the telemetry server.
  */
@@ -82,19 +81,17 @@ public class TelemetryPingGenerator {
                 StringUtils.safeSubstring(Build.MANUFACTURER, 0, 12) + '-' + StringUtils.safeSubstring(Build.MODEL, 0, 19);
 
         ping.put(CorePing.ARCHITECTURE, AppConstants.ANDROID_CPU_ARCH);
         ping.put(CorePing.CLIENT_ID, clientId);
         ping.put(CorePing.DEVICE, deviceDescriptor);
         ping.put(CorePing.LOCALE, Locales.getLanguageTag(Locale.getDefault()));
         ping.put(CorePing.OS_VERSION, Integer.toString(Build.VERSION.SDK_INT)); // A String for cross-platform reasons.
         ping.put(CorePing.SEQ, seq);
-        if (AppConstants.MOZ_SWITCHBOARD) {
-            ping.putArray(CorePing.EXPERIMENTS, SwitchBoard.getActiveExperiments(context));
-        }
+        ping.putArray(CorePing.EXPERIMENTS, Experiments.getActiveExperiments(context));
         // TODO (bug 1246816): Remove this "optional" parameter work-around when
         // GeckoProfile.getAndPersistProfileCreationDateFromFilesystem is implemented. That method returns -1
         // while it's not implemented so we don't include the parameter in the ping if that's the case.
         if (profileCreationDate >= 0) {
             ping.put(CorePing.PROFILE_CREATION_DATE, profileCreationDate);
         }
         return ping;
     }
--- a/mobile/android/base/java/org/mozilla/gecko/util/Experiments.java
+++ b/mobile/android/base/java/org/mozilla/gecko/util/Experiments.java
@@ -1,32 +1,42 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.util;
 
+import android.content.Context;
+
 import android.util.Log;
 import org.mozilla.gecko.mozglue.ContextUtils.SafeIntent;
+import android.text.TextUtils;
+import com.keepsafe.switchboard.SwitchBoard;
+import org.mozilla.gecko.GeckoSharedPrefs;
+
+import java.util.LinkedList;
+import java.util.List;
 
 /**
  * This class should reflect the experiment names found in the Switchboard experiments config here:
  * https://github.com/mozilla-services/switchboard-experiments
  */
 public class Experiments {
     private static final String LOGTAG = "GeckoExperiments";
 
     // Display History and Bookmarks in 3-dot menu.
     public static final String BOOKMARKS_HISTORY_MENU = "bookmark-history-menu";
 
     // Onboarding: "Features and Story"
     public static final String ONBOARDING2_A = "onboarding2-a"; // Control: Single (blue) welcome screen
     public static final String ONBOARDING2_B = "onboarding2-b"; // 4 static Feature slides
     public static final String ONBOARDING2_C = "onboarding2-c"; // 4 static + 1 clickable (Data saving) Feature slides
 
+    public static final String PREF_ONBOARDING_VERSION = "onboarding_version";
+
     // Show search mode (instead of home panels) when tapping on urlbar if there is a search term in the urlbar.
     public static final String SEARCH_TERM = "search-term";
 
     private static volatile Boolean disabled = null;
 
     /**
      * Determines whether Switchboard is disabled by the MOZ_DISABLE_SWITCHBOARD
      * environment variable. We need to read this value from the intent string
@@ -50,9 +60,43 @@ public class Experiments {
                     return disabled;
                 }
             }
             env = intent.getStringExtra("env" + i);
         }
         disabled = false;
         return disabled;
     }
+
+    /**
+     * Returns if a user is in certain local experiment.
+     * @param experiment Name of experiment to look up
+     * @return returns value for experiment or false if experiment does not exist.
+     */
+    public static boolean isInExperimentLocal(Context context, String experiment) {
+        if (SwitchBoard.isInBucket(context, 0, 33)) {
+            return Experiments.ONBOARDING2_A.equals(experiment);
+        } else if (SwitchBoard.isInBucket(context, 33, 66)) {
+            return Experiments.ONBOARDING2_B.equals(experiment);
+        } else if (SwitchBoard.isInBucket(context, 66, 100)) {
+            return Experiments.ONBOARDING2_C.equals(experiment);
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Returns list of all active experiments, remote and local.
+     * @return List of experiment names Strings
+     */
+    public static List<String> getActiveExperiments(Context c) {
+        final List<String> experiments = new LinkedList<>();
+        experiments.addAll(SwitchBoard.getActiveExperiments(c));
+
+        // Add onboarding version.
+        final String onboardingExperiment = GeckoSharedPrefs.forProfile(c).getString(Experiments.PREF_ONBOARDING_VERSION, null);
+        if (!TextUtils.isEmpty(onboardingExperiment)) {
+            experiments.add(onboardingExperiment);
+        }
+
+        return experiments;
+    }
 }
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -94,17 +94,16 @@ gujar.sources += ['java/org/mozilla/geck
     'util/ActivityResultHandler.java',
     'util/ActivityResultHandlerMap.java',
     'util/ActivityUtils.java',
     'util/BundleEventListener.java',
     'util/Clipboard.java',
     'util/ColorUtils.java',
     'util/DrawableUtil.java',
     'util/EventCallback.java',
-    'util/Experiments.java',
     'util/FileUtils.java',
     'util/FloatUtils.java',
     'util/GamepadUtils.java',
     'util/GeckoBackgroundThread.java',
     'util/GeckoEventListener.java',
     'util/GeckoJarReader.java',
     'util/GeckoRequest.java',
     'util/HardwareCodecCapabilityUtils.java',
@@ -573,16 +572,17 @@ gbjar.sources += ['java/org/mozilla/geck
     'toolbar/ToolbarEditLayout.java',
     'toolbar/ToolbarEditText.java',
     'toolbar/ToolbarPrefs.java',
     'toolbar/ToolbarProgressView.java',
     'TouchEventInterceptor.java',
     'trackingprotection/TrackingProtectionPrompt.java',
     'updater/UpdateService.java',
     'updater/UpdateServiceHelper.java',
+    'util/Experiments.java',
     'Webapp.java',
     'webapp/Allocator.java',
     'webapp/ApkResources.java',
     'webapp/Dispatcher.java',
     'webapp/EventListener.java',
     'webapp/InstallHelper.java',
     'webapp/InstallListener.java',
     'webapp/TaskKiller.java',