Bug 1258812 - Create switchboard experiments for content notifications. r=margaret
authorSebastian Kaspari <s.kaspari@gmail.com>
Thu, 24 Mar 2016 10:42:37 +0100
changeset 290785 10bcf67ff6b28db8d9901ae0eaafe2099b3161ad
parent 290784 c325569a1f4dc0cd049d3f439ee20318842740b1
child 290786 a7031fdd9cb9952d03721942ef8b0639bd144b6d
push id19656
push usergwagner@mozilla.com
push dateMon, 04 Apr 2016 13:43:23 +0000
treeherderb2g-inbound@e99061fde28a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmargaret
bugs1258812
milestone48.0a1
Bug 1258812 - Create switchboard experiments for content notifications. r=margaret MozReview-Commit-ID: 8SD5BRHRr0W
mobile/android/base/java/org/mozilla/gecko/feeds/FeedService.java
mobile/android/base/java/org/mozilla/gecko/feeds/action/SetupAlarmsAction.java
mobile/android/base/java/org/mozilla/gecko/preferences/GeckoPreferences.java
mobile/android/base/java/org/mozilla/gecko/util/Experiments.java
--- a/mobile/android/base/java/org/mozilla/gecko/feeds/FeedService.java
+++ b/mobile/android/base/java/org/mozilla/gecko/feeds/FeedService.java
@@ -71,17 +71,17 @@ public class FeedService extends IntentS
     protected void onHandleIntent(Intent intent) {
         try {
             if (intent == null) {
                 return;
             }
 
             Log.d(LOGTAG, "Service started with action: " + intent.getAction());
 
-            if (!SwitchBoard.isInExperiment(this, Experiments.CONTENT_NOTIFICATIONS)) {
+            if (!isInExperiment(this)) {
                 Log.d(LOGTAG, "Not in content notifications experiment. Skipping.");
                 return;
             }
 
             FeedAction action = createActionForIntent(intent);
             if (action == null) {
                 Log.d(LOGTAG, "No action to process");
                 return;
@@ -137,12 +137,18 @@ public class FeedService extends IntentS
         NetworkInfo networkInfo = manager.getActiveNetworkInfo();
         if (networkInfo == null || !networkInfo.isConnected()) {
             return false;
         }
 
         return !ConnectivityManagerCompat.isActiveNetworkMetered(manager);
     }
 
+    public static boolean isInExperiment(Context context) {
+        return SwitchBoard.isInExperiment(context, Experiments.CONTENT_NOTIFICATIONS_12HRS) ||
+               SwitchBoard.isInExperiment(context, Experiments.CONTENT_NOTIFICATIONS_5PM) ||
+               SwitchBoard.isInExperiment(context, Experiments.CONTENT_NOTIFICATIONS_8AM);
+    }
+
     private boolean isPreferenceEnabled() {
         return GeckoSharedPrefs.forApp(this).getBoolean(GeckoPreferences.PREFS_NOTIFICATIONS_CONTENT, true);
     }
 }
--- a/mobile/android/base/java/org/mozilla/gecko/feeds/action/SetupAlarmsAction.java
+++ b/mobile/android/base/java/org/mozilla/gecko/feeds/action/SetupAlarmsAction.java
@@ -6,19 +6,26 @@
 package org.mozilla.gecko.feeds.action;
 
 import android.app.AlarmManager;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
 import android.os.SystemClock;
 
+import com.keepsafe.switchboard.SwitchBoard;
+
 import org.mozilla.gecko.db.BrowserDB;
 import org.mozilla.gecko.feeds.FeedAlarmReceiver;
 import org.mozilla.gecko.feeds.FeedService;
+import org.mozilla.gecko.util.Experiments;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
 
 /**
  * SetupAlarmsAction: Set up alarms to run various actions every now and then.
  */
 public class SetupAlarmsAction extends FeedAction {
     private static final String LOGTAG = "FeedSetupAction";
 
     private Context context;
@@ -67,24 +74,62 @@ public class SetupAlarmsAction extends F
 
         alarmManager.setInexactRepeating(
                 AlarmManager.ELAPSED_REALTIME,
                 SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_HALF_HOUR,
                 AlarmManager.INTERVAL_DAY,
                 getEnrollPendingIntent()
         );
 
+        if (SwitchBoard.isInExperiment(context, Experiments.CONTENT_NOTIFICATIONS_12HRS)) {
+            scheduleUpdateCheckEvery12Hours(alarmManager);
+        }
+
+        if (SwitchBoard.isInExperiment(context, Experiments.CONTENT_NOTIFICATIONS_8AM)) {
+            scheduleUpdateAtFullHour(alarmManager, 8);
+        }
+
+        if (SwitchBoard.isInExperiment(context, Experiments.CONTENT_NOTIFICATIONS_5PM)) {
+            scheduleUpdateAtFullHour(alarmManager, 17);
+        }
+
+
+        log("Scheduled alarms");
+    }
+
+    private void scheduleUpdateCheckEvery12Hours(AlarmManager alarmManager) {
         alarmManager.setInexactRepeating(
                 AlarmManager.ELAPSED_REALTIME,
                 SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_HOUR,
                 AlarmManager.INTERVAL_HALF_DAY,
                 getCheckPendingIntent()
         );
+    }
 
-        log("Scheduled alarms");
+    private void scheduleUpdateAtFullHour(AlarmManager alarmManager, int hourOfDay) {
+        final Calendar calendar = Calendar.getInstance();
+
+        if (calendar.get(Calendar.HOUR_OF_DAY) >= hourOfDay) {
+            // This time has already passed today. Try again tomorrow.
+            calendar.add(Calendar.DAY_OF_MONTH, 1);
+        }
+
+        calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);
+        calendar.set(Calendar.MINUTE, 0);
+        calendar.set(Calendar.SECOND, 0);
+        calendar.set(Calendar.MILLISECOND, 0);
+
+        alarmManager.setInexactRepeating(
+                AlarmManager.RTC,
+                calendar.getTimeInMillis(),
+                AlarmManager.INTERVAL_DAY,
+                getCheckPendingIntent()
+        );
+
+        log("Scheduled update alarm at " + DateFormat.getDateTimeInstance().format(calendar.getTime()));
     }
 
     private PendingIntent getWithdrawPendingIntent() {
         Intent intent = new Intent(context, FeedAlarmReceiver.class);
         intent.setAction(FeedService.ACTION_WITHDRAW);
         return PendingIntent.getBroadcast(context, 0, intent, 0);
     }
 
--- a/mobile/android/base/java/org/mozilla/gecko/preferences/GeckoPreferences.java
+++ b/mobile/android/base/java/org/mozilla/gecko/preferences/GeckoPreferences.java
@@ -867,17 +867,17 @@ OnSharedPreferenceChangeListener
                     ((LinkPreference) pref).setUrl(url);
                 } else if (PREFS_DYNAMIC_TOOLBAR.equals(key)) {
                     if (DynamicToolbar.isForceDisabled()) {
                         preferences.removePreference(pref);
                         i--;
                         continue;
                     }
                 } else if (PREFS_NOTIFICATIONS_CONTENT.equals(key)) {
-                    if (!SwitchBoard.isInExperiment(this, Experiments.CONTENT_NOTIFICATIONS)) {
+                    if (!FeedService.isInExperiment(this)) {
                         preferences.removePreference(pref);
                         i--;
                         continue;
                     }
                 }
 
                 // Some Preference UI elements are not actually preferences,
                 // but they require a key to work correctly. For example,
--- a/mobile/android/base/java/org/mozilla/gecko/util/Experiments.java
+++ b/mobile/android/base/java/org/mozilla/gecko/util/Experiments.java
@@ -27,17 +27,19 @@ public class Experiments {
 
     // 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";
 
     // Show a system notification linking to a "What's New" page on app update.
     public static final String WHATSNEW_NOTIFICATION = "whatsnew-notification";
 
     // Subscribe to known, bookmarked sites and show a notification if new content is available.
-    public static final String CONTENT_NOTIFICATIONS = "content-notifications";
+    public static final String CONTENT_NOTIFICATIONS_12HRS = "content-notifications-12hrs";
+    public static final String CONTENT_NOTIFICATIONS_8AM = "content-notifications-8am";
+    public static final String CONTENT_NOTIFICATIONS_5PM = "content-notifications-5pm";
 
     // Onboarding: "Features and Story". These experiments are determined
     // on the client, they are not part of the server config.
     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";