Merge "Add Gmail timing to Analytics" into ub-gmail-ur12-dev
diff --git a/src/com/android/mail/analytics/Analytics.java b/src/com/android/mail/analytics/Analytics.java
index 551f468..778f3e0 100644
--- a/src/com/android/mail/analytics/Analytics.java
+++ b/src/com/android/mail/analytics/Analytics.java
@@ -85,6 +85,9 @@
         public void sendEvent(String category, String action, String label, long value) {}
 
         @Override
+        public void sendTiming(String category, long millis, String name, String label) {}
+
+        @Override
         public void sendMenuItemEvent(String category, int itemResId, String label, long value) {}
 
         @Override
diff --git a/src/com/android/mail/analytics/AnalyticsTimer.java b/src/com/android/mail/analytics/AnalyticsTimer.java
new file mode 100644
index 0000000..88bc270
--- /dev/null
+++ b/src/com/android/mail/analytics/AnalyticsTimer.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.mail.analytics;
+
+import android.os.SystemClock;
+
+import com.google.common.collect.Maps;
+
+import java.util.Map;
+
+/**
+ * Generic static singleton timer that keeps track of start time of various events. It  logs the
+ * event's duration into Analytics using the provided naming information.
+ * This timer class supports multiple data points per event ("lapping").
+ *
+ * This class also holds some defaults constant IDs that we log. This provides an easy way to check
+ * what data we are logging as well as ensuring that the IDs are consistent when accessed by
+ * different classes.
+ */
+public class AnalyticsTimer {
+    public static final String OPEN_CONV_VIEW_FROM_LIST = "open_conv_from_list";
+
+    private final Map<String, Long> mStartTimes = Maps.newConcurrentMap();
+
+    // Static singleton class to ensure that you can access the timer from anywhere in the code
+    private static final AnalyticsTimer mInstance = new AnalyticsTimer();
+
+    private AnalyticsTimer() {}
+
+    public static AnalyticsTimer getInstance() {
+        return mInstance;
+    }
+
+    public void trackStart(String id) {
+        mStartTimes.put(id, SystemClock.uptimeMillis());
+    }
+
+    /**
+     * Logs the duration of the event with the provided category, name, and label.
+     * This method can be destructive, meaning that any additional calls without calling
+     * {@link AnalyticsTimer#trackStart(String)} will do nothing
+     * We allow the method to be destructive to prevent the following cases from happening:
+     *   - recurring methods that call this with irrelevant mapped start times.
+     *   - multiple entry ways to the method that calls this, thus misusing the
+     *     start time.
+     * With destructive read, we ensure that we only log the event that we care about and only once.
+     * @param id id of the event
+     * @param isDestructive if you are done with this tag (used for multiple data points per tag)
+     * @param category category for analytics logging
+     * @param name name for analytics logging
+     * @param label label for analytics logging
+     */
+    public void logDuration(String id, boolean isDestructive, String category, String name,
+            String label) {
+        Long value = isDestructive ? mStartTimes.remove(id) : mStartTimes.get(id);
+        if (value != null) {
+            Analytics.getInstance().sendTiming(category, SystemClock.uptimeMillis() - value, name,
+                    label);
+        }
+    }
+}
diff --git a/src/com/android/mail/analytics/Tracker.java b/src/com/android/mail/analytics/Tracker.java
index a96677c..6a9e710 100644
--- a/src/com/android/mail/analytics/Tracker.java
+++ b/src/com/android/mail/analytics/Tracker.java
@@ -27,6 +27,7 @@
     void activityStart(Activity a);
     void activityStop(Activity a);
     void sendEvent(String category, String action, String label, long value);
+    void sendTiming(String category, long millis, String name, String label);
     void sendMenuItemEvent(String category, int itemResId, String label, long value);
     void sendView(String view);
     void setCustomDimension(int index, String value);
diff --git a/src/com/android/mail/ui/ConversationListFragment.java b/src/com/android/mail/ui/ConversationListFragment.java
index d5ec425..6951537 100644
--- a/src/com/android/mail/ui/ConversationListFragment.java
+++ b/src/com/android/mail/ui/ConversationListFragment.java
@@ -39,6 +39,7 @@
 import com.android.mail.ConversationListContext;
 import com.android.mail.R;
 import com.android.mail.analytics.Analytics;
+import com.android.mail.analytics.AnalyticsTimer;
 import com.android.mail.browse.ConversationCursor;
 import com.android.mail.browse.ConversationItemView;
 import com.android.mail.browse.ConversationItemViewModel;
@@ -622,6 +623,7 @@
                     // this is a peek.
                     Analytics.getInstance().sendEvent("peek", null, null, mSelectedSet.size());
                 }
+                AnalyticsTimer.getInstance().trackStart(AnalyticsTimer.OPEN_CONV_VIEW_FROM_LIST);
                 viewConversation(position);
             }
         } else {
diff --git a/src/com/android/mail/ui/ConversationViewFragment.java b/src/com/android/mail/ui/ConversationViewFragment.java
index e1a24e7..5d54b94 100644
--- a/src/com/android/mail/ui/ConversationViewFragment.java
+++ b/src/com/android/mail/ui/ConversationViewFragment.java
@@ -47,6 +47,7 @@
 import com.android.mail.FormattedDateBuilder;
 import com.android.mail.R;
 import com.android.mail.analytics.Analytics;
+import com.android.mail.analytics.AnalyticsTimer;
 import com.android.mail.browse.ConversationContainer;
 import com.android.mail.browse.ConversationContainer.OverlayPosition;
 import com.android.mail.browse.ConversationMessage;
@@ -619,6 +620,10 @@
     private void revealConversation() {
         timerMark("revealing conversation");
         mProgressController.dismissLoadingStatus(mOnProgressDismiss);
+        if (isUserVisible()) {
+            AnalyticsTimer.getInstance().logDuration(AnalyticsTimer.OPEN_CONV_VIEW_FROM_LIST,
+                    true /* isDestructive */, "open_conversation", "from_list", null);
+        }
     }
 
     private boolean isLoadWaiting() {