Bug 1243595 - Add session measurement hooks for record and retrieval. r=ahunt draft
authorMichael Comella <michael.l.comella@gmail.com>
Tue, 17 May 2016 15:00:41 -0700
changeset 368042 37cd71cad6bcf1031261b9fcbb89a5ebfd92a888
parent 368041 f748e38737a0e582975b19fd9ee7eb9a2fc43818
child 368487 9ebf28c70fc68f7f64a75057256ba03e1aa44dd8
push id18421
push usermichael.l.comella@gmail.com
push dateWed, 18 May 2016 00:13:57 +0000
reviewersahunt
bugs1243595
milestone49.0a1
Bug 1243595 - Add session measurement hooks for record and retrieval. r=ahunt MozReview-Commit-ID: AuZ6WEN6aCH
mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
mobile/android/base/java/org/mozilla/gecko/telemetry/UploadTelemetryCorePingCallback.java
--- a/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
+++ b/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
@@ -77,16 +77,17 @@ import org.mozilla.gecko.tabqueue.TabQue
 import org.mozilla.gecko.tabs.TabHistoryController;
 import org.mozilla.gecko.tabs.TabHistoryController.OnShowTabHistory;
 import org.mozilla.gecko.tabs.TabHistoryFragment;
 import org.mozilla.gecko.tabs.TabHistoryPage;
 import org.mozilla.gecko.tabs.TabsPanel;
 import org.mozilla.gecko.telemetry.measurements.SearchCountMeasurements;
 import org.mozilla.gecko.telemetry.TelemetryDispatcher;
 import org.mozilla.gecko.telemetry.UploadTelemetryCorePingCallback;
+import org.mozilla.gecko.telemetry.measurements.SessionMeasurements;
 import org.mozilla.gecko.toolbar.AutocompleteHandler;
 import org.mozilla.gecko.toolbar.BrowserToolbar;
 import org.mozilla.gecko.toolbar.BrowserToolbar.TabEditingState;
 import org.mozilla.gecko.toolbar.ToolbarProgressView;
 import org.mozilla.gecko.trackingprotection.TrackingProtectionPrompt;
 import org.mozilla.gecko.updater.UpdateServiceHelper;
 import org.mozilla.gecko.util.ActivityUtils;
 import org.mozilla.gecko.util.Clipboard;
@@ -314,16 +315,17 @@ public class BrowserApp extends GeckoApp
             (BrowserAppDelegate) new ReaderViewBookmarkPromotion(),
             (BrowserAppDelegate) new ContentNotificationsDelegate()
     ));
 
     @NonNull
     private SearchEngineManager searchEngineManager; // Contains reference to Context - DO NOT LEAK!
 
     private TelemetryDispatcher mTelemetryDispatcher;
+    private final SessionMeasurements mSessionMeasurements = new SessionMeasurements();
 
     private boolean mHasResumed;
 
     @Override
     public View onCreateView(final String name, final Context context, final AttributeSet attrs) {
         final View view;
         if (BrowserToolbar.class.getName().equals(name)) {
             view = BrowserToolbar.create(context, attrs);
@@ -996,16 +998,17 @@ public class BrowserApp extends GeckoApp
     public void onResume() {
         super.onResume();
         if (mIsAbortingAppLaunch) {
             return;
         }
 
         // Needed for Adjust to get accurate session measurements
         AdjustConstants.getAdjustHelper().onResume();
+        mSessionMeasurements.recordSessionStart();
 
         if (!mHasResumed) {
             EventDispatcher.getInstance().unregisterGeckoThreadListener((GeckoEventListener) this,
                     "Prompt:ShowTop");
             mHasResumed = true;
         }
 
         processTabQueue();
@@ -1020,16 +1023,20 @@ public class BrowserApp extends GeckoApp
         super.onPause();
         if (mIsAbortingAppLaunch) {
             return;
         }
 
         // Needed for Adjust to get accurate session measurements
         AdjustConstants.getAdjustHelper().onPause();
 
+        // onStart/onStop is ideal over onResume/onPause. However, onStop is not guaranteed to be called and
+        // dealing with that possibility adds a lot of complexity that we don't want to handle at this point.
+        mSessionMeasurements.recordSessionEnd(this);
+
         if (mHasResumed) {
             // Register for Prompt:ShowTop so we can foreground this activity even if it's hidden.
             EventDispatcher.getInstance().registerGeckoThreadListener((GeckoEventListener) this,
                 "Prompt:ShowTop");
             mHasResumed = false;
         }
 
         for (BrowserAppDelegate delegate : delegates) {
@@ -3901,16 +3908,20 @@ public class BrowserApp extends GeckoApp
 
     @Override
     public int getLayout() { return R.layout.gecko_app; }
 
     public TelemetryDispatcher getTelemetryDispatcher() {
         return mTelemetryDispatcher;
     }
 
+    public SessionMeasurements getSessionMeasurementDelegate() {
+        return mSessionMeasurements;
+    }
+
     // For use from tests only.
     @RobocopTarget
     public ReadingListHelper getReadingListHelper() {
         return mReadingListHelper;
     }
 
     /**
      * Launch UI that lets the user update Firefox.
--- a/mobile/android/base/java/org/mozilla/gecko/telemetry/UploadTelemetryCorePingCallback.java
+++ b/mobile/android/base/java/org/mozilla/gecko/telemetry/UploadTelemetryCorePingCallback.java
@@ -12,16 +12,17 @@ import android.support.annotation.Worker
 import android.util.Log;
 import org.mozilla.gecko.BrowserApp;
 import org.mozilla.gecko.GeckoProfile;
 import org.mozilla.gecko.GeckoSharedPrefs;
 import org.mozilla.gecko.distribution.DistributionStoreCallback;
 import org.mozilla.gecko.search.SearchEngineManager;
 import org.mozilla.gecko.sync.ExtendedJSONObject;
 import org.mozilla.gecko.telemetry.measurements.SearchCountMeasurements;
+import org.mozilla.gecko.telemetry.measurements.SessionMeasurements.SessionMeasurementsContainer;
 import org.mozilla.gecko.telemetry.pingbuilders.TelemetryCorePingBuilder;
 import org.mozilla.gecko.util.StringUtils;
 import org.mozilla.gecko.util.ThreadUtils;
 
 import java.io.IOException;
 import java.lang.ref.WeakReference;
 
 /**
@@ -69,21 +70,25 @@ public class UploadTelemetryCorePingCall
                     clientID = profile.getClientId();
                 } catch (final IOException e) {
                     Log.w(LOGTAG, "Unable to get client ID to generate core ping: " + e);
                     return;
                 }
 
                 // Each profile can have different telemetry data so we intentionally grab the shared prefs for the profile.
                 final SharedPreferences sharedPrefs = GeckoSharedPrefs.forProfileName(activity, profile.getName());
+                final SessionMeasurementsContainer sessionMeasurementsContainer =
+                        activity.getSessionMeasurementDelegate().getAndResetSessionMeasurements(activity);
                 final TelemetryCorePingBuilder pingBuilder = new TelemetryCorePingBuilder(activity)
                         .setClientID(clientID)
                         .setDefaultSearchEngine(TelemetryCorePingBuilder.getEngineIdentifier(engine))
                         .setProfileCreationDate(TelemetryCorePingBuilder.getProfileCreationDate(activity, profile))
-                        .setSequenceNumber(TelemetryCorePingBuilder.getAndIncrementSequenceNumber(sharedPrefs));
+                        .setSequenceNumber(TelemetryCorePingBuilder.getAndIncrementSequenceNumber(sharedPrefs))
+                        .setSessionCount(sessionMeasurementsContainer.sessionCount)
+                        .setSessionDuration(sessionMeasurementsContainer.elapsedSeconds);
                 maybeSetOptionalMeasurements(sharedPrefs, pingBuilder);
 
                 activity.getTelemetryDispatcher().queuePingForUpload(activity, pingBuilder);
             }
         });
     }
 
     private static void maybeSetOptionalMeasurements(final SharedPreferences sharedPrefs, final TelemetryCorePingBuilder pingBuilder) {