jenkins-bot has submitted this change and it was merged.

Change subject: Revive the session funnel.
......................................................................


Revive the session funnel.

- Re-enabled the session funnel, to be sampled at 1:100 in production and
  1:1 in non-production.
- Updated the funnel to record the number of pages viewed during a
  session, categorized by source.
- Added a new source, to represent pages viewed from the disambiguation
  list (Similar pages).
- The funnel now also records the average latency of the lead section
  request and the rest-of-sections request over the network. It also
  records whether the request is done via the MediaWiki API, or the new
  content service.
- Added a developer preference to set the length of a session for testing
  purposes (default is 30 minutes).

Bug: T111541
Change-Id: I600b00c2868a6922c1a0e02c86826e146a8dc2cb
---
A app/src/main/java/org/wikipedia/analytics/SessionData.java
M app/src/main/java/org/wikipedia/analytics/SessionFunnel.java
A app/src/main/java/org/wikipedia/data/SessionUnmarshaller.java
M app/src/main/java/org/wikipedia/data/TabUnmarshaller.java
M app/src/main/java/org/wikipedia/history/HistoryEntry.java
M app/src/main/java/org/wikipedia/page/JsonPageLoadStrategy.java
M app/src/main/java/org/wikipedia/page/PageActivity.java
M app/src/main/java/org/wikipedia/page/PageFragment.java
M app/src/main/java/org/wikipedia/page/PageInfoDialog.java
M app/src/main/java/org/wikipedia/settings/Prefs.java
M app/src/main/java/org/wikipedia/util/MathUtil.java
M app/src/main/res/values/dev_settings_strings.xml
M app/src/main/res/values/preference_keys.xml
M app/src/main/res/xml/developer_preferences.xml
14 files changed, 303 insertions(+), 113 deletions(-)

Approvals:
  Sniedzielski: Looks good to me, approved
  Niedzielski: Looks good to me, but someone else must approve
  jenkins-bot: Verified



diff --git a/app/src/main/java/org/wikipedia/analytics/SessionData.java 
b/app/src/main/java/org/wikipedia/analytics/SessionData.java
new file mode 100644
index 0000000..01cfb9b
--- /dev/null
+++ b/app/src/main/java/org/wikipedia/analytics/SessionData.java
@@ -0,0 +1,134 @@
+package org.wikipedia.analytics;
+
+import org.wikipedia.history.HistoryEntry;
+import org.wikipedia.util.MathUtil;
+
+public class SessionData {
+    private final MathUtil.Averaged<Long> leadLatency = new 
MathUtil.Averaged<>();
+    private final MathUtil.Averaged<Long> restLatency = new 
MathUtil.Averaged<>();
+    private long startTime;
+    private long lastTouchTime;
+    private int pagesFromSearch;
+    private int pagesFromRandom;
+    private int pagesFromLangLink;
+    private int pagesFromInternal;
+    private int pagesFromExternal;
+    private int pagesFromHistory;
+    private int pagesFromSaved;
+    private int pagesFromNearby;
+    private int pagesFromDisambig;
+    private int pagesFromBack;
+
+    public void addPageViewed(HistoryEntry entry) {
+        switch (entry.getSource()) {
+            case HistoryEntry.SOURCE_SEARCH:
+                pagesFromSearch++;
+                break;
+            case HistoryEntry.SOURCE_RANDOM:
+                pagesFromRandom++;
+                break;
+            case HistoryEntry.SOURCE_LANGUAGE_LINK:
+                pagesFromLangLink++;
+                break;
+            case HistoryEntry.SOURCE_EXTERNAL_LINK:
+                pagesFromExternal++;
+                break;
+            case HistoryEntry.SOURCE_HISTORY:
+                pagesFromHistory++;
+                break;
+            case HistoryEntry.SOURCE_SAVED_PAGE:
+                pagesFromSaved++;
+                break;
+            case HistoryEntry.SOURCE_NEARBY:
+                pagesFromNearby++;
+                break;
+            case HistoryEntry.SOURCE_DISAMBIG:
+                pagesFromDisambig++;
+                break;
+            default:
+                pagesFromInternal++;
+        }
+    }
+
+    public long getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(long startTime) {
+        this.startTime = startTime;
+    }
+
+    public long getLastTouchTime() {
+        return lastTouchTime;
+    }
+
+    public void setLastTouchTime(long lastTouchTime) {
+        this.lastTouchTime = lastTouchTime;
+    }
+
+    public long getLeadLatency() {
+        return (long) leadLatency.getAverage();
+    }
+
+    public void addLeadLatency(long leadLatency) {
+        this.leadLatency.addSample(leadLatency);
+    }
+
+    public long getRestLatency() {
+        return (long) restLatency.getAverage();
+    }
+
+    public void addRestLatency(long restLatency) {
+        this.restLatency.addSample(restLatency);
+    }
+
+    public int getPagesFromSearch() {
+        return pagesFromSearch;
+    }
+
+    public int getPagesFromRandom() {
+        return pagesFromRandom;
+    }
+
+    public int getPagesFromLangLink() {
+        return pagesFromLangLink;
+    }
+
+    public int getPagesFromInternal() {
+        return pagesFromInternal;
+    }
+
+    public int getPagesFromExternal() {
+        return pagesFromExternal;
+    }
+
+    public int getPagesFromHistory() {
+        return pagesFromHistory;
+    }
+
+    public int getPagesFromSaved() {
+        return pagesFromSaved;
+    }
+
+    public int getPagesFromNearby() {
+        return pagesFromNearby;
+    }
+
+    public int getPagesFromDisambig() {
+        return pagesFromDisambig;
+    }
+
+    public int getPagesFromBack() {
+        return pagesFromBack;
+    }
+
+    public void addPageFromBack() {
+        this.pagesFromBack++;
+    }
+
+    public int getTotalPages() {
+        return pagesFromSearch + pagesFromRandom + pagesFromLangLink + 
pagesFromInternal
+                + pagesFromExternal + pagesFromHistory + pagesFromSaved + 
pagesFromNearby
+                + pagesFromDisambig;
+    }
+}
diff --git a/app/src/main/java/org/wikipedia/analytics/SessionFunnel.java 
b/app/src/main/java/org/wikipedia/analytics/SessionFunnel.java
index 516debe..4daf984 100644
--- a/app/src/main/java/org/wikipedia/analytics/SessionFunnel.java
+++ b/app/src/main/java/org/wikipedia/analytics/SessionFunnel.java
@@ -3,57 +3,36 @@
 import org.wikipedia.WikipediaApp;
 import org.wikipedia.history.HistoryEntry;
 import org.json.JSONObject;
-import android.content.SharedPreferences;
-import android.preference.PreferenceManager;
+import org.wikipedia.settings.Prefs;
+import org.wikipedia.settings.RbSwitch;
+
 import android.support.annotation.NonNull;
 import android.text.format.DateUtils;
-import java.util.Date;
 
 public class SessionFunnel extends Funnel {
-    private static final String SCHEMA_NAME = "MobileWikiAppSessions";
-    private static final int REVISION = 10375481;
-
     /**
      * Definition of a "session timeout", as agreed upon by the Apps and 
Analytics teams.
      * (currently 30 minutes)
      */
-    private static final int SESSION_TIMEOUT_SECONDS = 30 * 60;
+    public static final int DEFAULT_SESSION_TIMEOUT = 30;
+    public static final int MIN_SESSION_TIMEOUT = 1;
 
-    private static final String SESSION_TIMESTAMP_PREF_NAME = 
"SESSION_TIMESTAMP_PREF";
-    private static final String SESSION_PAGES_SEARCH_PREF_NAME = 
"SESSION_PAGES_SEARCH_PREF";
-    private static final String SESSION_PAGES_RANDOM_PREF_NAME = 
"SESSION_PAGES_RANDOM_PREF";
-    private static final String SESSION_PAGES_LANGLINK_PREF_NAME = 
"SESSION_PAGES_LANGLINK_PREF";
-    private static final String SESSION_PAGES_INTERNAL_PREF_NAME = 
"SESSION_PAGES_INTERNAL_PREF";
-    private static final String SESSION_PAGES_EXTERNAL_PREF_NAME = 
"SESSION_PAGES_EXTERNAL_PREF";
-    private static final String SESSION_PAGES_HISTORY_PREF_NAME = 
"SESSION_PAGES_HISTORY_PREF";
-    private static final String SESSION_PAGES_SAVED_PREF_NAME = 
"SESSION_PAGES_SAVED_PREF";
-    private static final String SESSION_PAGES_BACK_PREF_NAME = 
"SESSION_PAGES_BACK_PREF";
+    private static final String SCHEMA_NAME = "MobileWikiAppSessions";
+    private static final int REVISION = 14031591;
 
-    private final Date lastEventTime;
-    private int pagesFromSearch;
-    private int pagesFromRandom;
-    private int pagesFromLanglink;
-    private int pagesFromInternal;
-    private int pagesFromExternal;
-    private int pagesFromHistory;
-    private int pagesFromSaved;
-    private int pagesFromBack;
+    private SessionData sessionData;
+    private long leadSectionStartTime;
+    private long restSectionsStartTime;
 
     public SessionFunnel(WikipediaApp app) {
-        super(app, SCHEMA_NAME, REVISION, Funnel.SAMPLE_LOG_DISABLE);
+        super(app, SCHEMA_NAME, REVISION, app.isProdRelease() ? 
Funnel.SAMPLE_LOG_100 : Funnel.SAMPLE_LOG_ALL);
 
-        SharedPreferences prefs = 
PreferenceManager.getDefaultSharedPreferences(app);
-
-        lastEventTime = new Date(prefs.getLong(SESSION_TIMESTAMP_PREF_NAME, 
0));
-        pagesFromSearch = prefs.getInt(SESSION_PAGES_SEARCH_PREF_NAME, 0);
-        pagesFromRandom = prefs.getInt(SESSION_PAGES_RANDOM_PREF_NAME, 0);
-        pagesFromLanglink = prefs.getInt(SESSION_PAGES_LANGLINK_PREF_NAME, 0);
-        pagesFromInternal = prefs.getInt(SESSION_PAGES_INTERNAL_PREF_NAME, 0);
-        pagesFromExternal = prefs.getInt(SESSION_PAGES_EXTERNAL_PREF_NAME, 0);
-        pagesFromHistory = prefs.getInt(SESSION_PAGES_HISTORY_PREF_NAME, 0);
-        pagesFromSaved = prefs.getInt(SESSION_PAGES_SAVED_PREF_NAME, 0);
-        pagesFromBack = prefs.getInt(SESSION_PAGES_BACK_PREF_NAME, 0);
-
+        sessionData = Prefs.getSessionData();
+        if (sessionData.getStartTime() == 0) {
+            long now = System.currentTimeMillis();
+            sessionData.setStartTime(now);
+            sessionData.setLastTouchTime(now);
+        }
         touchSession();
     }
 
@@ -62,91 +41,76 @@
      * so that we don't have to save its state every time a single parameter 
is modified.
      */
     public void persistSession() {
-        SharedPreferences prefs = 
PreferenceManager.getDefaultSharedPreferences(getApp());
-        prefs.edit().putLong(SESSION_TIMESTAMP_PREF_NAME, 
lastEventTime.getTime())
-             .putInt(SESSION_PAGES_SEARCH_PREF_NAME, pagesFromSearch)
-             .putInt(SESSION_PAGES_RANDOM_PREF_NAME, pagesFromRandom)
-             .putInt(SESSION_PAGES_LANGLINK_PREF_NAME, pagesFromLanglink)
-             .putInt(SESSION_PAGES_INTERNAL_PREF_NAME, pagesFromInternal)
-             .putInt(SESSION_PAGES_EXTERNAL_PREF_NAME, pagesFromExternal)
-             .putInt(SESSION_PAGES_HISTORY_PREF_NAME, pagesFromHistory)
-             .putInt(SESSION_PAGES_SAVED_PREF_NAME, pagesFromSaved)
-             .putInt(SESSION_PAGES_BACK_PREF_NAME, pagesFromBack).apply();
+        Prefs.setSessionData(sessionData);
     }
 
-    @Override protected void preprocessSessionToken(@NonNull JSONObject 
eventData) { }
+    @Override
+    protected void preprocessSessionToken(@NonNull JSONObject eventData) { }
 
     /**
-     * Update the timestamp for the current session. If the last-updated time 
is older than the defined
-     * timeout period, then consider the current session as over, and send the 
event!
+     * Update the timestamp for the current session. If the last-updated time 
is older than the
+     * defined timeout period, then consider the current session as over, and 
send the event!
      */
-    private void touchSession() {
-        Date now = new Date();
-        if (lastEventTime.getTime() == 0) {
-            //the app was just launched, and there's no record of a previous 
session,
-            //so send a session "start" event
-            log(
-                    "action", "start"
-            );
-        } else if (now.getTime() - lastEventTime.getTime() > 
(SESSION_TIMEOUT_SECONDS * DateUtils.SECOND_IN_MILLIS)) {
-
-            // the last session is over!
-            log(
-                    "action", "end",
-                    "pagesViewedFromSearch", pagesFromSearch,
-                    "pagesViewedFromRandom", pagesFromRandom,
-                    "pagesViewedFromLanglink", pagesFromLanglink,
-                    "pagesViewedFromExternal", pagesFromExternal,
-                    "pagesViewedFromHistory", pagesFromHistory,
-                    "pagesViewedFromSaved", pagesFromSaved,
-                    "totalPagesViewed", pagesFromSearch + pagesFromRandom + 
pagesFromLanglink + pagesFromInternal
-                            + pagesFromExternal + pagesFromHistory + 
pagesFromSaved,
-                    "backPressed", pagesFromBack
-            );
-
+    public void touchSession() {
+        long now = System.currentTimeMillis();
+        if (hasTimedOut()) {
+            logSessionData();
             // start a new session by clearing everything.
-            // We don't actually need to send another "start" event, since the 
"end" event that we just sent
-            // implies that a new session is starting.
-            pagesFromSearch = 0;
-            pagesFromRandom = 0;
-            pagesFromLanglink = 0;
-            pagesFromInternal = 0;
-            pagesFromExternal = 0;
-            pagesFromHistory = 0;
-            pagesFromSaved = 0;
-            pagesFromBack = 0;
+            sessionData = new SessionData();
+            sessionData.setStartTime(now);
         }
-        lastEventTime.setTime(now.getTime());
+        sessionData.setLastTouchTime(now);
     }
 
     public void pageViewed(HistoryEntry entry) {
         touchSession();
-        switch (entry.getSource()) {
-            case HistoryEntry.SOURCE_SEARCH:
-                pagesFromSearch++;
-                break;
-            case HistoryEntry.SOURCE_RANDOM:
-                pagesFromRandom++;
-                break;
-            case HistoryEntry.SOURCE_LANGUAGE_LINK:
-                pagesFromLanglink++;
-                break;
-            case HistoryEntry.SOURCE_EXTERNAL_LINK:
-                pagesFromExternal++;
-                break;
-            case HistoryEntry.SOURCE_HISTORY:
-                pagesFromHistory++;
-                break;
-            case HistoryEntry.SOURCE_SAVED_PAGE:
-                pagesFromSaved++;
-                break;
-            default:
-                pagesFromInternal++;
-        }
+        sessionData.addPageViewed(entry);
     }
 
     public void backPressed() {
         touchSession();
-        pagesFromBack++;
+        sessionData.addPageFromBack();
+    }
+
+    public void leadSectionFetchStart() {
+        leadSectionStartTime = System.currentTimeMillis();
+    }
+
+    public void leadSectionFetchEnd() {
+        sessionData.addLeadLatency(System.currentTimeMillis() - 
leadSectionStartTime);
+    }
+
+    public void restSectionsFetchStart() {
+        restSectionsStartTime = System.currentTimeMillis();
+    }
+
+    public void restSectionsFetchEnd() {
+        sessionData.addRestLatency(System.currentTimeMillis() - 
restSectionsStartTime);
+    }
+
+    private boolean hasTimedOut() {
+        return System.currentTimeMillis() - sessionData.getLastTouchTime()
+                > Prefs.getSessionTimeout() * DateUtils.MINUTE_IN_MILLIS;
+    }
+
+    private void logSessionData() {
+        long sessionLengthSeconds = (sessionData.getLastTouchTime() - 
sessionData.getStartTime()) / DateUtils.SECOND_IN_MILLIS;
+        log(
+                "length", sessionLengthSeconds,
+                "fromSearch", sessionData.getPagesFromSearch(),
+                "fromRandom", sessionData.getPagesFromRandom(),
+                "fromLanglink", sessionData.getPagesFromLangLink(),
+                "fromInternal", sessionData.getPagesFromInternal(),
+                "fromExternal", sessionData.getPagesFromExternal(),
+                "fromHistory", sessionData.getPagesFromHistory(),
+                "fromSaved", sessionData.getPagesFromSaved(),
+                "fromNearby", sessionData.getPagesFromNearby(),
+                "fromDisambig", sessionData.getPagesFromDisambig(),
+                "fromBack", sessionData.getPagesFromBack(),
+                "totalPages", sessionData.getTotalPages(),
+                "leadLatency", sessionData.getLeadLatency(),
+                "restLatency", sessionData.getRestLatency(),
+                "apiMode", RbSwitch.INSTANCE.isRestBaseEnabled() ? 1 : 0
+        );
     }
 }
diff --git a/app/src/main/java/org/wikipedia/data/SessionUnmarshaller.java 
b/app/src/main/java/org/wikipedia/data/SessionUnmarshaller.java
new file mode 100644
index 0000000..a510d77
--- /dev/null
+++ b/app/src/main/java/org/wikipedia/data/SessionUnmarshaller.java
@@ -0,0 +1,33 @@
+package org.wikipedia.data;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+
+import org.acra.ACRA;
+import org.wikipedia.WikipediaApp;
+import org.wikipedia.analytics.SessionData;
+import org.wikipedia.util.log.L;
+
+public final class SessionUnmarshaller {
+    @NonNull public static SessionData unmarshal(@Nullable String json) {
+        SessionData sessionData = null;
+        try {
+            sessionData = GsonUnmarshaller.unmarshal(SessionData.class, json);
+        } catch (Exception e) {
+            // Catch all. Any Exception can be thrown when unmarshalling.
+            // TODO: replace this block with silent exception reporting.
+            if (WikipediaApp.getInstance().isProdRelease()) {
+                L.e(e);
+            } else {
+                ACRA.getErrorReporter().putCustomData("json", json);
+                ACRA.getErrorReporter().handleException(e, false);
+            }
+        }
+        if (sessionData == null) {
+            sessionData = new SessionData();
+        }
+        return sessionData;
+    }
+
+    private SessionUnmarshaller() { }
+}
diff --git a/app/src/main/java/org/wikipedia/data/TabUnmarshaller.java 
b/app/src/main/java/org/wikipedia/data/TabUnmarshaller.java
index 2dccc33..aea7550 100644
--- a/app/src/main/java/org/wikipedia/data/TabUnmarshaller.java
+++ b/app/src/main/java/org/wikipedia/data/TabUnmarshaller.java
@@ -22,7 +22,6 @@
             object = GsonUnmarshaller.unmarshal(TYPE_TOKEN, json);
         } catch (Exception e) {
             // Catch all. Any Exception can be thrown when unmarshalling.
-
             // TODO: replace this block with silent exception reporting.
             if (WikipediaApp.getInstance().isProdRelease()) {
                 L.e(e);
diff --git a/app/src/main/java/org/wikipedia/history/HistoryEntry.java 
b/app/src/main/java/org/wikipedia/history/HistoryEntry.java
index 4f9453c..a5a98ff 100644
--- a/app/src/main/java/org/wikipedia/history/HistoryEntry.java
+++ b/app/src/main/java/org/wikipedia/history/HistoryEntry.java
@@ -18,6 +18,7 @@
     public static final int SOURCE_RANDOM = 7;
     public static final int SOURCE_MAIN_PAGE = 8;
     public static final int SOURCE_NEARBY = 9;
+    public static final int SOURCE_DISAMBIG = 10;
 
     private final PageTitle title;
     private final Date timestamp;
diff --git a/app/src/main/java/org/wikipedia/page/JsonPageLoadStrategy.java 
b/app/src/main/java/org/wikipedia/page/JsonPageLoadStrategy.java
index c60f51e..35d9201 100644
--- a/app/src/main/java/org/wikipedia/page/JsonPageLoadStrategy.java
+++ b/app/src/main/java/org/wikipedia/page/JsonPageLoadStrategy.java
@@ -628,6 +628,7 @@
 
     @VisibleForTesting
     protected void loadLeadSection(final int startSequenceNum) {
+        app.getSessionFunnel().leadSectionFetchStart();
         PageLoadUtil.getApiService(model.getTitle().getSite()).pageLead(
                 model.getTitle().getPrefixedText(),
                 PageLoadUtil.calculateLeadImageWidth(),
@@ -636,6 +637,7 @@
                     @Override
                     public void success(PageLead pageLead, Response response) {
                         Log.v(TAG, response.getUrl());
+                        app.getSessionFunnel().leadSectionFetchEnd();
                         onLeadSectionLoaded(pageLead, startSequenceNum);
                     }
 
@@ -715,6 +717,7 @@
     }
 
     private void loadRemainingSections(final int startSequenceNum) {
+        app.getSessionFunnel().restSectionsFetchStart();
         PageLoadUtil.getApiService(model.getTitle().getSite()).pageRemaining(
                 model.getTitle().getPrefixedText(),
                 !app.isImageDownloadEnabled(),
@@ -722,6 +725,7 @@
                     @Override
                     public void success(PageRemaining pageRemaining, Response 
response) {
                         Log.v(TAG, response.getUrl());
+                        app.getSessionFunnel().restSectionsFetchEnd();
                         onRemainingSectionsLoaded(pageRemaining, 
startSequenceNum);
                     }
 
diff --git a/app/src/main/java/org/wikipedia/page/PageActivity.java 
b/app/src/main/java/org/wikipedia/page/PageActivity.java
index 41f5cbe..a96db0a 100644
--- a/app/src/main/java/org/wikipedia/page/PageActivity.java
+++ b/app/src/main/java/org/wikipedia/page/PageActivity.java
@@ -699,11 +699,11 @@
             }
             return;
         }
+        app.getSessionFunnel().backPressed();
         if (getTopFragment() instanceof BackPressedHandler
                 && ((BackPressedHandler) getTopFragment()).onBackPressed()) {
             return;
         }
-        app.getSessionFunnel().backPressed();
         if (getSupportFragmentManager().getBackStackEntryCount() > 1) {
             popFragment();
         } else {
@@ -803,6 +803,7 @@
     protected void onResume() {
         super.onResume();
         app.resetSite();
+        app.getSessionFunnel().touchSession();
         boolean latestWikipediaZeroDisposition = 
app.getWikipediaZeroHandler().isZeroEnabled();
         if (pausedStateOfZero && !latestWikipediaZeroDisposition) {
             bus.post(new WikipediaZeroStateChangeEvent());
diff --git a/app/src/main/java/org/wikipedia/page/PageFragment.java 
b/app/src/main/java/org/wikipedia/page/PageFragment.java
index 6d1c0c7..99f4664 100755
--- a/app/src/main/java/org/wikipedia/page/PageFragment.java
+++ b/app/src/main/java/org/wikipedia/page/PageFragment.java
@@ -367,6 +367,9 @@
             public void onUpOrCancelMotionEvent() {
                 // queue the button to be hidden when the user stops scrolling.
                 setToCButtonFadedIn(false);
+                // update our session, since it's possible for the user to 
remain on the page for
+                // a long time, and we wouldn't want the session to time out.
+                app.getSessionFunnel().touchSession();
             }
         });
         webView.setOnFastScrollListener(new 
ObservableWebView.OnFastScrollListener() {
diff --git a/app/src/main/java/org/wikipedia/page/PageInfoDialog.java 
b/app/src/main/java/org/wikipedia/page/PageInfoDialog.java
index b9fd055..3c1d474 100644
--- a/app/src/main/java/org/wikipedia/page/PageInfoDialog.java
+++ b/app/src/main/java/org/wikipedia/page/PageInfoDialog.java
@@ -53,13 +53,13 @@
             @Override
             public void onItemClick(AdapterView<?> parent, View view, int 
position, long id) {
                 PageTitle title = ((DisambigResult) 
disambigList.getAdapter().getItem(position)).getTitle();
-                HistoryEntry historyEntry = new HistoryEntry(title, 
HistoryEntry.SOURCE_INTERNAL_LINK);
+                HistoryEntry historyEntry = new HistoryEntry(title, 
HistoryEntry.SOURCE_DISAMBIG);
                 dismiss();
                 activity.displayNewPage(title, historyEntry);
             }
         });
         PageLongPressHandler.ListViewContextMenuListener contextMenuListener = 
new LongPressHandler(activity);
-        new PageLongPressHandler(getContext(), disambigList, 
HistoryEntry.SOURCE_INTERNAL_LINK,
+        new PageLongPressHandler(getContext(), disambigList, 
HistoryEntry.SOURCE_DISAMBIG,
                 contextMenuListener);
 
         if (pageInfo.getDisambigs().length > 0) {
diff --git a/app/src/main/java/org/wikipedia/settings/Prefs.java 
b/app/src/main/java/org/wikipedia/settings/Prefs.java
index af7e3ac..9721939 100644
--- a/app/src/main/java/org/wikipedia/settings/Prefs.java
+++ b/app/src/main/java/org/wikipedia/settings/Prefs.java
@@ -2,7 +2,10 @@
 
 import org.wikipedia.R;
 import org.wikipedia.WikipediaApp;
+import org.wikipedia.analytics.SessionData;
+import org.wikipedia.analytics.SessionFunnel;
 import org.wikipedia.data.GsonMarshaller;
+import org.wikipedia.data.SessionUnmarshaller;
 import org.wikipedia.data.TabUnmarshaller;
 import org.wikipedia.page.tabs.Tab;
 import org.wikipedia.theme.Theme;
@@ -202,6 +205,26 @@
         return contains(R.string.preference_key_tabs);
     }
 
+    public static void setSessionData(@NonNull SessionData data) {
+        setString(R.string.preference_key_session_data, 
GsonMarshaller.marshal(data));
+    }
+
+    @NonNull
+    public static SessionData getSessionData() {
+        return hasSessionData()
+                ? 
SessionUnmarshaller.unmarshal(getString(R.string.preference_key_session_data, 
null))
+                : new SessionData();
+    }
+
+    public static boolean hasSessionData() {
+        return contains(R.string.preference_key_session_data);
+    }
+
+    public static int getSessionTimeout() {
+        // return the timeout, but don't let it be less than the minimum
+        return Math.max(getInt(R.string.preference_key_session_timeout, 
SessionFunnel.DEFAULT_SESSION_TIMEOUT), SessionFunnel.MIN_SESSION_TIMEOUT);
+    }
+
     public static int getTextSizeMultiplier() {
         return getInt(R.string.preference_key_text_size_multiplier, 0);
     }
diff --git a/app/src/main/java/org/wikipedia/util/MathUtil.java 
b/app/src/main/java/org/wikipedia/util/MathUtil.java
index b041c26..09da932 100644
--- a/app/src/main/java/org/wikipedia/util/MathUtil.java
+++ b/app/src/main/java/org/wikipedia/util/MathUtil.java
@@ -6,6 +6,25 @@
         return Math.min(Math.max(min, f), max);
     }
 
+    public static class Averaged<T extends Number> {
+        private double sampleSum;
+        private int sampleSize;
+
+        public void addSample(T sample) {
+            sampleSum += sample.doubleValue();
+            ++sampleSize;
+        }
+
+        public double getAverage() {
+            return sampleSize == 0 ? 0 : sampleSum / sampleSize;
+        }
+
+        public void reset() {
+            sampleSum = 0;
+            sampleSize = 0;
+        }
+    }
+
     private MathUtil() {
     }
 }
\ No newline at end of file
diff --git a/app/src/main/res/values/dev_settings_strings.xml 
b/app/src/main/res/values/dev_settings_strings.xml
index 3fda15d..bac81c8 100644
--- a/app/src/main/res/values/dev_settings_strings.xml
+++ b/app/src/main/res/values/dev_settings_strings.xml
@@ -14,4 +14,5 @@
     <string name="preferences_developer_crash_key">crash</string>
     <string name="preferences_developer_crash_title">Crash</string>
     <string name="preferences_developer_crash_summary">Tap here to crash the 
app</string>
+    <string name="preferences_developer_session_timeout_title">Session timeout 
(minutes)</string>
 </resources>
diff --git a/app/src/main/res/values/preference_keys.xml 
b/app/src/main/res/values/preference_keys.xml
index 82a23e4..e952fca 100644
--- a/app/src/main/res/values/preference_keys.xml
+++ b/app/src/main/res/values/preference_keys.xml
@@ -33,4 +33,6 @@
     <string name="preference_key_last_run_time_format">%s-lastrun</string>
     <string name="preference_key_tabs">tabs</string>
     <string name="preference_key_show_link_previews">showLinkPreviews</string>
+    <string name="preference_key_session_data">session_data</string>
+    <string name="preference_key_session_timeout">session_timeout</string>
 </resources>
diff --git a/app/src/main/res/xml/developer_preferences.xml 
b/app/src/main/res/xml/developer_preferences.xml
index c680f54..682f525 100644
--- a/app/src/main/res/xml/developer_preferences.xml
+++ b/app/src/main/res/xml/developer_preferences.xml
@@ -74,6 +74,12 @@
             android:entryValues="@array/preference_values_retrofit_log"
             android:summary="%s" />
 
+        <!--suppress AndroidUnknownAttribute -->
+        <org.wikipedia.settings.IntPreference
+            style="@style/IntPreference"
+            android:key="@string/preference_key_session_timeout"
+            
android:title="@string/preferences_developer_session_timeout_title" />
+
     </PreferenceCategory>
 
     <PreferenceCategory 
android:title="@string/preferences_developer_misc_heading">

-- 
To view, visit https://gerrit.wikimedia.org/r/244693
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I600b00c2868a6922c1a0e02c86826e146a8dc2cb
Gerrit-PatchSet: 10
Gerrit-Project: apps/android/wikipedia
Gerrit-Branch: master
Gerrit-Owner: Dbrant <[email protected]>
Gerrit-Reviewer: BearND <[email protected]>
Gerrit-Reviewer: Brion VIBBER <[email protected]>
Gerrit-Reviewer: Dbrant <[email protected]>
Gerrit-Reviewer: Mholloway <[email protected]>
Gerrit-Reviewer: Niedzielski <[email protected]>
Gerrit-Reviewer: Sniedzielski <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to