Bug 1243595 - Add session measurement hooks for record and retrieval. r=ahunt
MozReview-Commit-ID: AuZ6WEN6aCH
--- 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) {