Merge "UsageStats tracking of screen usage."
diff --git a/api/current.txt b/api/current.txt
index 83cc69d..2c5f8b5 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -7641,13 +7641,16 @@
     method public java.lang.String getPackageName();
     method public java.lang.String getShortcutId();
     method public long getTimeStamp();
+    field public static final int ACTIVITY_PAUSED = 2; // 0x2
+    field public static final int ACTIVITY_RESUMED = 1; // 0x1
+    field public static final int ACTIVITY_STOPPED = 23; // 0x17
     field public static final int CONFIGURATION_CHANGE = 5; // 0x5
     field public static final int FOREGROUND_SERVICE_START = 19; // 0x13
     field public static final int FOREGROUND_SERVICE_STOP = 20; // 0x14
     field public static final int KEYGUARD_HIDDEN = 18; // 0x12
     field public static final int KEYGUARD_SHOWN = 17; // 0x11
-    field public static final int MOVE_TO_BACKGROUND = 2; // 0x2
-    field public static final int MOVE_TO_FOREGROUND = 1; // 0x1
+    field public static final deprecated int MOVE_TO_BACKGROUND = 2; // 0x2
+    field public static final deprecated int MOVE_TO_FOREGROUND = 1; // 0x1
     field public static final int NONE = 0; // 0x0
     field public static final int SCREEN_INTERACTIVE = 15; // 0xf
     field public static final int SCREEN_NON_INTERACTIVE = 16; // 0x10
@@ -7664,9 +7667,11 @@
     method public long getLastTimeForegroundServiceUsed();
     method public long getLastTimeStamp();
     method public long getLastTimeUsed();
+    method public long getLastTimeVisible();
     method public java.lang.String getPackageName();
     method public long getTotalTimeForegroundServiceUsed();
     method public long getTotalTimeInForeground();
+    method public long getTotalTimeVisible();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.app.usage.UsageStats> CREATOR;
   }
diff --git a/api/system-current.txt b/api/system-current.txt
index 784d826..feecdf8 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -899,6 +899,7 @@
   }
 
   public static final class UsageEvents.Event {
+    method public int getInstanceId();
     method public java.lang.String getNotificationChannelId();
     field public static final int NOTIFICATION_INTERRUPTION = 12; // 0xc
     field public static final int NOTIFICATION_SEEN = 10; // 0xa
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index af3da0c..f928501 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -196,8 +196,26 @@
 
     public abstract void updateOomAdj();
     public abstract void updateCpuStats();
-    public abstract void updateUsageStats(
+
+    /**
+     * Update battery stats on activity usage.
+     * @param activity
+     * @param uid
+     * @param userId
+     * @param started
+     */
+    public abstract void updateBatteryStats(
             ComponentName activity, int uid, int userId, boolean resumed);
+
+    /**
+     * Update UsageStats of the activity.
+     * @param activity
+     * @param userId
+     * @param event
+     * @param appToken ActivityRecord's appToken.
+     */
+    public abstract void updateActivityUsageStats(
+            ComponentName activity, int userId, int event, IBinder appToken);
     public abstract void updateForegroundTimeIfOnBattery(
             String packageName, int uid, long cpuTimeDiff);
     public abstract void sendForegroundProfileChanged(int userId);
diff --git a/core/java/android/app/usage/EventList.java b/core/java/android/app/usage/EventList.java
index aaae57e5..a79ad2f 100644
--- a/core/java/android/app/usage/EventList.java
+++ b/core/java/android/app/usage/EventList.java
@@ -103,4 +103,21 @@
         }
         return result;
     }
+
+    /**
+     * Remove events of certain type on or after a timestamp.
+     * @param type The type of event to remove.
+     * @param timeStamp the timeStamp on or after which to remove the event.
+     */
+    public void removeOnOrAfter(int type, long timeStamp) {
+        for (int i = mEvents.size() - 1; i >= 0; i--) {
+            UsageEvents.Event event = mEvents.get(i);
+            if (event.mTimeStamp < timeStamp) {
+                break;
+            }
+            if (event.mEventType == type) {
+                mEvents.remove(i);
+            }
+        }
+    }
 }
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index 3a5975a..a06213d 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -50,13 +50,27 @@
         public static final int NONE = 0;
 
         /**
+         * @deprecated by {@link #ACTIVITY_RESUMED}
+         */
+        @Deprecated
+        public static final int MOVE_TO_FOREGROUND = 1;
+
+        /**
          * An event type denoting that an {@link android.app.Activity} moved to the foreground.
          * This event has a package name and class name associated with it and can be retrieved
          * using {@link #getPackageName()} and {@link #getClassName()}.
          * If a package has multiple activities, this event is reported for each activity that moves
          * to foreground.
+         * This event is corresponding to {@link android.app.Activity#onResume()} of the
+         * activity's lifecycle.
          */
-        public static final int MOVE_TO_FOREGROUND = 1;
+        public static final int ACTIVITY_RESUMED = MOVE_TO_FOREGROUND;
+
+        /**
+         * @deprecated by {@link #ACTIVITY_PAUSED}
+         */
+        @Deprecated
+        public static final int MOVE_TO_BACKGROUND = 2;
 
         /**
          * An event type denoting that an {@link android.app.Activity} moved to the background.
@@ -64,19 +78,21 @@
          * using {@link #getPackageName()} and {@link #getClassName()}.
          * If a package has multiple activities, this event is reported for each activity that moves
          * to background.
+         * This event is corresponding to {@link android.app.Activity#onPause()} of the activity's
+         * lifecycle.
          */
-        public static final int MOVE_TO_BACKGROUND = 2;
+        public static final int ACTIVITY_PAUSED = MOVE_TO_BACKGROUND;
 
         /**
          * An event type denoting that a component was in the foreground when the stats
-         * rolled-over. This is effectively treated as a {@link #MOVE_TO_BACKGROUND}.
+         * rolled-over. This is effectively treated as a {@link #ACTIVITY_PAUSED}.
          * {@hide}
          */
         public static final int END_OF_DAY = 3;
 
         /**
          * An event type denoting that a component was in the foreground the previous day.
-         * This is effectively treated as a {@link #MOVE_TO_FOREGROUND}.
+         * This is effectively treated as a {@link #ACTIVITY_RESUMED}.
          * {@hide}
          */
         public static final int CONTINUE_PREVIOUS_DAY = 4;
@@ -207,10 +223,31 @@
         public static final int ROLLOVER_FOREGROUND_SERVICE = 22;
 
         /**
+         * An activity becomes invisible on the UI, corresponding to
+         * {@link android.app.Activity#onStop()} of the activity's lifecycle.
+         */
+        public static final int ACTIVITY_STOPPED = 23;
+
+        /**
+         * An activity object is destroyed, corresponding to
+         * {@link android.app.Activity#onDestroy()} of the activity's lifecycle.
+         * {@hide}
+         */
+        public static final int ACTIVITY_DESTROYED = 24;
+
+        /**
+         * The event type demoting that a flush of UsageStatsDatabase to file system. Before the
+         * flush all usage stats need to be updated to latest timestamp to make sure the most
+         * up to date stats are persisted.
+         * @hide
+         */
+        public static final int FLUSH_TO_DISK = 25;
+
+        /**
          * Keep in sync with the greatest event type value.
          * @hide
          */
-        public static final int MAX_EVENT_TYPE = 22;
+        public static final int MAX_EVENT_TYPE = 25;
 
         /** @hide */
         public static final int FLAG_IS_PACKAGE_INSTANT_APP = 1 << 0;
@@ -240,6 +277,12 @@
         @UnsupportedAppUsage
         public String mClass;
 
+
+        /**
+         * {@hide}
+         */
+        public int mInstanceId;
+
         /**
          * {@hide}
          */
@@ -311,9 +354,16 @@
         }
 
         /** @hide */
+        public Event(int type,  long timeStamp) {
+            mEventType = type;
+            mTimeStamp = timeStamp;
+        }
+
+        /** @hide */
         public Event(Event orig) {
             mPackage = orig.mPackage;
             mClass = orig.mClass;
+            mInstanceId = orig.mInstanceId;
             mTimeStamp = orig.mTimeStamp;
             mEventType = orig.mEventType;
             mConfiguration = orig.mConfiguration;
@@ -342,6 +392,16 @@
         }
 
         /**
+         *  An activity can be instantiated multiple times, this is the unique activity instance ID.
+         *  For non-activity class, instance ID is always zero.
+         *  @hide
+         */
+        @SystemApi
+        public int getInstanceId() {
+            return mInstanceId;
+        }
+
+        /**
          * The time at which this event occurred, measured in milliseconds since the epoch.
          * <p/>
          * See {@link System#currentTimeMillis()}.
@@ -352,12 +412,14 @@
 
         /**
          * The event type.
-         *
-         * @see #MOVE_TO_BACKGROUND
-         * @see #MOVE_TO_FOREGROUND
+         * @see #ACTIVITY_PAUSED
+         * @see #ACTIVITY_RESUMED
          * @see #CONFIGURATION_CHANGE
          * @see #USER_INTERACTION
          * @see #STANDBY_BUCKET_CHANGED
+         * @see #FOREGROUND_SERVICE_START
+         * @see #FOREGROUND_SERVICE_STOP
+         * @see #ACTIVITY_STOPPED
          */
         public int getEventType() {
             return mEventType;
@@ -576,6 +638,7 @@
         }
         p.writeInt(packageIndex);
         p.writeInt(classIndex);
+        p.writeInt(event.mInstanceId);
         p.writeInt(event.mEventType);
         p.writeLong(event.mTimeStamp);
 
@@ -618,6 +681,7 @@
         } else {
             eventOut.mClass = null;
         }
+        eventOut.mInstanceId = p.readInt();
         eventOut.mEventType = p.readInt();
         eventOut.mTimeStamp = p.readLong();
 
diff --git a/core/java/android/app/usage/UsageStats.java b/core/java/android/app/usage/UsageStats.java
index 73426e4..8fb7f4c 100644
--- a/core/java/android/app/usage/UsageStats.java
+++ b/core/java/android/app/usage/UsageStats.java
@@ -16,13 +16,15 @@
 
 package android.app.usage;
 
-import static android.app.usage.UsageEvents.Event.CONTINUE_PREVIOUS_DAY;
+import static android.app.usage.UsageEvents.Event.ACTIVITY_DESTROYED;
+import static android.app.usage.UsageEvents.Event.ACTIVITY_PAUSED;
+import static android.app.usage.UsageEvents.Event.ACTIVITY_RESUMED;
+import static android.app.usage.UsageEvents.Event.ACTIVITY_STOPPED;
 import static android.app.usage.UsageEvents.Event.CONTINUING_FOREGROUND_SERVICE;
 import static android.app.usage.UsageEvents.Event.END_OF_DAY;
+import static android.app.usage.UsageEvents.Event.FLUSH_TO_DISK;
 import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_START;
 import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_STOP;
-import static android.app.usage.UsageEvents.Event.MOVE_TO_BACKGROUND;
-import static android.app.usage.UsageEvents.Event.MOVE_TO_FOREGROUND;
 import static android.app.usage.UsageEvents.Event.ROLLOVER_FOREGROUND_SERVICE;
 
 import android.annotation.SystemApi;
@@ -31,6 +33,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.ArrayMap;
+import android.util.SparseIntArray;
 
 /**
  * Contains usage statistics for an app package for a specific
@@ -57,13 +60,20 @@
     public long mEndTimeStamp;
 
     /**
-     * Last time used by the user with an explicit action (notification, activity launch)
+     * Last time an activity is at foreground (have focus), this is corresponding to
+     * {@link android.app.usage.UsageEvents.Event#ACTIVITY_RESUMED} event.
      * {@hide}
      */
     @UnsupportedAppUsage
     public long mLastTimeUsed;
 
     /**
+     * Last time an activity is visible.
+     * @hide
+     */
+    public long mLastTimeVisible;
+
+    /**
      * Total time this package's activity is in foreground.
      * {@hide}
      */
@@ -71,6 +81,12 @@
     public long mTotalTimeInForeground;
 
     /**
+     * Total time this package's activity is visible.
+     * {@hide}
+     */
+    public long mTotalTimeVisible;
+
+    /**
      * Last time foreground service is started.
      * {@hide}
      */
@@ -93,31 +109,32 @@
      */
     public int mAppLaunchCount;
 
-    /** Last activity MOVE_TO_FOREGROUND or MOVE_TO_BACKGROUND event.
+    /** Last activity ACTIVITY_RESUMED or ACTIVITY_PAUSED event.
      * {@hide}
-     * @deprecated use {@link #mLastForegroundActivityEventMap} instead.
+     * @deprecated use {@link #mActivities} instead.
      */
     @UnsupportedAppUsage
     @Deprecated
     public int mLastEvent;
 
     /**
-     * If an activity is in foreground, it has one entry in this map.
-     * When activity moves to background, it is removed from this map.
-     * Key is activity class name.
-     * Value is last time this activity MOVE_TO_FOREGROUND or MOVE_TO_BACKGROUND event.
+     * If an activity is visible(onStart(), onPause() states) or in foreground (onResume() state),
+     * it has one entry in this map. When an activity becomes invisible (onStop() or onDestroy()),
+     * it is removed from this map.
+     * Key is instanceId of the activity (ActivityRecode appToken hashCode)..
+     * Value is this activity's last event, one of ACTIVITY_RESUMED or
+     * ACTIVITY_PAUSED.
      * {@hide}
      */
-    public ArrayMap<String, Integer> mLastForegroundActivityEventMap = new ArrayMap<>();
-
+    public SparseIntArray mActivities = new SparseIntArray();
     /**
      * If a foreground service is started, it has one entry in this map.
-     * When a foreground service is stopped, it is removed from this map.
+     * When a foreground service is stopped, it is removed from this set.
      * Key is foreground service class name.
-     * Value is last foreground service FOREGROUND_SERVICE_START ot FOREGROUND_SERVICE_STOP event.
+     * Value is the foreground service's last event, it is FOREGROUND_SERVICE_START.
      * {@hide}
      */
-    public ArrayMap<String, Integer> mLastForegroundServiceEventMap = new ArrayMap<>();
+    public ArrayMap<String, Integer> mForegroundServices = new ArrayMap<>();
 
     /**
      * {@hide}
@@ -135,14 +152,16 @@
         mBeginTimeStamp = stats.mBeginTimeStamp;
         mEndTimeStamp = stats.mEndTimeStamp;
         mLastTimeUsed = stats.mLastTimeUsed;
+        mLastTimeVisible = stats.mLastTimeVisible;
         mLastTimeForegroundServiceUsed = stats.mLastTimeForegroundServiceUsed;
         mTotalTimeInForeground = stats.mTotalTimeInForeground;
+        mTotalTimeVisible = stats.mTotalTimeVisible;
         mTotalTimeForegroundServiceUsed = stats.mTotalTimeForegroundServiceUsed;
         mLaunchCount = stats.mLaunchCount;
         mAppLaunchCount = stats.mAppLaunchCount;
         mLastEvent = stats.mLastEvent;
-        mLastForegroundActivityEventMap = stats.mLastForegroundActivityEventMap;
-        mLastForegroundServiceEventMap = stats.mLastForegroundServiceEventMap;
+        mActivities = stats.mActivities;
+        mForegroundServices = stats.mForegroundServices;
         mChooserCounts = stats.mChooserCounts;
     }
 
@@ -191,6 +210,14 @@
     }
 
     /**
+     * Get the last time this package's activity is visible in the UI, measured in milliseconds
+     * since the epoch.
+     */
+    public long getLastTimeVisible() {
+        return mLastTimeVisible;
+    }
+
+    /**
      * Get the total time this package spent in the foreground, measured in milliseconds.
      */
     public long getTotalTimeInForeground() {
@@ -198,6 +225,13 @@
     }
 
     /**
+     * Get the total time this package's activity is visible in the UI, measured in milliseconds.
+     */
+    public long getTotalTimeVisible() {
+        return mTotalTimeVisible;
+    }
+
+    /**
      * Get the last time this package's foreground service was used, measured in milliseconds since
      * the epoch.
      * <p/>
@@ -224,6 +258,20 @@
         return mAppLaunchCount;
     }
 
+    private void mergeEventMap(SparseIntArray left, SparseIntArray right) {
+        final int size = right.size();
+        for (int i = 0; i < size; i++) {
+            final int instanceId = right.keyAt(i);
+            final int event = right.valueAt(i);
+            final int index = left.indexOfKey(instanceId);
+            if (index >= 0) {
+                left.put(instanceId, Math.max(left.valueAt(index), event));
+            } else {
+                left.put(instanceId, event);
+            }
+        }
+    }
+
     private void mergeEventMap(ArrayMap<String, Integer> left, ArrayMap<String, Integer> right) {
         final int size = right.size();
         for (int i = 0; i < size; i++) {
@@ -255,15 +303,17 @@
         if (right.mBeginTimeStamp > mBeginTimeStamp) {
             // Even though incoming UsageStat begins after this one, its last time used fields
             // may somehow be empty or chronologically preceding the older UsageStat.
-            mergeEventMap(mLastForegroundActivityEventMap, right.mLastForegroundActivityEventMap);
-            mergeEventMap(mLastForegroundServiceEventMap, right.mLastForegroundServiceEventMap);
+            mergeEventMap(mActivities, right.mActivities);
+            mergeEventMap(mForegroundServices, right.mForegroundServices);
             mLastTimeUsed = Math.max(mLastTimeUsed, right.mLastTimeUsed);
+            mLastTimeVisible = Math.max(mLastTimeVisible, right.mLastTimeVisible);
             mLastTimeForegroundServiceUsed = Math.max(mLastTimeForegroundServiceUsed,
                     right.mLastTimeForegroundServiceUsed);
         }
         mBeginTimeStamp = Math.min(mBeginTimeStamp, right.mBeginTimeStamp);
         mEndTimeStamp = Math.max(mEndTimeStamp, right.mEndTimeStamp);
         mTotalTimeInForeground += right.mTotalTimeInForeground;
+        mTotalTimeVisible += right.mTotalTimeVisible;
         mTotalTimeForegroundServiceUsed += right.mTotalTimeForegroundServiceUsed;
         mLaunchCount += right.mLaunchCount;
         mAppLaunchCount += right.mAppLaunchCount;
@@ -290,36 +340,76 @@
     }
 
     /**
-     * Tell if an event indicate activity is in foreground or not.
-     * @param event the activity event.
-     * @return true if activity is in foreground, false otherwise.
-     * @hide
+     * Tell if any activity is in foreground.
+     * @return
      */
-    private boolean isActivityInForeground(int event) {
-        return event == MOVE_TO_FOREGROUND
-                || event == CONTINUE_PREVIOUS_DAY;
+    private boolean hasForegroundActivity() {
+        final int size = mActivities.size();
+        for (int i = 0; i < size; i++) {
+            if (mActivities.valueAt(i) == ACTIVITY_RESUMED) {
+                return true;
+            }
+        }
+        return false;
     }
 
     /**
-     * Tell if an event indicate foreground sevice is started or not.
-     * @param event the foreground service event.
-     * @return true if foreground service is started, false if stopped.
-     * @hide
+     * Tell if any activity is visible.
+     * @return
      */
-    private boolean isForegroundServiceStarted(int event) {
-        return event == FOREGROUND_SERVICE_START
-                || event == CONTINUING_FOREGROUND_SERVICE;
+    private boolean hasVisibleActivity() {
+        final int size = mActivities.size();
+        for (int i = 0; i < size; i++) {
+            final int type = mActivities.valueAt(i);
+            if (type == ACTIVITY_RESUMED
+                    || type == ACTIVITY_PAUSED) {
+                return true;
+            }
+        }
+        return false;
     }
 
     /**
-     * If any activity in foreground or any foreground service is started, the app is considered in
-     * use.
-     * @return true if in use, false otherwise.
-     * @hide
+     * Tell if any foreground service is started.
+     * @return
      */
-    private boolean isAppInUse() {
-        return !mLastForegroundActivityEventMap.isEmpty()
-                || !mLastForegroundServiceEventMap.isEmpty();
+    private boolean anyForegroundServiceStarted() {
+        return !mForegroundServices.isEmpty();
+    }
+
+    /**
+     * Increment total time in foreground and update last time in foreground.
+     * @param timeStamp current timestamp.
+     */
+    private void incrementTimeUsed(long timeStamp) {
+        if (timeStamp > mLastTimeUsed) {
+            mTotalTimeInForeground += timeStamp - mLastTimeUsed;
+            mLastTimeUsed = timeStamp;
+        }
+    }
+
+    /**
+     * Increment total time visible and update last time visible.
+     * @param timeStamp current timestmap.
+     */
+    private void incrementTimeVisible(long timeStamp) {
+        if (timeStamp > mLastTimeVisible) {
+            mTotalTimeVisible += timeStamp - mLastTimeVisible;
+            mLastTimeVisible = timeStamp;
+        }
+    }
+
+    /**
+     * Increment total time foreground service is used and update last time foreground service is
+     * used.
+     * @param timeStamp current timestamp.
+     */
+    private void incrementServiceTimeUsed(long timeStamp) {
+        if (timeStamp > mLastTimeForegroundServiceUsed) {
+            mTotalTimeForegroundServiceUsed +=
+                    timeStamp - mLastTimeForegroundServiceUsed;
+            mLastTimeForegroundServiceUsed = timeStamp;
+        }
     }
 
     /**
@@ -327,33 +417,63 @@
      * @param className className of the activity.
      * @param timeStamp timeStamp of the event.
      * @param eventType type of the event.
+     * @param instanceId hashCode of the ActivityRecord's appToken.
      * @hide
      */
-    private void updateForegroundActivity(String className, long timeStamp, int eventType) {
-        if (eventType != MOVE_TO_BACKGROUND
-                && eventType != MOVE_TO_FOREGROUND
-                && eventType != END_OF_DAY) {
+    private void updateActivity(String className, long timeStamp, int eventType, int instanceId) {
+        if (eventType != ACTIVITY_RESUMED
+                && eventType != ACTIVITY_PAUSED
+                && eventType != ACTIVITY_STOPPED
+                && eventType != ACTIVITY_DESTROYED) {
             return;
         }
 
-        final Integer lastEvent = mLastForegroundActivityEventMap.get(className);
-        if (lastEvent != null) {
-            if (isActivityInForeground(lastEvent)) {
-                if (timeStamp > mLastTimeUsed) {
-                    mTotalTimeInForeground += timeStamp - mLastTimeUsed;
+        // update usage.
+        final int index = mActivities.indexOfKey(instanceId);
+        if (index >= 0) {
+            final int lastEvent = mActivities.valueAt(index);
+            switch (lastEvent) {
+                case ACTIVITY_RESUMED:
+                    incrementTimeUsed(timeStamp);
+                    incrementTimeVisible(timeStamp);
+                    break;
+                case ACTIVITY_PAUSED:
+                    incrementTimeVisible(timeStamp);
+                    break;
+                default:
+                    break;
+            }
+        }
+
+        // update current event.
+        switch(eventType) {
+            case ACTIVITY_RESUMED:
+                if (!hasVisibleActivity()) {
+                    // this is the first visible activity.
+                    mLastTimeUsed = timeStamp;
+                    mLastTimeVisible = timeStamp;
+                } else if (!hasForegroundActivity()) {
+                    // this is the first foreground activity.
                     mLastTimeUsed = timeStamp;
                 }
-            }
-            if (eventType == MOVE_TO_BACKGROUND) {
-                mLastForegroundActivityEventMap.remove(className);
-            } else {
-                mLastForegroundActivityEventMap.put(className, eventType);
-            }
-        } else if (eventType == MOVE_TO_FOREGROUND) {
-            if (!isAppInUse()) {
-                mLastTimeUsed = timeStamp;
-            }
-            mLastForegroundActivityEventMap.put(className, eventType);
+                mActivities.put(instanceId, eventType);
+                break;
+            case ACTIVITY_PAUSED:
+                if (!hasVisibleActivity()) {
+                    // this is the first visible activity.
+                    mLastTimeVisible = timeStamp;
+                }
+                mActivities.put(instanceId, eventType);
+                break;
+            case ACTIVITY_STOPPED:
+                mActivities.put(instanceId, eventType);
+                break;
+            case ACTIVITY_DESTROYED:
+                // remove activity from the map.
+                mActivities.delete(instanceId);
+                break;
+            default:
+                break;
         }
     }
 
@@ -366,80 +486,97 @@
      */
     private void updateForegroundService(String className, long timeStamp, int eventType) {
         if (eventType != FOREGROUND_SERVICE_STOP
-                && eventType != FOREGROUND_SERVICE_START
-                && eventType != ROLLOVER_FOREGROUND_SERVICE) {
+                && eventType != FOREGROUND_SERVICE_START) {
             return;
         }
-        final Integer lastEvent = mLastForegroundServiceEventMap.get(className);
+        final Integer lastEvent = mForegroundServices.get(className);
+        // update usage.
         if (lastEvent != null) {
-            if (isForegroundServiceStarted(lastEvent)) {
-                if (timeStamp > mLastTimeForegroundServiceUsed) {
-                    mTotalTimeForegroundServiceUsed +=
-                            timeStamp - mLastTimeForegroundServiceUsed;
+            switch (lastEvent) {
+                case FOREGROUND_SERVICE_START:
+                case CONTINUING_FOREGROUND_SERVICE:
+                    incrementServiceTimeUsed(timeStamp);
+                    break;
+                default:
+                    break;
+            }
+        }
+
+        // update current event.
+        switch (eventType) {
+            case FOREGROUND_SERVICE_START:
+                if (!anyForegroundServiceStarted()) {
                     mLastTimeForegroundServiceUsed = timeStamp;
                 }
-            }
-            if (eventType == FOREGROUND_SERVICE_STOP) {
-                mLastForegroundServiceEventMap.remove(className);
-            } else {
-                mLastForegroundServiceEventMap.put(className, eventType);
-            }
-        } else if (eventType == FOREGROUND_SERVICE_START) {
-            if (!isAppInUse()) {
-                mLastTimeForegroundServiceUsed = timeStamp;
-            }
-            mLastForegroundServiceEventMap.put(className, eventType);
+                mForegroundServices.put(className, eventType);
+                break;
+            case FOREGROUND_SERVICE_STOP:
+                mForegroundServices.remove(className);
+                break;
+            default:
+                break;
         }
     }
 
     /**
      * Update the UsageStats by a activity or foreground service event.
-     * @param className class name of a activity or foreground service, could be null to mark
-     *                  END_OF_DAY or rollover.
+     * @param className class name of a activity or foreground service, could be null to if this
+     *                  is sent to all activities/services in this package.
      * @param timeStamp Epoch timestamp in milliseconds.
      * @param eventType event type as in {@link UsageEvents.Event}
+     * @param instanceId if className is an activity, the hashCode of ActivityRecord's appToken.
+     *                 if className is not an activity, instanceId is not used.
      * @hide
      */
-    public void update(String className, long timeStamp, int eventType) {
+    public void update(String className, long timeStamp, int eventType, int instanceId) {
         switch(eventType) {
-            case MOVE_TO_BACKGROUND:
-            case MOVE_TO_FOREGROUND:
-                updateForegroundActivity(className, timeStamp, eventType);
+            case ACTIVITY_RESUMED:
+            case ACTIVITY_PAUSED:
+            case ACTIVITY_STOPPED:
+            case ACTIVITY_DESTROYED:
+                updateActivity(className, timeStamp, eventType, instanceId);
                 break;
             case END_OF_DAY:
-                // END_OF_DAY means updating all activities.
-                final int size = mLastForegroundActivityEventMap.size();
-                for (int i = 0; i < size; i++) {
-                    final String name = mLastForegroundActivityEventMap.keyAt(i);
-                    updateForegroundActivity(name, timeStamp, eventType);
+                // END_OF_DAY updates all activities.
+                if (hasForegroundActivity()) {
+                    incrementTimeUsed(timeStamp);
+                }
+                if (hasVisibleActivity()) {
+                    incrementTimeVisible(timeStamp);
                 }
                 break;
-            case CONTINUE_PREVIOUS_DAY:
-                mLastTimeUsed = timeStamp;
-                mLastForegroundActivityEventMap.put(className, eventType);
-                break;
-            case FOREGROUND_SERVICE_STOP:
             case FOREGROUND_SERVICE_START:
+            case FOREGROUND_SERVICE_STOP:
                 updateForegroundService(className, timeStamp, eventType);
                 break;
             case ROLLOVER_FOREGROUND_SERVICE:
-                // ROLLOVER_FOREGROUND_SERVICE means updating all foreground services.
-                final int size2 = mLastForegroundServiceEventMap.size();
-                for (int i = 0; i < size2; i++) {
-                    final String name = mLastForegroundServiceEventMap.keyAt(i);
-                    updateForegroundService(name, timeStamp, eventType);
+                // ROLLOVER_FOREGROUND_SERVICE updates all foreground services.
+                if (anyForegroundServiceStarted()) {
+                    incrementServiceTimeUsed(timeStamp);
                 }
                 break;
             case CONTINUING_FOREGROUND_SERVICE:
                 mLastTimeForegroundServiceUsed = timeStamp;
-                mLastForegroundServiceEventMap.put(className, eventType);
+                mForegroundServices.put(className, eventType);
+                break;
+            case FLUSH_TO_DISK:
+                // update usage of all active activities/services.
+                if (hasForegroundActivity()) {
+                    incrementTimeUsed(timeStamp);
+                }
+                if (hasVisibleActivity()) {
+                    incrementTimeVisible(timeStamp);
+                }
+                if (anyForegroundServiceStarted()) {
+                    incrementServiceTimeUsed(timeStamp);
+                }
                 break;
             default:
                 break;
         }
         mEndTimeStamp = timeStamp;
 
-        if (eventType == MOVE_TO_FOREGROUND) {
+        if (eventType == ACTIVITY_RESUMED) {
             mLaunchCount += 1;
         }
     }
@@ -455,8 +592,10 @@
         dest.writeLong(mBeginTimeStamp);
         dest.writeLong(mEndTimeStamp);
         dest.writeLong(mLastTimeUsed);
+        dest.writeLong(mLastTimeVisible);
         dest.writeLong(mLastTimeForegroundServiceUsed);
         dest.writeLong(mTotalTimeInForeground);
+        dest.writeLong(mTotalTimeVisible);
         dest.writeLong(mTotalTimeForegroundServiceUsed);
         dest.writeInt(mLaunchCount);
         dest.writeInt(mAppLaunchCount);
@@ -477,21 +616,26 @@
         }
         dest.writeBundle(allCounts);
 
-        final Bundle foregroundActivityEventBundle = new Bundle();
-        final int foregroundEventSize = mLastForegroundActivityEventMap.size();
-        for (int i = 0; i < foregroundEventSize; i++) {
-            foregroundActivityEventBundle.putInt(mLastForegroundActivityEventMap.keyAt(i),
-                    mLastForegroundActivityEventMap.valueAt(i));
-        }
-        dest.writeBundle(foregroundActivityEventBundle);
+        writeSparseIntArray(dest, mActivities);
+        dest.writeBundle(eventMapToBundle(mForegroundServices));
+    }
 
-        final Bundle foregroundServiceEventBundle = new Bundle();
-        final int foregroundServiceEventSize = mLastForegroundServiceEventMap.size();
-        for (int i = 0; i < foregroundServiceEventSize; i++) {
-            foregroundServiceEventBundle.putInt(mLastForegroundServiceEventMap.keyAt(i),
-                    mLastForegroundServiceEventMap.valueAt(i));
+    private void writeSparseIntArray(Parcel dest, SparseIntArray arr) {
+        final int size = arr.size();
+        dest.writeInt(size);
+        for (int i = 0; i < size; i++) {
+            dest.writeInt(arr.keyAt(i));
+            dest.writeInt(arr.valueAt(i));
         }
-        dest.writeBundle(foregroundServiceEventBundle);
+    }
+
+    private Bundle eventMapToBundle(ArrayMap<String, Integer> eventMap) {
+        final Bundle bundle = new Bundle();
+        final int size = eventMap.size();
+        for (int i = 0; i < size; i++) {
+            bundle.putInt(eventMap.keyAt(i), eventMap.valueAt(i));
+        }
+        return bundle;
     }
 
     public static final Creator<UsageStats> CREATOR = new Creator<UsageStats>() {
@@ -502,8 +646,10 @@
             stats.mBeginTimeStamp = in.readLong();
             stats.mEndTimeStamp = in.readLong();
             stats.mLastTimeUsed = in.readLong();
+            stats.mLastTimeVisible = in.readLong();
             stats.mLastTimeForegroundServiceUsed = in.readLong();
             stats.mTotalTimeInForeground = in.readLong();
+            stats.mTotalTimeVisible = in.readLong();
             stats.mTotalTimeForegroundServiceUsed = in.readLong();
             stats.mLaunchCount = in.readInt();
             stats.mAppLaunchCount = in.readInt();
@@ -527,12 +673,21 @@
                     }
                 }
             }
-            readBundleToEventMap(stats.mLastForegroundActivityEventMap, in.readBundle());
-            readBundleToEventMap(stats.mLastForegroundServiceEventMap, in.readBundle());
+            readSparseIntArray(in, stats.mActivities);
+            readBundleToEventMap(in.readBundle(), stats.mForegroundServices);
             return stats;
         }
 
-        private void readBundleToEventMap(ArrayMap<String, Integer> eventMap, Bundle bundle) {
+        private void readSparseIntArray(Parcel in, SparseIntArray arr) {
+            final int size = in.readInt();
+            for (int i = 0; i < size; i++) {
+                final int key = in.readInt();
+                final int value = in.readInt();
+                arr.put(key, value);
+            }
+        }
+
+        private void readBundleToEventMap(Bundle bundle, ArrayMap<String, Integer> eventMap) {
             if (bundle != null) {
                 for (String className : bundle.keySet()) {
                     final int event = bundle.getInt(className);
diff --git a/core/java/android/app/usage/UsageStatsManagerInternal.java b/core/java/android/app/usage/UsageStatsManagerInternal.java
index 1a656ab..2edad35 100644
--- a/core/java/android/app/usage/UsageStatsManagerInternal.java
+++ b/core/java/android/app/usage/UsageStatsManagerInternal.java
@@ -37,9 +37,12 @@
      * @param component The component for which this event occurred.
      * @param userId The user id to which the component belongs to.
      * @param eventType The event that occurred. Valid values can be found at
-     * {@link UsageEvents}
+     *                  {@link UsageEvents}
+     * @param instanceId For activity, hashCode of ActivityRecord's appToken.
+     *                   For non-activity, it is not used.
      */
-    public abstract void reportEvent(ComponentName component, @UserIdInt int userId, int eventType);
+    public abstract void reportEvent(ComponentName component, @UserIdInt int userId, int eventType,
+            int instanceId);
 
     /**
      * Reports an event to the UsageStatsManager.
diff --git a/core/proto/android/server/usagestatsservice.proto b/core/proto/android/server/usagestatsservice.proto
index 3d60a86..528c1a4 100644
--- a/core/proto/android/server/usagestatsservice.proto
+++ b/core/proto/android/server/usagestatsservice.proto
@@ -54,6 +54,9 @@
     // Time attributes stored as an offset of the IntervalStats's beginTime.
     optional int64 last_time_service_used_ms = 8;
     optional int64 total_time_service_used_ms = 9;
+    // Time attributes stored as an offset of the IntervalStats's beginTime.
+    optional int64 last_time_visible_ms = 10;
+    optional int64 total_time_visible_ms = 11;
   }
 
   // Stores the relevant information an IntervalStats will have about a Configuration
@@ -82,6 +85,9 @@
     optional string notification_channel = 12;
     // notification_channel_index contains the index + 1 of the channel name in the string pool
     optional int32 notification_channel_index = 13;
+    // If class field is an Activity, instance_id is a unique id of the
+    // Activity object.
+    optional int32 instance_id = 14;
   }
 
   // The following fields contain supplemental data used to build IntervalStats, such as a string
diff --git a/core/tests/coretests/src/android/app/usage/UsageStatsTest.java b/core/tests/coretests/src/android/app/usage/UsageStatsTest.java
index 1f047f9e..28aaf1e 100644
--- a/core/tests/coretests/src/android/app/usage/UsageStatsTest.java
+++ b/core/tests/coretests/src/android/app/usage/UsageStatsTest.java
@@ -16,18 +16,22 @@
 
 package android.app.usage;
 
-import static android.app.usage.UsageEvents.Event.CONTINUE_PREVIOUS_DAY;
+import static android.app.usage.UsageEvents.Event.ACTIVITY_DESTROYED;
+import static android.app.usage.UsageEvents.Event.ACTIVITY_PAUSED;
+import static android.app.usage.UsageEvents.Event.ACTIVITY_RESUMED;
+import static android.app.usage.UsageEvents.Event.ACTIVITY_STOPPED;
 import static android.app.usage.UsageEvents.Event.CONTINUING_FOREGROUND_SERVICE;
 import static android.app.usage.UsageEvents.Event.END_OF_DAY;
+import static android.app.usage.UsageEvents.Event.FLUSH_TO_DISK;
 import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_START;
 import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_STOP;
-import static android.app.usage.UsageEvents.Event.MOVE_TO_BACKGROUND;
-import static android.app.usage.UsageEvents.Event.MOVE_TO_FOREGROUND;
 import static android.app.usage.UsageEvents.Event.ROLLOVER_FOREGROUND_SERVICE;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
+import android.app.usage.UsageEvents.Event;
 import android.os.Parcel;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
@@ -120,10 +124,10 @@
         left.mBeginTimeStamp = 100000;
         left.mTotalTimeInForeground = 10;
 
-        left.mLastForegroundActivityEventMap.put("com.test.activity1", MOVE_TO_FOREGROUND);
-        left.mLastForegroundActivityEventMap.put("com.test.activity2", MOVE_TO_FOREGROUND);
-        left.mLastForegroundServiceEventMap.put("com.test.service1", FOREGROUND_SERVICE_START);
-        left.mLastForegroundServiceEventMap.put("com.test.service2", FOREGROUND_SERVICE_START);
+        left.mActivities.put(1, Event.ACTIVITY_RESUMED);
+        left.mActivities.put(2, Event.ACTIVITY_RESUMED);
+        left.mForegroundServices.put("com.test.service1", FOREGROUND_SERVICE_START);
+        left.mForegroundServices.put("com.test.service2", FOREGROUND_SERVICE_START);
 
         Parcel p = Parcel.obtain();
         left.writeToParcel(p, 0);
@@ -133,37 +137,38 @@
     }
 
     @Test
-    public void testForegroundActivity() {
+    public void testActivity() {
         left.mPackageName = "com.test";
         left.mBeginTimeStamp = 100000;
 
-        left.update("com.test.activity1", 200000, MOVE_TO_FOREGROUND);
+        left.update("com.test.activity1", 200000, Event.ACTIVITY_RESUMED, 1);
         assertEquals(left.mLastTimeUsed, 200000);
-        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
-                new Integer(MOVE_TO_FOREGROUND));
+        assertEquals(left.mLastTimeVisible, 200000);
+        assertEquals(left.mActivities.get(1), Event.ACTIVITY_RESUMED);
         assertEquals(left.mLaunchCount, 1);
+        assertEquals(left.mTotalTimeInForeground, 0);
+        assertEquals(left.mTotalTimeVisible, 0);
 
-        left.update("com.test.activity1", 350000, MOVE_TO_BACKGROUND);
+        left.update("com.test.activity1", 350000, ACTIVITY_PAUSED, 1);
         assertEquals(left.mLastTimeUsed, 350000);
-        assertFalse(left.mLastForegroundActivityEventMap.containsKey("com.test.activity1"));
+        assertEquals(left.mLastTimeVisible, 350000);
+        assertEquals(left.mActivities.get(1), ACTIVITY_PAUSED);
         assertEquals(left.mTotalTimeInForeground, 350000 - 200000);
-    }
+        assertEquals(left.mTotalTimeVisible, 350000 - 200000);
 
-    @Test
-    public void testEvent_CONTINUE_PREVIOUS_DAY() {
-        left.mPackageName = "com.test";
-        left.mBeginTimeStamp = 100000;
-
-        left.update("com.test.activity1", 100000, CONTINUE_PREVIOUS_DAY);
-        assertEquals(left.mLastTimeUsed, 100000);
-        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
-                new Integer(CONTINUE_PREVIOUS_DAY));
-        assertEquals(left.mLaunchCount, 0);
-
-        left.update("com.test.activity1", 350000, MOVE_TO_BACKGROUND);
+        left.update("com.test.activity1", 400000, ACTIVITY_STOPPED, 1);
         assertEquals(left.mLastTimeUsed, 350000);
-        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"), null);
-        assertEquals(left.mTotalTimeInForeground, 350000 - 100000);
+        assertEquals(left.mLastTimeVisible, 400000);
+        assertEquals(left.mActivities.get(1), ACTIVITY_STOPPED);
+        assertEquals(left.mTotalTimeInForeground, 350000 - 200000);
+        assertEquals(left.mTotalTimeVisible, 400000 - 200000);
+
+        left.update("com.test.activity1", 500000, ACTIVITY_DESTROYED, 1);
+        assertEquals(left.mLastTimeUsed, 350000);
+        assertEquals(left.mLastTimeVisible, 400000);
+        assertTrue(left.mActivities.indexOfKey(1) < 0);
+        assertEquals(left.mTotalTimeInForeground, 350000 - 200000);
+        assertEquals(left.mTotalTimeVisible, 400000 - 200000);
     }
 
     @Test
@@ -171,93 +176,143 @@
         left.mPackageName = "com.test";
         left.mBeginTimeStamp = 100000;
 
-        left.update("com.test.activity1", 100000, CONTINUE_PREVIOUS_DAY);
+        left.update("com.test.activity1", 100000, Event.ACTIVITY_RESUMED, 1);
         assertEquals(left.mLastTimeUsed, 100000);
-        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
-                new Integer(CONTINUE_PREVIOUS_DAY));
-        assertEquals(left.mLaunchCount, 0);
-
-        left.update(null, 350000, END_OF_DAY);
-        assertEquals(left.mLastTimeUsed, 350000);
-        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
-                new Integer(END_OF_DAY));
-        assertEquals(left.mTotalTimeInForeground, 350000 - 100000);
-    }
-
-    @Test
-    public void testForegroundActivityEventSequence() {
-        left.mPackageName = "com.test";
-        left.mBeginTimeStamp = 100000;
-
-        left.update("com.test.activity1", 100000, CONTINUE_PREVIOUS_DAY);
-        assertEquals(left.mLastTimeUsed, 100000);
-        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
-                new Integer(CONTINUE_PREVIOUS_DAY));
-        assertEquals(left.mLaunchCount, 0);
-
-        left.update("com.test.activity1", 350000, MOVE_TO_BACKGROUND);
-        assertEquals(left.mLastTimeUsed, 350000);
-        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"), null);
-        assertEquals(left.mTotalTimeInForeground, 250000 /*350000 - 100000*/);
-
-        left.update("com.test.activity1", 450000, MOVE_TO_FOREGROUND);
-        assertEquals(left.mLastTimeUsed, 450000);
-        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
-                new Integer(MOVE_TO_FOREGROUND));
-        assertEquals(left.mTotalTimeInForeground, 250000);
-
-        left.update("com.test.activity1", 500000, MOVE_TO_BACKGROUND);
-        assertEquals(left.mLastTimeUsed, 500000);
-        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"), null);
-        assertEquals(left.mTotalTimeInForeground, 250000 + 50000 /*500000 - 450000*/);
-    }
-
-    @Test
-    public void testForegroundActivityEventOutOfSequence() {
-        left.mPackageName = "com.test";
-        left.mBeginTimeStamp = 100000;
-
-        left.update("com.test.activity1", 100000, CONTINUE_PREVIOUS_DAY);
-        assertEquals(left.mLastTimeUsed, 100000);
-        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
-                new Integer(CONTINUE_PREVIOUS_DAY));
-        assertEquals(left.mLaunchCount, 0);
-
-        left.update("com.test.activity1", 150000, MOVE_TO_FOREGROUND);
-        assertEquals(left.mLastTimeUsed, 150000);
-        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
-                new Integer(MOVE_TO_FOREGROUND));
+        assertEquals(left.mLastTimeVisible, 100000);
+        assertEquals(left.mActivities.get(1), Event.ACTIVITY_RESUMED);
         assertEquals(left.mLaunchCount, 1);
-        assertEquals(left.mTotalTimeInForeground, 50000 /*150000 - 100000*/);
 
-        left.update("com.test.activity1", 200000, MOVE_TO_FOREGROUND);
+        left.update(null, 350000, END_OF_DAY, 0);
+        assertEquals(left.mLastTimeUsed, 350000);
+        assertEquals(left.mLastTimeVisible, 350000);
+        assertEquals(left.mActivities.get(1), Event.ACTIVITY_RESUMED);
+        assertEquals(left.mTotalTimeInForeground, 350000 - 100000);
+        assertEquals(left.mTotalTimeVisible, 350000 - 100000);
+    }
+
+    @Test
+    public void testEvent_ACTIVITY_PAUSED() {
+        left.mPackageName = "com.test";
+        left.mBeginTimeStamp = 100000;
+
+        left.update("com.test.activity1", 100000, ACTIVITY_PAUSED, 1);
+        assertEquals(left.mLastTimeUsed, 0);
+        assertEquals(left.mLastTimeVisible, 100000);
+        assertEquals(left.mActivities.get(1), ACTIVITY_PAUSED);
+
+        left.update("com.test.activity1", 200000, Event.ACTIVITY_RESUMED, 1);
         assertEquals(left.mLastTimeUsed, 200000);
-        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
-                new Integer(MOVE_TO_FOREGROUND));
+        assertEquals(left.mLastTimeVisible, 200000);
+        assertEquals(left.mActivities.get(1), Event.ACTIVITY_RESUMED);
+        assertEquals(left.mTotalTimeInForeground, 0);
+        assertEquals(left.mTotalTimeVisible, 200000 - 100000);
+
+        left.update("com.test.activity1", 300000, ACTIVITY_PAUSED, 1);
+        assertEquals(left.mLastTimeUsed, 300000);
+        assertEquals(left.mLastTimeVisible, 300000);
+        assertEquals(left.mActivities.get(1), ACTIVITY_PAUSED);
+        assertEquals(left.mTotalTimeInForeground, 300000 - 200000);
+        assertEquals(left.mTotalTimeVisible, 300000 - 100000);
+
+        left.update("com.test.activity1", 400000, ACTIVITY_STOPPED, 1);
+        assertEquals(left.mLastTimeUsed, 300000);
+        assertEquals(left.mLastTimeVisible, 400000);
+        assertEquals(left.mActivities.get(1), ACTIVITY_STOPPED);
+        assertEquals(left.mTotalTimeInForeground, 300000 - 200000);
+        assertEquals(left.mTotalTimeVisible, 400000 - 100000);
+    }
+
+    @Test
+    public void testEvent_CHANGE_TO_INVISIBLE() {
+        left.mPackageName = "com.test";
+        left.mBeginTimeStamp = 100000;
+
+        left.update("com.test.activity1", 100000, ACTIVITY_RESUMED, 1);
+        assertEquals(left.mLastTimeUsed, 100000);
+        assertEquals(left.mLastTimeVisible, 100000);
+        assertEquals(left.mActivities.get(1), ACTIVITY_RESUMED);
+
+        left.update("com.test.activity1", 200000, ACTIVITY_STOPPED, 1);
+        assertEquals(left.mLastTimeUsed, 200000);
+        assertEquals(left.mLastTimeVisible, 200000);
+        assertEquals(left.mActivities.get(1), ACTIVITY_STOPPED);
+        assertEquals(left.mTotalTimeInForeground, 200000 - 100000);
+        assertEquals(left.mTotalTimeVisible, 200000 - 100000);
+
+        left.update("com.test.activity1", 300000, ACTIVITY_RESUMED, 1);
+        assertEquals(left.mLastTimeUsed, 300000);
+        assertEquals(left.mLastTimeVisible, 300000);
+        assertEquals(left.mActivities.get(1), ACTIVITY_RESUMED);
+        assertEquals(left.mTotalTimeInForeground, 200000 - 100000);
+        assertEquals(left.mTotalTimeVisible, 200000 - 100000);
+    }
+
+    @Test
+    public void testEvent_ACTIVITY_DESTROYED() {
+        left.mPackageName = "com.test";
+        left.mBeginTimeStamp = 100000;
+
+        left.update("com.test.activity1", 100000, ACTIVITY_RESUMED, 1);
+        assertEquals(left.mLastTimeUsed, 100000);
+        assertEquals(left.mLastTimeVisible, 100000);
+        assertEquals(left.mActivities.get(1), ACTIVITY_RESUMED);
+
+        left.update("com.test.activity1", 200000, ACTIVITY_DESTROYED, 1);
+        assertEquals(left.mLastTimeUsed, 200000);
+        assertEquals(left.mLastTimeVisible, 200000);
+        assertTrue(left.mActivities.indexOfKey(1) < 0);
+        assertEquals(left.mTotalTimeInForeground, 200000 - 100000);
+        assertEquals(left.mTotalTimeVisible, 200000 - 100000);
+    }
+
+    @Test
+    public void testActivityEventOutOfOrder() {
+        left.mPackageName = "com.test";
+        left.mBeginTimeStamp = 100000;
+
+        left.update("com.test.activity1", 100000, Event.ACTIVITY_RESUMED, 1);
+        assertEquals(left.mLastTimeUsed, 100000);
+        assertEquals(left.mLastTimeVisible, 100000);
+        assertEquals(left.mActivities.get(1), Event.ACTIVITY_RESUMED);
+        assertEquals(left.mLaunchCount, 1);
+        assertEquals(left.mTotalTimeInForeground, 0);
+        assertEquals(left.mTotalTimeVisible, 0);
+
+        left.update("com.test.activity1", 200000, Event.ACTIVITY_RESUMED, 1);
+        assertEquals(left.mLastTimeUsed, 200000);
+        assertEquals(left.mLastTimeVisible, 200000);
+        assertEquals(left.mActivities.get(1), Event.ACTIVITY_RESUMED);
         assertEquals(left.mLaunchCount, 2);
         assertEquals(left.mTotalTimeInForeground, 100000);
+        assertEquals(left.mTotalTimeVisible, 100000 /*200000 - 100000*/);
 
-        left.update("com.test.activity1", 250000, MOVE_TO_BACKGROUND);
+        left.update("com.test.activity1", 250000, ACTIVITY_PAUSED, 1);
         assertEquals(left.mLastTimeUsed, 250000);
-        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"), null);
+        assertEquals(left.mLastTimeVisible, 250000);
+        assertEquals(left.mActivities.get(1), ACTIVITY_PAUSED);
         assertEquals(left.mTotalTimeInForeground, 150000);
+        assertEquals(left.mTotalTimeVisible, 150000 /*250000 - 100000*/);
 
-        left.update("com.test.activity1", 300000, MOVE_TO_BACKGROUND);
+        left.update("com.test.activity1", 300000, ACTIVITY_PAUSED, 1);
         assertEquals(left.mLastTimeUsed, 250000);
-        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"), null);
+        assertEquals(left.mLastTimeVisible, 300000);
+        assertEquals(left.mActivities.get(1), ACTIVITY_PAUSED);
         assertEquals(left.mTotalTimeInForeground, 150000);
+        assertEquals(left.mTotalTimeVisible, 200000 /*300000 - 100000*/);
 
-        left.update("com.test.activity1", 350000, MOVE_TO_FOREGROUND);
+        left.update("com.test.activity1", 350000, Event.ACTIVITY_RESUMED, 1);
         assertEquals(left.mLastTimeUsed, 350000);
-        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
-                new Integer(MOVE_TO_FOREGROUND));
+        assertEquals(left.mLastTimeVisible, 350000);
+        assertEquals(left.mActivities.get(1), Event.ACTIVITY_RESUMED);
         assertEquals(left.mTotalTimeInForeground, 150000);
+        assertEquals(left.mTotalTimeVisible, 250000 /*350000 - 100000*/);
 
-        left.update("com.test.activity1", 400000, END_OF_DAY);
+        left.update("com.test.activity1", 400000, END_OF_DAY, 1);
         assertEquals(left.mLastTimeUsed, 400000);
-        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
-                new Integer(END_OF_DAY));
+        assertEquals(left.mLastTimeVisible, 400000);
+        assertEquals(left.mActivities.get(1), Event.ACTIVITY_RESUMED);
         assertEquals(left.mTotalTimeInForeground, 200000);
+        assertEquals(left.mTotalTimeVisible, 300000 /*400000 - 100000*/);
     }
 
     @Test
@@ -265,28 +320,41 @@
         left.mPackageName = "com.test";
         left.mBeginTimeStamp = 100000;
 
-        left.update("com.test.activity1", 100000, CONTINUE_PREVIOUS_DAY);
-        left.update("com.test.activity2", 100000, CONTINUE_PREVIOUS_DAY);
+        left.update("com.test.activity1", 100000, Event.ACTIVITY_RESUMED, 1);
+        left.update("com.test.activity2", 100000, Event.ACTIVITY_RESUMED, 2);
         assertEquals(left.mLastTimeUsed, 100000);
-        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
-                new Integer(CONTINUE_PREVIOUS_DAY));
-        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity2"),
-                new Integer(CONTINUE_PREVIOUS_DAY));
-        assertEquals(left.mLaunchCount, 0);
+        assertEquals(left.mLastTimeVisible, 100000);
+        assertEquals(left.mActivities.get(1), Event.ACTIVITY_RESUMED);
+        assertEquals(left.mActivities.get(2), Event.ACTIVITY_RESUMED);
+        assertEquals(left.mLaunchCount, 2);
 
-        left.update("com.test.activity1", 350000, MOVE_TO_BACKGROUND);
+        left.update("com.test.activity1", 350000, ACTIVITY_PAUSED, 1);
         assertEquals(left.mLastTimeUsed, 350000);
-        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"), null);
+        assertEquals(left.mLastTimeVisible, 350000);
+        assertEquals(left.mActivities.get(1), ACTIVITY_PAUSED);
         assertEquals(left.mTotalTimeInForeground, 250000 /*350000 - 100000*/);
+        assertEquals(left.mTotalTimeVisible, 250000 /*350000 - 100000*/);
 
-        left.update("com.test.activity2", 450000, MOVE_TO_BACKGROUND);
+        left.update("com.test.activity2", 450000, ACTIVITY_PAUSED, 2);
         assertEquals(left.mLastTimeUsed, 450000);
-        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity2"), null);
+        assertEquals(left.mLastTimeVisible, 450000);
+        assertEquals(left.mActivities.get(2), ACTIVITY_PAUSED);
         assertEquals(left.mTotalTimeInForeground, 250000 + 100000 /*450000 - 350000*/);
+        assertEquals(left.mTotalTimeVisible, 250000 + 100000 /*450000 - 350000*/);
 
-        left.update(null, 500000, END_OF_DAY);
+        left.update("com.test.activity1", 550000, ACTIVITY_STOPPED, 1);
         assertEquals(left.mLastTimeUsed, 450000);
+        assertEquals(left.mLastTimeVisible, 550000);
+        assertEquals(left.mActivities.get(1), ACTIVITY_STOPPED);
         assertEquals(left.mTotalTimeInForeground, 350000);
+        assertEquals(left.mTotalTimeVisible, 350000 + 100000 /*550000 - 450000*/);
+
+        left.update("com.test.activity2", 650000, ACTIVITY_STOPPED, 2);
+        assertEquals(left.mLastTimeUsed, 450000);
+        assertEquals(left.mLastTimeVisible, 650000);
+        assertEquals(left.mActivities.get(2), ACTIVITY_STOPPED);
+        assertEquals(left.mTotalTimeInForeground, 350000);
+        assertEquals(left.mTotalTimeVisible, 450000 + 100000 /*650000 - 550000*/);
     }
 
     @Test
@@ -294,15 +362,14 @@
         left.mPackageName = "com.test";
         left.mBeginTimeStamp = 100000;
 
-        left.update("com.test.service1", 200000, FOREGROUND_SERVICE_START);
+        left.update("com.test.service1", 200000, FOREGROUND_SERVICE_START, 0);
         assertEquals(left.mLastTimeForegroundServiceUsed, 200000);
-        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"),
+        assertEquals(left.mForegroundServices.get("com.test.service1"),
                 new Integer(FOREGROUND_SERVICE_START));
-        assertEquals(left.mLaunchCount, 0);
 
-        left.update("com.test.service1", 350000, FOREGROUND_SERVICE_STOP);
+        left.update("com.test.service1", 350000, FOREGROUND_SERVICE_STOP, 0);
         assertEquals(left.mLastTimeForegroundServiceUsed, 350000);
-        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"), null);
+        assertEquals(left.mForegroundServices.get("com.test.service1"), null);
         assertEquals(left.mTotalTimeForegroundServiceUsed, 350000 - 200000);
     }
 
@@ -311,15 +378,15 @@
         left.mPackageName = "com.test";
         left.mBeginTimeStamp = 100000;
 
-        left.update("com.test.service1", 100000, CONTINUING_FOREGROUND_SERVICE);
+        left.update("com.test.service1", 100000,
+                CONTINUING_FOREGROUND_SERVICE, 0);
         assertEquals(left.mLastTimeForegroundServiceUsed, 100000);
-        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"),
+        assertEquals(left.mForegroundServices.get("com.test.service1"),
                 new Integer(CONTINUING_FOREGROUND_SERVICE));
-        assertEquals(left.mLaunchCount, 0);
 
-        left.update("com.test.service1", 350000, FOREGROUND_SERVICE_STOP);
+        left.update("com.test.service1", 350000, FOREGROUND_SERVICE_STOP, 0);
         assertEquals(left.mLastTimeForegroundServiceUsed, 350000);
-        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"), null);
+        assertEquals(left.mForegroundServices.get("com.test.service1"), null);
         assertEquals(left.mTotalTimeForegroundServiceUsed, 350000 - 100000);
     }
 
@@ -329,16 +396,15 @@
         left.mBeginTimeStamp = 100000;
 
         left.update("com.test.service1", 100000,
-                CONTINUING_FOREGROUND_SERVICE);
+                CONTINUING_FOREGROUND_SERVICE, 0);
         assertEquals(left.mLastTimeForegroundServiceUsed, 100000);
-        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"),
+        assertEquals(left.mForegroundServices.get("com.test.service1"),
                 new Integer(CONTINUING_FOREGROUND_SERVICE));
-        assertEquals(left.mLaunchCount, 0);
 
-        left.update(null, 350000, ROLLOVER_FOREGROUND_SERVICE);
+        left.update(null, 350000, ROLLOVER_FOREGROUND_SERVICE, 0);
         assertEquals(left.mLastTimeForegroundServiceUsed, 350000);
-        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"),
-                new Integer(ROLLOVER_FOREGROUND_SERVICE));
+        assertEquals(left.mForegroundServices.get("com.test.service1"),
+                new Integer(CONTINUING_FOREGROUND_SERVICE));
         assertEquals(left.mTotalTimeForegroundServiceUsed, 350000 - 100000);
     }
 
@@ -348,27 +414,28 @@
         left.mBeginTimeStamp = 100000;
 
         left.update("com.test.service1", 100000,
-                CONTINUING_FOREGROUND_SERVICE);
+                CONTINUING_FOREGROUND_SERVICE, 0);
         assertEquals(left.mLastTimeForegroundServiceUsed, 100000);
-        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"),
+        assertEquals(left.mForegroundServices.get("com.test.service1"),
                 new Integer(CONTINUING_FOREGROUND_SERVICE));
         assertEquals(left.mLaunchCount, 0);
 
-        left.update("com.test.service1", 350000, FOREGROUND_SERVICE_STOP);
+        left.update("com.test.service1", 350000, FOREGROUND_SERVICE_STOP, 0);
         assertEquals(left.mLastTimeForegroundServiceUsed, 350000);
-        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"), null);
+        assertEquals(left.mForegroundServices.get("com.test.service1"), null);
         assertEquals(left.mTotalTimeForegroundServiceUsed, 250000 /*350000 - 100000*/);
 
-        left.update("com.test.service1", 450000, FOREGROUND_SERVICE_START);
+        left.update("com.test.service1", 450000, FOREGROUND_SERVICE_START, 0);
         assertEquals(left.mLastTimeForegroundServiceUsed, 450000);
-        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"),
+        assertEquals(left.mForegroundServices.get("com.test.service1"),
                 new Integer(FOREGROUND_SERVICE_START));
         assertEquals(left.mTotalTimeForegroundServiceUsed, 250000);
 
-        left.update("com.test.service1", 500000, FOREGROUND_SERVICE_STOP);
+        left.update("com.test.service1", 500000, FOREGROUND_SERVICE_STOP, 0);
         assertEquals(left.mLastTimeForegroundServiceUsed, 500000);
-        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"), null);
-        assertEquals(left.mTotalTimeForegroundServiceUsed, 250000 + 50000 /*500000 - 450000*/);
+        assertEquals(left.mForegroundServices.get("com.test.service1"), null);
+        assertEquals(left.mTotalTimeForegroundServiceUsed,
+                250000 + 50000 /*500000 - 450000*/);
     }
 
     @Test
@@ -377,27 +444,27 @@
         left.mBeginTimeStamp = 100000;
 
         left.update("com.test.service1", 100000,
-                CONTINUING_FOREGROUND_SERVICE);
+                CONTINUING_FOREGROUND_SERVICE, 0);
         left.update("com.test.service2", 100000,
-                CONTINUING_FOREGROUND_SERVICE);
+                CONTINUING_FOREGROUND_SERVICE, 0);
         assertEquals(left.mLastTimeForegroundServiceUsed, 100000);
-        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"),
+        assertEquals(left.mForegroundServices.get("com.test.service1"),
                 new Integer(CONTINUING_FOREGROUND_SERVICE));
-        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service2"),
+        assertEquals(left.mForegroundServices.get("com.test.service2"),
                 new Integer(CONTINUING_FOREGROUND_SERVICE));
-        assertEquals(left.mLaunchCount, 0);
 
-        left.update("com.test.service1", 350000, FOREGROUND_SERVICE_STOP);
+        left.update("com.test.service1", 350000, FOREGROUND_SERVICE_STOP, 0);
         assertEquals(left.mLastTimeForegroundServiceUsed, 350000);
-        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"), null);
+        assertEquals(left.mForegroundServices.get("com.test.service1"), null);
         assertEquals(left.mTotalTimeForegroundServiceUsed, 250000 /*350000 - 100000*/);
 
-        left.update("com.test.service2", 450000, FOREGROUND_SERVICE_STOP);
+        left.update("com.test.service2", 450000, FOREGROUND_SERVICE_STOP, 0);
         assertEquals(left.mLastTimeForegroundServiceUsed, 450000);
-        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service2"), null);
-        assertEquals(left.mTotalTimeForegroundServiceUsed, 250000 + 100000 /*450000 - 350000*/);
+        assertEquals(left.mForegroundServices.get("com.test.service2"), null);
+        assertEquals(left.mTotalTimeForegroundServiceUsed,
+                250000 + 100000 /*450000 - 350000*/);
 
-        left.update(null, 500000, ROLLOVER_FOREGROUND_SERVICE);
+        left.update(null, 500000, ROLLOVER_FOREGROUND_SERVICE, 0);
         assertEquals(left.mLastTimeForegroundServiceUsed, 450000);
         assertEquals(left.mTotalTimeForegroundServiceUsed, 350000);
     }
@@ -407,76 +474,117 @@
         left.mPackageName = "com.test";
         left.mBeginTimeStamp = 100000;
 
-        left.update("com.test.activity1", 100000, CONTINUE_PREVIOUS_DAY);
-        left.update("com.test.activity2", 100000, CONTINUE_PREVIOUS_DAY);
+        left.update("com.test.activity1", 100000, Event.ACTIVITY_RESUMED, 1);
+        left.update("com.test.activity2", 100000, Event.ACTIVITY_RESUMED, 2);
         left.update("com.test.service1", 100000,
-                CONTINUING_FOREGROUND_SERVICE);
+                CONTINUING_FOREGROUND_SERVICE, 0);
         left.update("com.test.service2", 100000,
-                CONTINUING_FOREGROUND_SERVICE);
+                CONTINUING_FOREGROUND_SERVICE, 0);
         assertEquals(left.mLastTimeUsed, 100000);
         assertEquals(left.mLastTimeForegroundServiceUsed, 100000);
-        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
-                new Integer(CONTINUE_PREVIOUS_DAY));
-        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity2"),
-                new Integer(CONTINUE_PREVIOUS_DAY));
-        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"),
+        assertEquals(left.mActivities.get(1), Event.ACTIVITY_RESUMED);
+        assertEquals(left.mActivities.get(2), Event.ACTIVITY_RESUMED);
+        assertEquals(left.mForegroundServices.get("com.test.service1"),
                 new Integer(CONTINUING_FOREGROUND_SERVICE));
-        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service2"),
+        assertEquals(left.mForegroundServices.get("com.test.service2"),
                 new Integer(CONTINUING_FOREGROUND_SERVICE));
-        assertEquals(left.mLaunchCount, 0);
+        assertEquals(left.mLaunchCount, 2);
 
-        left.update("com.test.activity1", 350000, MOVE_TO_BACKGROUND);
+        left.update("com.test.activity1", 350000, ACTIVITY_PAUSED, 1);
         assertEquals(left.mLastTimeUsed, 350000);
-        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"), null);
+        assertEquals(left.mLastTimeVisible, 350000);
+        assertEquals(left.mActivities.get(1), ACTIVITY_PAUSED);
         assertEquals(left.mTotalTimeInForeground, 250000 /*350000 - 100000*/);
+        assertEquals(left.mTotalTimeVisible, 250000 /*350000 - 100000*/);
 
-        left.update("com.test.service1", 400000, FOREGROUND_SERVICE_STOP);
+        left.update("com.test.service1", 400000, FOREGROUND_SERVICE_STOP, 0);
         assertEquals(left.mLastTimeForegroundServiceUsed, 400000);
-        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"), null);
+        assertEquals(left.mForegroundServices.get("com.test.service1"), null);
         assertEquals(left.mTotalTimeForegroundServiceUsed, 300000 /*400000 - 100000*/);
 
-        left.update("com.test.activity2", 450000, MOVE_TO_BACKGROUND);
+        left.update("com.test.activity2", 450000, ACTIVITY_PAUSED, 2);
         assertEquals(left.mLastTimeUsed, 450000);
-        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity2"), null);
+        assertEquals(left.mLastTimeVisible, 450000);
+        assertEquals(left.mActivities.get(2), ACTIVITY_PAUSED);
         assertEquals(left.mTotalTimeInForeground, 250000 + 100000 /*450000 - 350000*/);
+        assertEquals(left.mTotalTimeVisible, 250000 + 100000 /*450000 - 350000*/);
 
-        left.update("com.test.service2", 500000, FOREGROUND_SERVICE_STOP);
+        left.update("com.test.service2", 500000, FOREGROUND_SERVICE_STOP, 0);
         assertEquals(left.mLastTimeForegroundServiceUsed, 500000);
-        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service2"), null);
-        assertEquals(left.mTotalTimeForegroundServiceUsed, 300000 + 100000 /*500000 - 400000*/);
+        assertEquals(left.mForegroundServices.get("com.test.service2"), null);
+        assertEquals(left.mTotalTimeForegroundServiceUsed,
+                300000 + 100000 /*500000 - 400000*/);
 
 
-        left.update(null, 550000, END_OF_DAY);
+        left.update(null, 550000, END_OF_DAY, 0);
         assertEquals(left.mLastTimeUsed, 450000);
+        assertEquals(left.mLastTimeVisible, 550000);
         assertEquals(left.mTotalTimeInForeground, 350000);
-        left.update(null, 550000, ROLLOVER_FOREGROUND_SERVICE);
+        assertEquals(left.mTotalTimeVisible, 450000);
+
+        left.update(null, 550000, ROLLOVER_FOREGROUND_SERVICE, 0);
         assertEquals(left.mLastTimeForegroundServiceUsed, 500000);
         assertEquals(left.mTotalTimeForegroundServiceUsed, 400000);
     }
 
+    @Test
+    public void testEvent_FLUSH_TO_DISK() {
+        testClosingEvent(FLUSH_TO_DISK);
+    }
+
+    private void testClosingEvent(int eventType) {
+        // When these three closing events are received, all open activities/services need to be
+        // closed and usage stats are updated.
+        if (eventType != FLUSH_TO_DISK) {
+            fail("Closing eventType must be one of FLUSH_TO_DISK");
+        }
+
+        left.mPackageName = "com.test";
+        left.mBeginTimeStamp = 100000;
+
+        left.update("com.test.activity1", 100000, Event.ACTIVITY_RESUMED, 1);
+        assertEquals(left.mLastTimeUsed, 100000);
+        assertEquals(left.mLastTimeVisible, 100000);
+        assertEquals(left.mActivities.get(1), Event.ACTIVITY_RESUMED);
+
+        left.update("com.test.service1", 150000, FOREGROUND_SERVICE_START, 0);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 150000);
+        assertEquals(left.mForegroundServices.get("com.test.service1"),
+                new Integer(FOREGROUND_SERVICE_START));
+
+        left.update(null, 200000, eventType, 0);
+        assertEquals(left.mLastTimeUsed, 200000);
+        assertEquals(left.mLastTimeVisible, 200000);
+        assertEquals(left.mTotalTimeInForeground, 200000 - 100000);
+        assertEquals(left.mTotalTimeVisible, 200000 - 100000);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 200000);
+        assertEquals(left.mTotalTimeForegroundServiceUsed, 200000 - 150000);
+    }
+
     void compareUsageStats(UsageStats us1, UsageStats us2) {
         assertEquals(us1.mPackageName, us2.mPackageName);
         assertEquals(us1.mBeginTimeStamp, us2.mBeginTimeStamp);
         assertEquals(us1.mLastTimeUsed, us2.mLastTimeUsed);
+        assertEquals(us1.mLastTimeVisible, us2.mLastTimeVisible);
         assertEquals(us1.mLastTimeForegroundServiceUsed, us2.mLastTimeForegroundServiceUsed);
         assertEquals(us1.mTotalTimeInForeground, us2.mTotalTimeInForeground);
         assertEquals(us1.mTotalTimeForegroundServiceUsed, us2.mTotalTimeForegroundServiceUsed);
         assertEquals(us1.mAppLaunchCount, us2.mAppLaunchCount);
-        assertEquals(us1.mLastForegroundActivityEventMap.size(),
-                us2.mLastForegroundActivityEventMap.size());
-        for (int i = 0; i < us1.mLastForegroundActivityEventMap.size(); i++) {
-            assertEquals(us1.mLastForegroundActivityEventMap.keyAt(i),
-                    us2.mLastForegroundActivityEventMap.keyAt(i));
-            assertEquals(us1.mLastForegroundActivityEventMap.valueAt(i),
-                    us2.mLastForegroundActivityEventMap.valueAt(i));
+        assertEquals(us1.mActivities.size(),
+                us2.mActivities.size());
+        for (int i = 0; i < us1.mActivities.size(); i++) {
+            assertEquals(us1.mActivities.keyAt(i),
+                    us2.mActivities.keyAt(i));
+            assertEquals(us1.mActivities.valueAt(i),
+                    us2.mActivities.valueAt(i));
         }
-        assertEquals(us1.mLastForegroundServiceEventMap.size(),
-                us2.mLastForegroundServiceEventMap.size());
-        for (int i = 0; i < us1.mLastForegroundServiceEventMap.size(); i++) {
-            assertEquals(us1.mLastForegroundServiceEventMap.keyAt(i),
-                    us2.mLastForegroundServiceEventMap.keyAt(i));
-            assertEquals(us1.mLastForegroundServiceEventMap.valueAt(i),
-                    us2.mLastForegroundServiceEventMap.valueAt(i));
+        assertEquals(us1.mForegroundServices.size(),
+                us2.mForegroundServices.size());
+        for (int i = 0; i < us1.mForegroundServices.size(); i++) {
+            assertEquals(us1.mForegroundServices.keyAt(i),
+                    us2.mForegroundServices.keyAt(i));
+            assertEquals(us1.mForegroundServices.valueAt(i),
+                    us2.mForegroundServices.valueAt(i));
         }
         assertEquals(us1.mChooserCounts, us2.mChooserCounts);
     }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 6e9db88..69cfcc2 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2724,47 +2724,86 @@
         return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
     }
 
-    void updateUsageStats(ComponentName activity, int uid, int userId, boolean resumed) {
+    /**
+     * Update battery stats on the activity' usage.
+     * @param activity
+     * @param uid
+     * @param userId
+     * @param resumed
+     */
+    void updateBatteryStats(ComponentName activity, int uid, int userId, boolean resumed) {
         if (DEBUG_SWITCH) {
             Slog.d(TAG_SWITCH,
-                    "updateUsageStats: comp=" + activity + "res=" + resumed);
+                    "updateBatteryStats: comp=" + activity + "res=" + resumed);
         }
         final BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
         StatsLog.write(StatsLog.ACTIVITY_FOREGROUND_STATE_CHANGED,
-            uid, activity.getPackageName(),
-            activity.getShortClassName(), resumed ?
-                        StatsLog.ACTIVITY_FOREGROUND_STATE_CHANGED__STATE__FOREGROUND :
+                uid, activity.getPackageName(), activity.getShortClassName(),
+                resumed ? StatsLog.ACTIVITY_FOREGROUND_STATE_CHANGED__STATE__FOREGROUND :
                         StatsLog.ACTIVITY_FOREGROUND_STATE_CHANGED__STATE__BACKGROUND);
-        if (resumed) {
-            if (mUsageStatsService != null) {
-                mUsageStatsService.reportEvent(activity, userId,
-                        UsageEvents.Event.MOVE_TO_FOREGROUND);
-
-            }
-            synchronized (stats) {
+        synchronized (stats) {
+            if (resumed) {
                 stats.noteActivityResumedLocked(uid);
-            }
-        } else {
-            if (mUsageStatsService != null) {
-                mUsageStatsService.reportEvent(activity, userId,
-                        UsageEvents.Event.MOVE_TO_BACKGROUND);
-            }
-            synchronized (stats) {
+            } else {
                 stats.noteActivityPausedLocked(uid);
             }
         }
     }
 
+    /**
+     * Update UsageStas on the activity's usage.
+     * @param activity
+     * @param userId
+     * @param event
+     * @param appToken ActivityRecord's appToken.
+     */
+    public void updateActivityUsageStats(ComponentName activity, int userId, int event,
+            IBinder appToken) {
+        if (DEBUG_SWITCH) {
+            Slog.d(TAG_SWITCH, "updateActivityUsageStats: comp="
+                    + activity + " hash=" + appToken.hashCode() + " event=" + event);
+        }
+        synchronized (this) {
+            if (mUsageStatsService != null) {
+                mUsageStatsService.reportEvent(activity, userId, event, appToken.hashCode());
+            }
+        }
+    }
+
+    /**
+     * Update UsageStats on this package's usage.
+     * @param packageName
+     * @param userId
+     * @param event
+     */
+    public void updateActivityUsageStats(String packageName, int userId, int event) {
+        if (DEBUG_SWITCH) {
+            Slog.d(TAG_SWITCH, "updateActivityUsageStats: package="
+                    + packageName + " event=" + event);
+        }
+        synchronized (this) {
+            if (mUsageStatsService != null) {
+                mUsageStatsService.reportEvent(packageName, userId, event);
+            }
+        }
+    }
+
+    /**
+     * Update Usages on this foreground service's usage.
+     * @param service
+     * @param userId
+     * @param started
+     */
     void updateForegroundServiceUsageStats(ComponentName service, int userId, boolean started) {
         if (DEBUG_SWITCH) {
             Slog.d(TAG_SWITCH, "updateForegroundServiceUsageStats: comp="
-                    + service + "started=" + started);
+                    + service + " started=" + started);
         }
         synchronized (this) {
             if (mUsageStatsService != null) {
                 mUsageStatsService.reportEvent(service, userId,
                         started ? UsageEvents.Event.FOREGROUND_SERVICE_START
-                                : UsageEvents.Event.FOREGROUND_SERVICE_STOP);
+                                : UsageEvents.Event.FOREGROUND_SERVICE_STOP, 0);
             }
         }
     }
@@ -19068,9 +19107,19 @@
         }
 
         @Override
-        public void updateUsageStats(ComponentName activity, int uid, int userId, boolean resumed) {
+        public void updateBatteryStats(ComponentName activity, int uid, int userId,
+                boolean resumed) {
             synchronized (ActivityManagerService.this) {
-                ActivityManagerService.this.updateUsageStats(activity, uid, userId, resumed);
+                ActivityManagerService.this.updateBatteryStats(activity, uid, userId, resumed);
+            }
+        }
+
+        @Override
+        public void updateActivityUsageStats(ComponentName activity, int userId, int event,
+                IBinder appToken) {
+            synchronized (ActivityManagerService.this) {
+                ActivityManagerService.this.updateActivityUsageStats(activity, userId, event,
+                        appToken);
             }
         }
 
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 5f380e5..88dd3c6 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -96,6 +96,7 @@
 import static com.android.server.am.ActivityRecordProto.VISIBLE;
 import static com.android.server.am.EventLogTags.AM_RELAUNCH_ACTIVITY;
 import static com.android.server.am.EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY;
+import static com.android.server.wm.ActivityStack.ActivityState.DESTROYED;
 import static com.android.server.wm.ActivityStack.ActivityState.INITIALIZING;
 import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
 import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
@@ -122,8 +123,7 @@
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
-import static com.android.server.wm.ActivityTaskManagerService
-        .RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
+import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
 import static com.android.server.wm.IdentifierProto.HASH_CODE;
 import static com.android.server.wm.IdentifierProto.TITLE;
 import static com.android.server.wm.IdentifierProto.USER_ID;
@@ -157,6 +157,7 @@
 import android.app.servertransaction.PipModeChangeItem;
 import android.app.servertransaction.ResumeActivityItem;
 import android.app.servertransaction.WindowVisibilityItem;
+import android.app.usage.UsageEvents.Event;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
@@ -1798,6 +1799,18 @@
             }
             mAppWindowToken.detachChildren();
         }
+
+        if (state == RESUMED) {
+            mAtmService.updateBatteryStats(this, true);
+            mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_RESUMED);
+        } else if (state == PAUSED) {
+            mAtmService.updateBatteryStats(this, false);
+            mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_PAUSED);
+        } else if (state == STOPPED) {
+            mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_STOPPED);
+        } else if (state == DESTROYED) {
+            mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_DESTROYED);
+        }
     }
 
     ActivityState getState() {
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index b0fb09b..1a6ae3e 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -1617,7 +1617,6 @@
             try {
                 EventLogTags.writeAmPauseActivity(prev.mUserId, System.identityHashCode(prev),
                         prev.shortComponentName, "userLeaving=" + userLeaving);
-                mService.updateUsageStats(prev, false);
 
                 mService.getLifecycleManager().scheduleTransaction(prev.app.getThread(),
                         prev.appToken, PauseActivityItem.obtain(prev.finishing, userLeaving,
@@ -4649,9 +4648,6 @@
                                     r.mUserId, System.identityHashCode(r),
                                     r.getTaskRecord().taskId, r.shortComponentName,
                                     "proc died without state saved");
-                            if (r.getState() == RESUMED) {
-                                mService.updateUsageStats(r, false);
-                            }
                         }
                     } else {
                         // We have the current state for this activity, so
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 6a5954f..4339e51 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -2040,9 +2040,6 @@
         mStoppingActivities.remove(r);
 
         final ActivityStack stack = r.getActivityStack();
-        if (mRootActivityContainer.isTopDisplayFocusedStack(stack)) {
-            mService.updateUsageStats(r, true);
-        }
         if (stack.getDisplay().allResumedActivitiesComplete()) {
             mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
             // Make sure activity & window visibility should be identical
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 182d1a0..46ee08f 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -5234,13 +5234,20 @@
         mH.post(mAmInternal::updateCpuStats);
     }
 
-    void updateUsageStats(ActivityRecord component, boolean resumed) {
-        final Message m = PooledLambda.obtainMessage(ActivityManagerInternal::updateUsageStats,
+    void updateBatteryStats(ActivityRecord component, boolean resumed) {
+        final Message m = PooledLambda.obtainMessage(ActivityManagerInternal::updateBatteryStats,
                 mAmInternal, component.mActivityComponent, component.app.mUid, component.mUserId,
                 resumed);
         mH.sendMessage(m);
     }
 
+    void updateActivityUsageStats(ActivityRecord activity, int event) {
+        final Message m = PooledLambda.obtainMessage(
+                ActivityManagerInternal::updateActivityUsageStats, mAmInternal,
+                activity.mActivityComponent, activity.mUserId, event, activity.appToken);
+        mH.sendMessage(m);
+    }
+
     void setBooting(boolean booting) {
         mAmInternal.setBooting(booting);
     }
diff --git a/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java b/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
index bf7f53d..860656b 100644
--- a/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
+++ b/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
@@ -16,6 +16,8 @@
 
 package com.android.server.usage;
 
+import static android.app.usage.UsageEvents.Event.MAX_EVENT_TYPE;
+
 import static junit.framework.TestCase.fail;
 
 import static org.testng.Assert.assertEquals;
@@ -136,9 +138,11 @@
                 event.mFlags |= Event.FLAG_IS_PACKAGE_INSTANT_APP;
             }
 
-            event.mClass = ".fake.class.name" + i % 11;
+            final int instanceId = i % 11;
+            event.mClass = ".fake.class.name" + instanceId;
             event.mTimeStamp = time;
-            event.mEventType = i % 19; //"random" event type
+            event.mEventType = i % (MAX_EVENT_TYPE + 1); //"random" event type
+            event.mInstanceId = instanceId;
 
             switch (event.mEventType) {
                 case Event.CONFIGURATION_CHANGE:
@@ -160,7 +164,8 @@
             }
 
             mIntervalStats.events.insert(event);
-            mIntervalStats.update(event.mPackage, event.mClass, event.mTimeStamp, event.mEventType);
+            mIntervalStats.update(event.mPackage, event.mClass, event.mTimeStamp, event.mEventType,
+                    event.mInstanceId);
 
             time += timeProgression; // Arbitrary progression of time
         }
@@ -219,7 +224,9 @@
         // mBeginTimeStamp is based on the enclosing IntervalStats, don't bother checking
         // mEndTimeStamp is based on the enclosing IntervalStats, don't bother checking
         assertEquals(us1.mLastTimeUsed, us2.mLastTimeUsed);
+        assertEquals(us1.mLastTimeVisible, us2.mLastTimeVisible);
         assertEquals(us1.mTotalTimeInForeground, us2.mTotalTimeInForeground);
+        assertEquals(us1.mTotalTimeVisible, us2.mTotalTimeVisible);
         assertEquals(us1.mLastTimeForegroundServiceUsed, us2.mLastTimeForegroundServiceUsed);
         assertEquals(us1.mTotalTimeForegroundServiceUsed, us2.mTotalTimeForegroundServiceUsed);
         // mLaunchCount not persisted, so skipped
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
index 79a052c..569c6d4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -447,7 +447,11 @@
         }
 
         @Override
-        void updateUsageStats(ActivityRecord component, boolean resumed) {
+        void updateBatteryStats(ActivityRecord component, boolean resumed) {
+        }
+
+        @Override
+        void updateActivityUsageStats(ActivityRecord activity, int event) {
         }
 
         @Override
diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java
index 4f573a4..65ed85d 100644
--- a/services/usage/java/com/android/server/usage/AppStandbyController.java
+++ b/services/usage/java/com/android/server/usage/AppStandbyController.java
@@ -842,8 +842,8 @@
             final boolean previouslyIdle = mAppIdleHistory.isIdle(
                     event.mPackage, userId, elapsedRealtime);
             // Inform listeners if necessary
-            if ((event.mEventType == UsageEvents.Event.MOVE_TO_FOREGROUND
-                    || event.mEventType == UsageEvents.Event.MOVE_TO_BACKGROUND
+            if ((event.mEventType == UsageEvents.Event.ACTIVITY_RESUMED
+                    || event.mEventType == UsageEvents.Event.ACTIVITY_PAUSED
                     || event.mEventType == UsageEvents.Event.SYSTEM_INTERACTION
                     || event.mEventType == UsageEvents.Event.USER_INTERACTION
                     || event.mEventType == UsageEvents.Event.NOTIFICATION_SEEN
@@ -894,8 +894,8 @@
 
     private int usageEventToSubReason(int eventType) {
         switch (eventType) {
-            case UsageEvents.Event.MOVE_TO_FOREGROUND: return REASON_SUB_USAGE_MOVE_TO_FOREGROUND;
-            case UsageEvents.Event.MOVE_TO_BACKGROUND: return REASON_SUB_USAGE_MOVE_TO_BACKGROUND;
+            case UsageEvents.Event.ACTIVITY_RESUMED: return REASON_SUB_USAGE_MOVE_TO_FOREGROUND;
+            case UsageEvents.Event.ACTIVITY_PAUSED: return REASON_SUB_USAGE_MOVE_TO_BACKGROUND;
             case UsageEvents.Event.SYSTEM_INTERACTION: return REASON_SUB_USAGE_SYSTEM_INTERACTION;
             case UsageEvents.Event.USER_INTERACTION: return REASON_SUB_USAGE_USER_INTERACTION;
             case UsageEvents.Event.NOTIFICATION_SEEN: return REASON_SUB_USAGE_NOTIFICATION_SEEN;
diff --git a/services/usage/java/com/android/server/usage/IntervalStats.java b/services/usage/java/com/android/server/usage/IntervalStats.java
index 8405267..94cc650 100644
--- a/services/usage/java/com/android/server/usage/IntervalStats.java
+++ b/services/usage/java/com/android/server/usage/IntervalStats.java
@@ -15,10 +15,31 @@
  */
 package com.android.server.usage;
 
+import static android.app.usage.UsageEvents.Event.ACTIVITY_DESTROYED;
+import static android.app.usage.UsageEvents.Event.ACTIVITY_PAUSED;
+import static android.app.usage.UsageEvents.Event.ACTIVITY_RESUMED;
+import static android.app.usage.UsageEvents.Event.ACTIVITY_STOPPED;
+import static android.app.usage.UsageEvents.Event.CONFIGURATION_CHANGE;
+import static android.app.usage.UsageEvents.Event.CONTINUE_PREVIOUS_DAY;
+import static android.app.usage.UsageEvents.Event.CONTINUING_FOREGROUND_SERVICE;
+import static android.app.usage.UsageEvents.Event.END_OF_DAY;
+import static android.app.usage.UsageEvents.Event.FLUSH_TO_DISK;
+import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_START;
+import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_STOP;
+import static android.app.usage.UsageEvents.Event.KEYGUARD_HIDDEN;
+import static android.app.usage.UsageEvents.Event.KEYGUARD_SHOWN;
+import static android.app.usage.UsageEvents.Event.NOTIFICATION_INTERRUPTION;
+import static android.app.usage.UsageEvents.Event.ROLLOVER_FOREGROUND_SERVICE;
+import static android.app.usage.UsageEvents.Event.SCREEN_INTERACTIVE;
+import static android.app.usage.UsageEvents.Event.SCREEN_NON_INTERACTIVE;
+import static android.app.usage.UsageEvents.Event.SHORTCUT_INVOCATION;
+import static android.app.usage.UsageEvents.Event.STANDBY_BUCKET_CHANGED;
+import static android.app.usage.UsageEvents.Event.SYSTEM_INTERACTION;
+
 import android.app.usage.ConfigurationStats;
 import android.app.usage.EventList;
 import android.app.usage.EventStats;
-import android.app.usage.UsageEvents;
+import android.app.usage.UsageEvents.Event;
 import android.app.usage.UsageStats;
 import android.content.res.Configuration;
 import android.util.ArrayMap;
@@ -125,8 +146,8 @@
     /**
      * Builds a UsageEvents.Event, but does not add it internally.
      */
-    UsageEvents.Event buildEvent(String packageName, String className) {
-        UsageEvents.Event event = new UsageEvents.Event();
+    Event buildEvent(String packageName, String className) {
+        Event event = new Event();
         event.mPackage = getCachedStringRef(packageName);
         if (className != null) {
             event.mClass = getCachedStringRef(className);
@@ -138,9 +159,9 @@
      * Builds a UsageEvents.Event from a proto, but does not add it internally.
      * Built here to take advantage of the cached String Refs
      */
-    UsageEvents.Event buildEvent(ProtoInputStream parser, List<String> stringPool)
+    Event buildEvent(ProtoInputStream parser, List<String> stringPool)
             throws IOException {
-        final UsageEvents.Event event = new UsageEvents.Event();
+        final Event event = new Event();
         while (true) {
             switch (parser.nextField()) {
                 case (int) IntervalStatsProto.Event.PACKAGE:
@@ -190,20 +211,23 @@
                             parser.readInt(IntervalStatsProto.Event.NOTIFICATION_CHANNEL_INDEX)
                                     - 1));
                     break;
+                case (int) IntervalStatsProto.Event.INSTANCE_ID:
+                    event.mInstanceId = parser.readInt(IntervalStatsProto.Event.INSTANCE_ID);
+                    break;
                 case ProtoInputStream.NO_MORE_FIELDS:
                     // Handle default values for certain events types
                     switch (event.mEventType) {
-                        case UsageEvents.Event.CONFIGURATION_CHANGE:
+                        case CONFIGURATION_CHANGE:
                             if (event.mConfiguration == null) {
                                 event.mConfiguration = new Configuration();
                             }
                             break;
-                        case UsageEvents.Event.SHORTCUT_INVOCATION:
+                        case SHORTCUT_INVOCATION:
                             if (event.mShortcutId == null) {
                                 event.mShortcutId = "";
                             }
                             break;
-                        case UsageEvents.Event.NOTIFICATION_INTERRUPTION:
+                        case NOTIFICATION_INTERRUPTION:
                             if (event.mNotificationChannelId == null) {
                                 event.mNotificationChannelId = "";
                             }
@@ -220,14 +244,15 @@
 
     private boolean isStatefulEvent(int eventType) {
         switch (eventType) {
-            case UsageEvents.Event.MOVE_TO_FOREGROUND:
-            case UsageEvents.Event.MOVE_TO_BACKGROUND:
-            case UsageEvents.Event.FOREGROUND_SERVICE_START:
-            case UsageEvents.Event.FOREGROUND_SERVICE_STOP:
-            case UsageEvents.Event.END_OF_DAY:
-            case UsageEvents.Event.ROLLOVER_FOREGROUND_SERVICE:
-            case UsageEvents.Event.CONTINUE_PREVIOUS_DAY:
-            case UsageEvents.Event.CONTINUING_FOREGROUND_SERVICE:
+            case ACTIVITY_RESUMED:
+            case ACTIVITY_PAUSED:
+            case ACTIVITY_STOPPED:
+            case FOREGROUND_SERVICE_START:
+            case FOREGROUND_SERVICE_STOP:
+            case END_OF_DAY:
+            case ROLLOVER_FOREGROUND_SERVICE:
+            case CONTINUE_PREVIOUS_DAY:
+            case CONTINUING_FOREGROUND_SERVICE:
                 return true;
         }
         return false;
@@ -238,17 +263,56 @@
      * interaction. Excludes those that are internally generated.
      */
     private boolean isUserVisibleEvent(int eventType) {
-        return eventType != UsageEvents.Event.SYSTEM_INTERACTION
-                && eventType != UsageEvents.Event.STANDBY_BUCKET_CHANGED;
+        return eventType != SYSTEM_INTERACTION
+                && eventType != STANDBY_BUCKET_CHANGED;
     }
 
     /**
+     * Update the IntervalStats by a activity or foreground service event.
+     * @param packageName package name of this event. Is null if event targets to all packages.
+     * @param className class name of a activity or foreground service, could be null to if this
+     *                  is sent to all activities/services in this package.
+     * @param timeStamp Epoch timestamp in milliseconds.
+     * @param eventType event type as in {@link Event}
+     * @param instanceId if className is an activity, the hashCode of ActivityRecord's appToken.
+     *                 if className is not an activity, instanceId is not used.
      * @hide
      */
     @VisibleForTesting
-    public void update(String packageName, String className, long timeStamp, int eventType) {
-        UsageStats usageStats = getOrCreateUsageStats(packageName);
-        usageStats.update(className, timeStamp, eventType);
+    public void update(String packageName, String className, long timeStamp, int eventType,
+            int instanceId) {
+        if (eventType == FLUSH_TO_DISK) {
+            // FLUSH_TO_DISK are sent to all packages.
+            final int size = packageStats.size();
+            for (int i = 0; i < size; i++) {
+                UsageStats usageStats = packageStats.valueAt(i);
+                usageStats.update(null, timeStamp, eventType, instanceId);
+            }
+        } else if (eventType == ACTIVITY_DESTROYED) {
+            UsageStats usageStats = packageStats.get(packageName);
+            if (usageStats != null) {
+                // If previous event is not ACTIVITY_STOPPED, convert ACTIVITY_DESTROYED
+                // to ACTIVITY_STOPPED and add to event list.
+                // Otherwise do not add anything to event list. (Because we want to save space
+                // and we do not want a ACTIVITY_STOPPED followed by
+                // ACTIVITY_DESTROYED in event list).
+                final int index = usageStats.mActivities.indexOfKey(instanceId);
+                if (index >= 0) {
+                    final int type = usageStats.mActivities.valueAt(index);
+                    if (type != ACTIVITY_STOPPED) {
+                        Event event = new Event(ACTIVITY_STOPPED, timeStamp);
+                        event.mPackage = packageName;
+                        event.mClass = className;
+                        event.mInstanceId = instanceId;
+                        addEvent(event);
+                    }
+                }
+                usageStats.update(className, timeStamp, ACTIVITY_DESTROYED, instanceId);
+            }
+        } else {
+            UsageStats usageStats = getOrCreateUsageStats(packageName);
+            usageStats.update(className, timeStamp, eventType, instanceId);
+        }
         endTime = timeStamp;
     }
 
@@ -256,7 +320,7 @@
      * @hide
      */
     @VisibleForTesting
-    public void addEvent(UsageEvents.Event event) {
+    public void addEvent(Event event) {
         if (events == null) {
             events = new EventList();
         }
@@ -265,7 +329,7 @@
         if (event.mClass != null) {
             event.mClass = getCachedStringRef(event.mClass);
         }
-        if (event.mEventType == UsageEvents.Event.NOTIFICATION_INTERRUPTION) {
+        if (event.mEventType == NOTIFICATION_INTERRUPTION) {
             event.mNotificationChannelId = getCachedStringRef(event.mNotificationChannelId);
         }
         events.insert(event);
@@ -338,13 +402,13 @@
     }
 
     void addEventStatsTo(List<EventStats> out) {
-        interactiveTracker.addToEventStats(out, UsageEvents.Event.SCREEN_INTERACTIVE,
+        interactiveTracker.addToEventStats(out, SCREEN_INTERACTIVE,
                 beginTime, endTime);
-        nonInteractiveTracker.addToEventStats(out, UsageEvents.Event.SCREEN_NON_INTERACTIVE,
+        nonInteractiveTracker.addToEventStats(out, SCREEN_NON_INTERACTIVE,
                 beginTime, endTime);
-        keyguardShownTracker.addToEventStats(out, UsageEvents.Event.KEYGUARD_SHOWN,
+        keyguardShownTracker.addToEventStats(out, KEYGUARD_SHOWN,
                 beginTime, endTime);
-        keyguardHiddenTracker.addToEventStats(out, UsageEvents.Event.KEYGUARD_HIDDEN,
+        keyguardHiddenTracker.addToEventStats(out, KEYGUARD_HIDDEN,
                 beginTime, endTime);
     }
 
diff --git a/services/usage/java/com/android/server/usage/UsageStatsProto.java b/services/usage/java/com/android/server/usage/UsageStatsProto.java
index 8e1c060..d706537 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsProto.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsProto.java
@@ -135,6 +135,15 @@
                     stats.mTotalTimeForegroundServiceUsed = proto.readLong(
                             IntervalStatsProto.UsageStats.TOTAL_TIME_SERVICE_USED_MS);
                     break;
+                case (int) IntervalStatsProto.UsageStats.LAST_TIME_VISIBLE_MS:
+                    // Time attributes stored is an offset of the beginTime.
+                    stats.mLastTimeVisible = statsOut.beginTime + proto.readLong(
+                            IntervalStatsProto.UsageStats.LAST_TIME_VISIBLE_MS);
+                    break;
+                case (int) IntervalStatsProto.UsageStats.TOTAL_TIME_VISIBLE_MS:
+                    stats.mTotalTimeVisible = proto.readLong(
+                            IntervalStatsProto.UsageStats.TOTAL_TIME_VISIBLE_MS);
+                    break;
             }
         }
         if (stats.mLastTimeUsed == 0) {
@@ -337,6 +346,11 @@
                 usageStats.mLastTimeForegroundServiceUsed - stats.beginTime);
         proto.write(IntervalStatsProto.UsageStats.TOTAL_TIME_SERVICE_USED_MS,
                 usageStats.mTotalTimeForegroundServiceUsed);
+        // Time attributes stored as an offset of the beginTime.
+        proto.write(IntervalStatsProto.UsageStats.LAST_TIME_VISIBLE_MS,
+                usageStats.mLastTimeVisible - stats.beginTime);
+        proto.write(IntervalStatsProto.UsageStats.TOTAL_TIME_VISIBLE_MS,
+                usageStats.mTotalTimeVisible);
         proto.write(IntervalStatsProto.UsageStats.APP_LAUNCH_COUNT, usageStats.mAppLaunchCount);
         writeChooserCounts(proto, usageStats);
         proto.end(token);
@@ -427,6 +441,7 @@
         proto.write(IntervalStatsProto.Event.TIME_MS, event.mTimeStamp - stats.beginTime);
         proto.write(IntervalStatsProto.Event.FLAGS, event.mFlags);
         proto.write(IntervalStatsProto.Event.TYPE, event.mEventType);
+        proto.write(IntervalStatsProto.Event.INSTANCE_ID, event.mInstanceId);
         switch (event.mEventType) {
             case UsageEvents.Event.CONFIGURATION_CHANGE:
                 if (event.mConfiguration != null) {
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 2621252..57dc08f 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -16,6 +16,12 @@
 
 package com.android.server.usage;
 
+import static android.app.usage.UsageEvents.Event.CHOOSER_ACTION;
+import static android.app.usage.UsageEvents.Event.CONFIGURATION_CHANGE;
+import static android.app.usage.UsageEvents.Event.FLUSH_TO_DISK;
+import static android.app.usage.UsageEvents.Event.NOTIFICATION_INTERRUPTION;
+import static android.app.usage.UsageEvents.Event.SHORTCUT_INVOCATION;
+
 import android.Manifest;
 import android.app.ActivityManager;
 import android.app.AppOpsManager;
@@ -28,10 +34,10 @@
 import android.app.usage.EventStats;
 import android.app.usage.IUsageStatsManager;
 import android.app.usage.UsageEvents;
-import android.app.usage.UsageStatsManager;
-import android.app.usage.UsageStatsManager.StandbyBuckets;
 import android.app.usage.UsageEvents.Event;
 import android.app.usage.UsageStats;
+import android.app.usage.UsageStatsManager;
+import android.app.usage.UsageStatsManager.StandbyBuckets;
 import android.app.usage.UsageStatsManagerInternal;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -75,9 +81,7 @@
 import java.io.PrintWriter;
 import java.util.Arrays;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
-import java.util.concurrent.TimeUnit;
 
 /**
  * A service that collects, aggregates, and persists application usage data.
@@ -106,6 +110,7 @@
     static final int MSG_FLUSH_TO_DISK = 1;
     static final int MSG_REMOVE_USER = 2;
     static final int MSG_UID_STATE_CHANGED = 3;
+    static final int MSG_REPORT_EVENT_TO_ALL_USERID = 4;
 
     private final Object mLock = new Object();
     Handler mHandler;
@@ -135,12 +140,10 @@
                 @Override
                 public void onAppIdleStateChanged(String packageName, int userId, boolean idle,
                         int bucket, int reason) {
-                    Event event = new Event();
-                    event.mEventType = Event.STANDBY_BUCKET_CHANGED;
+                    Event event = new Event(Event.STANDBY_BUCKET_CHANGED,
+                            SystemClock.elapsedRealtime());
                     event.mBucketAndReason = (bucket << 16) | (reason & 0xFFFF);
                     event.mPackage = packageName;
-                    // This will later be converted to system time.
-                    event.mTimeStamp = SystemClock.elapsedRealtime();
                     mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
                 }
 
@@ -397,7 +400,7 @@
      * Assuming the event's timestamp is measured in milliseconds since boot,
      * convert it to a system wall time.
      */
-    private void convertToSystemTimeLocked(UsageEvents.Event event) {
+    private void convertToSystemTimeLocked(Event event) {
         event.mTimeStamp = Math.max(0, event.mTimeStamp - mRealTimeSnapshot) + mSystemTimeSnapshot;
     }
 
@@ -406,7 +409,6 @@
      */
     void shutdown() {
         synchronized (mLock) {
-            mHandler.removeMessages(MSG_REPORT_EVENT);
             flushToDiskLocked();
         }
     }
@@ -414,7 +416,7 @@
     /**
      * Called by the Binder stub.
      */
-    void reportEvent(UsageEvents.Event event, int userId) {
+    void reportEvent(Event event, int userId) {
         synchronized (mLock) {
             final long timeNow = checkAndGetTimeLocked();
             final long elapsedRealtime = SystemClock.elapsedRealtime();
@@ -431,14 +433,14 @@
 
             mAppStandby.reportEvent(event, elapsedRealtime, userId);
             switch (event.mEventType) {
-                case Event.MOVE_TO_FOREGROUND:
+                case Event.ACTIVITY_RESUMED:
                     try {
                         mAppTimeLimit.noteUsageStart(event.getPackageName(), userId);
                     } catch (IllegalArgumentException iae) {
                         Slog.e(TAG, "Failed to note usage start", iae);
                     }
                     break;
-                case Event.MOVE_TO_BACKGROUND:
+                case Event.ACTIVITY_PAUSED:
                     try {
                         mAppTimeLimit.noteUsageStop(event.getPackageName(), userId);
                     } catch (IllegalArgumentException iae) {
@@ -450,10 +452,31 @@
     }
 
     /**
-     * Called by the Binder stub.
+     * Some events like FLUSH_TO_DISK need to be sent to all userId.
+     * @param event
+     */
+    void reportEventToAllUserId(Event event) {
+        synchronized (mLock) {
+            final int userCount = mUserState.size();
+            for (int i = 0; i < userCount; i++) {
+                Event copy = new Event(event);
+                reportEvent(copy, mUserState.keyAt(i));
+            }
+        }
+    }
+
+    /**
+     * Called by the Handler for message MSG_FLUSH_TO_DISK.
      */
     void flushToDisk() {
         synchronized (mLock) {
+            // Before flush to disk, report FLUSH_TO_DISK event to signal UsageStats to update app
+            // usage. In case of abrupt power shutdown like battery drain or cold temperature,
+            // all UsageStats has correct data up to last flush to disk.
+            // The FLUSH_TO_DISK event is an internal event, it will not show up in IntervalStats'
+            // EventList.
+            Event event = new Event(FLUSH_TO_DISK, SystemClock.elapsedRealtime());
+            reportEventToAllUserId(event);
             flushToDiskLocked();
         }
     }
@@ -656,9 +679,11 @@
         public void handleMessage(Message msg) {
             switch (msg.what) {
                 case MSG_REPORT_EVENT:
-                    reportEvent((UsageEvents.Event) msg.obj, msg.arg1);
+                    reportEvent((Event) msg.obj, msg.arg1);
                     break;
-
+                case MSG_REPORT_EVENT_TO_ALL_USERID:
+                    reportEventToAllUserId((Event) msg.obj);
+                    break;
                 case MSG_FLUSH_TO_DISK:
                     flushToDisk();
                     break;
@@ -1120,20 +1145,11 @@
                 return;
             }
 
-            UsageEvents.Event event = new UsageEvents.Event();
+            Event event = new Event(CHOOSER_ACTION, SystemClock.elapsedRealtime());
             event.mPackage = packageName;
-
-            // This will later be converted to system time.
-            event.mTimeStamp = SystemClock.elapsedRealtime();
-
-            event.mEventType = Event.CHOOSER_ACTION;
-
             event.mAction = action;
-
             event.mContentType = contentType;
-
             event.mContentAnnotations = annotations;
-
             mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
         }
 
@@ -1251,37 +1267,29 @@
     private final class LocalService extends UsageStatsManagerInternal {
 
         @Override
-        public void reportEvent(ComponentName component, int userId, int eventType) {
+        public void reportEvent(ComponentName component, int userId, int eventType,
+                int instanceId) {
             if (component == null) {
                 Slog.w(TAG, "Event reported without a component name");
                 return;
             }
 
-            UsageEvents.Event event = new UsageEvents.Event();
+            Event event = new Event(eventType, SystemClock.elapsedRealtime());
             event.mPackage = component.getPackageName();
             event.mClass = component.getClassName();
-
-            // This will later be converted to system time.
-            event.mTimeStamp = SystemClock.elapsedRealtime();
-
-            event.mEventType = eventType;
+            event.mInstanceId = instanceId;
             mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
         }
 
         @Override
         public void reportEvent(String packageName, int userId, int eventType) {
             if (packageName == null) {
-                Slog.w(TAG, "Event reported without a package name");
+                Slog.w(TAG, "Event reported without a package name, eventType:" + eventType);
                 return;
             }
 
-            UsageEvents.Event event = new UsageEvents.Event();
+            Event event = new Event(eventType, SystemClock.elapsedRealtime());
             event.mPackage = packageName;
-
-            // This will later be converted to system time.
-            event.mTimeStamp = SystemClock.elapsedRealtime();
-
-            event.mEventType = eventType;
             mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
         }
 
@@ -1292,13 +1300,8 @@
                 return;
             }
 
-            UsageEvents.Event event = new UsageEvents.Event();
+            Event event = new Event(CONFIGURATION_CHANGE, SystemClock.elapsedRealtime());
             event.mPackage = "android";
-
-            // This will later be converted to system time.
-            event.mTimeStamp = SystemClock.elapsedRealtime();
-
-            event.mEventType = UsageEvents.Event.CONFIGURATION_CHANGE;
             event.mConfiguration = new Configuration(config);
             mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
         }
@@ -1311,14 +1314,9 @@
                 return;
             }
 
-            UsageEvents.Event event = new UsageEvents.Event();
+            Event event = new Event(NOTIFICATION_INTERRUPTION, SystemClock.elapsedRealtime());
             event.mPackage = packageName.intern();
             event.mNotificationChannelId = channelId.intern();
-
-            // This will later be converted to system time.
-            event.mTimeStamp = SystemClock.elapsedRealtime();
-
-            event.mEventType = Event.NOTIFICATION_INTERRUPTION;
             mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
         }
 
@@ -1329,14 +1327,9 @@
                 return;
             }
 
-            UsageEvents.Event event = new UsageEvents.Event();
+            Event event = new Event(SHORTCUT_INVOCATION, SystemClock.elapsedRealtime());
             event.mPackage = packageName.intern();
             event.mShortcutId = shortcutId.intern();
-
-            // This will later be converted to system time.
-            event.mTimeStamp = SystemClock.elapsedRealtime();
-
-            event.mEventType = Event.SHORTCUT_INVOCATION;
             mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
         }
 
@@ -1372,7 +1365,7 @@
             // This method *WILL* do IO work, but we must block until it is finished or else
             // we might not shutdown cleanly. This is ok to do with the 'am' lock held, because
             // we are shutting down.
-            shutdown();
+            UsageStatsService.this.shutdown();
         }
 
         @Override
diff --git a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
index 01e566c..ec475bf 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
@@ -61,11 +61,13 @@
     private static final String FLAGS_ATTR = "flags";
     private static final String CLASS_ATTR = "class";
     private static final String TOTAL_TIME_ACTIVE_ATTR = "timeActive";
+    private static final String TOTAL_TIME_VISIBLE_ATTR = "timeVisible";
     private static final String TOTAL_TIME_SERVICE_USED_ATTR = "timeServiceUsed";
     private static final String COUNT_ATTR = "count";
     private static final String ACTIVE_ATTR = "active";
     private static final String LAST_EVENT_ATTR = "lastEvent";
     private static final String TYPE_ATTR = "type";
+    private static final String INSTANCE_ID_ATTR = "instanceId";
     private static final String SHORTCUT_ID_ATTR = "shortcutId";
     private static final String STANDBY_BUCKET_ATTR = "standbyBucket";
     private static final String APP_LAUNCH_COUNT_ATTR = "appLaunchCount";
@@ -75,6 +77,7 @@
 
     // Time attributes stored as an offset of the beginTime.
     private static final String LAST_TIME_ACTIVE_ATTR = "lastTimeActive";
+    private static final String LAST_TIME_VISIBLE_ATTR = "lastTimeVisible";
     private static final String LAST_TIME_SERVICE_USED_ATTR = "lastTimeServiceUsed";
     private static final String END_TIME_ATTR = "endTime";
     private static final String TIME_ATTR = "time";
@@ -92,6 +95,13 @@
                 parser, LAST_TIME_ACTIVE_ATTR);
 
         try {
+            stats.mLastTimeVisible = statsOut.beginTime + XmlUtils.readLongAttribute(
+                    parser, LAST_TIME_VISIBLE_ATTR);
+        } catch (IOException e) {
+            Log.e(TAG, "Failed to parse mLastTimeVisible", e);
+        }
+
+        try {
             stats.mLastTimeForegroundServiceUsed = statsOut.beginTime + XmlUtils.readLongAttribute(
                     parser, LAST_TIME_SERVICE_USED_ATTR);
         } catch (IOException e) {
@@ -101,8 +111,14 @@
         stats.mTotalTimeInForeground = XmlUtils.readLongAttribute(parser, TOTAL_TIME_ACTIVE_ATTR);
 
         try {
+            stats.mTotalTimeVisible = XmlUtils.readLongAttribute(parser, TOTAL_TIME_VISIBLE_ATTR);
+        } catch (IOException e) {
+            Log.e(TAG, "Failed to parse mTotalTimeVisible", e);
+        }
+
+        try {
             stats.mTotalTimeForegroundServiceUsed = XmlUtils.readLongAttribute(parser,
-                TOTAL_TIME_SERVICE_USED_ATTR);
+                    TOTAL_TIME_SERVICE_USED_ATTR);
         } catch (IOException e) {
             Log.e(TAG, "Failed to parse mTotalTimeForegroundServiceUsed", e);
         }
@@ -199,6 +215,13 @@
         event.mTimeStamp = statsOut.beginTime + XmlUtils.readLongAttribute(parser, TIME_ATTR);
 
         event.mEventType = XmlUtils.readIntAttribute(parser, TYPE_ATTR);
+
+        try {
+            event.mInstanceId = XmlUtils.readIntAttribute(parser, INSTANCE_ID_ATTR);
+        } catch (IOException e) {
+            Log.e(TAG, "Failed to parse mInstanceId", e);
+        }
+
         switch (event.mEventType) {
             case UsageEvents.Event.CONFIGURATION_CHANGE:
                 event.mConfiguration = new Configuration();
@@ -227,10 +250,13 @@
         // Write the time offset.
         XmlUtils.writeLongAttribute(xml, LAST_TIME_ACTIVE_ATTR,
                 usageStats.mLastTimeUsed - stats.beginTime);
+        XmlUtils.writeLongAttribute(xml, LAST_TIME_VISIBLE_ATTR,
+                usageStats.mLastTimeVisible - stats.beginTime);
         XmlUtils.writeLongAttribute(xml, LAST_TIME_SERVICE_USED_ATTR,
                 usageStats.mLastTimeForegroundServiceUsed - stats.beginTime);
         XmlUtils.writeStringAttribute(xml, PACKAGE_ATTR, usageStats.mPackageName);
         XmlUtils.writeLongAttribute(xml, TOTAL_TIME_ACTIVE_ATTR, usageStats.mTotalTimeInForeground);
+        XmlUtils.writeLongAttribute(xml, TOTAL_TIME_VISIBLE_ATTR, usageStats.mTotalTimeVisible);
         XmlUtils.writeLongAttribute(xml, TOTAL_TIME_SERVICE_USED_ATTR,
                 usageStats.mTotalTimeForegroundServiceUsed);
         XmlUtils.writeIntAttribute(xml, LAST_EVENT_ATTR, usageStats.mLastEvent);
@@ -317,6 +343,7 @@
         }
         XmlUtils.writeIntAttribute(xml, FLAGS_ATTR, event.mFlags);
         XmlUtils.writeIntAttribute(xml, TYPE_ATTR, event.mEventType);
+        XmlUtils.writeIntAttribute(xml, INSTANCE_ID_ATTR, event.mInstanceId);
 
         switch (event.mEventType) {
             case UsageEvents.Event.CONFIGURATION_CHANGE:
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 94d7dbb..5128ae1 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -16,10 +16,18 @@
 
 package com.android.server.usage;
 
+import static android.app.usage.UsageStatsManager.INTERVAL_BEST;
+import static android.app.usage.UsageStatsManager.INTERVAL_COUNT;
+import static android.app.usage.UsageStatsManager.INTERVAL_DAILY;
+import static android.app.usage.UsageStatsManager.INTERVAL_MONTHLY;
+import static android.app.usage.UsageStatsManager.INTERVAL_WEEKLY;
+import static android.app.usage.UsageStatsManager.INTERVAL_YEARLY;
+
 import android.app.usage.ConfigurationStats;
 import android.app.usage.EventList;
 import android.app.usage.EventStats;
 import android.app.usage.UsageEvents;
+import android.app.usage.UsageEvents.Event;
 import android.app.usage.UsageStats;
 import android.app.usage.UsageStatsManager;
 import android.content.Context;
@@ -29,6 +37,7 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Slog;
+import android.util.SparseIntArray;
 
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.usage.UsageStatsDatabase.StatCombiner;
@@ -65,7 +74,7 @@
     private final int mUserId;
 
     // STOPSHIP: Temporary member variable for debugging b/110930764.
-    private UsageEvents.Event mLastEvent;
+    private Event mLastEvent;
 
     private static final long[] INTERVAL_LENGTH = new long[] {
             UnixCalendar.DAY_IN_MILLIS, UnixCalendar.WEEK_IN_MILLIS,
@@ -87,7 +96,7 @@
         mContext = context;
         mDailyExpiryDate = new UnixCalendar(0);
         mDatabase = new UsageStatsDatabase(usageStatsDir);
-        mCurrentStats = new IntervalStats[UsageStatsManager.INTERVAL_COUNT];
+        mCurrentStats = new IntervalStats[INTERVAL_COUNT];
         mListener = listener;
         mLogPrefix = "User[" + Integer.toString(userId) + "] ";
         mUserId = userId;
@@ -125,28 +134,6 @@
             updateRolloverDeadline();
         }
 
-        // Now close off any events that were open at the time this was saved.
-        for (IntervalStats stat : mCurrentStats) {
-            final int pkgCount = stat.packageStats.size();
-            for (int i = 0; i < pkgCount; i++) {
-                final UsageStats pkgStats = stat.packageStats.valueAt(i);
-                if (!pkgStats.mLastForegroundActivityEventMap.isEmpty()
-                        || !pkgStats.mLastForegroundServiceEventMap.isEmpty()) {
-                    if (!pkgStats.mLastForegroundActivityEventMap.isEmpty()) {
-                        stat.update(pkgStats.mPackageName, null, stat.lastTimeSaved,
-                                UsageEvents.Event.END_OF_DAY);
-                    }
-                    if (!pkgStats.mLastForegroundServiceEventMap.isEmpty()) {
-                        stat.update(pkgStats.mPackageName, null , stat.lastTimeSaved,
-                                UsageEvents.Event.ROLLOVER_FOREGROUND_SERVICE);
-                    }
-                    notifyStatsChanged();
-                }
-            }
-
-            stat.updateConfigurationStats(null, stat.lastTimeSaved);
-        }
-
         if (mDatabase.isNewUpdate()) {
             notifyNewUpdate();
         }
@@ -158,40 +145,46 @@
         loadActiveStats(newTime);
     }
 
-    void reportEvent(UsageEvents.Event event) {
+    void reportEvent(Event event) {
         if (DEBUG) {
             Slog.d(TAG, mLogPrefix + "Got usage event for " + event.mPackage
                     + "[" + event.mTimeStamp + "]: "
                     + eventToString(event.mEventType));
         }
 
-        mLastEvent = new UsageEvents.Event(event);
+        mLastEvent = new Event(event);
 
         if (event.mTimeStamp >= mDailyExpiryDate.getTimeInMillis()) {
             // Need to rollover
             rolloverStats(event.mTimeStamp);
         }
 
-        final IntervalStats currentDailyStats = mCurrentStats[UsageStatsManager.INTERVAL_DAILY];
+        final IntervalStats currentDailyStats = mCurrentStats[INTERVAL_DAILY];
 
         final Configuration newFullConfig = event.mConfiguration;
-        if (event.mEventType == UsageEvents.Event.CONFIGURATION_CHANGE &&
-                currentDailyStats.activeConfiguration != null) {
+        if (event.mEventType == Event.CONFIGURATION_CHANGE
+                && currentDailyStats.activeConfiguration != null) {
             // Make the event configuration a delta.
             event.mConfiguration = Configuration.generateDelta(
                     currentDailyStats.activeConfiguration, newFullConfig);
         }
 
-        if (event.mEventType != UsageEvents.Event.SYSTEM_INTERACTION) {
+        if (event.mEventType != Event.SYSTEM_INTERACTION
+                // ACTIVITY_DESTROYED is a private event. If there is preceding ACTIVITY_STOPPED
+                // ACTIVITY_DESTROYED will be dropped. Otherwise it will be converted to
+                // ACTIVITY_STOPPED.
+                && event.mEventType != Event.ACTIVITY_DESTROYED
+                // FLUSH_TO_DISK is a private event.
+                && event.mEventType != Event.FLUSH_TO_DISK) {
             currentDailyStats.addEvent(event);
         }
 
         boolean incrementAppLaunch = false;
-        if (event.mEventType == UsageEvents.Event.MOVE_TO_FOREGROUND) {
+        if (event.mEventType == Event.ACTIVITY_RESUMED) {
             if (event.mPackage != null && !event.mPackage.equals(mLastBackgroundedPackage)) {
                 incrementAppLaunch = true;
             }
-        } else if (event.mEventType == UsageEvents.Event.MOVE_TO_BACKGROUND) {
+        } else if (event.mEventType == Event.ACTIVITY_PAUSED) {
             if (event.mPackage != null) {
                 mLastBackgroundedPackage = event.mPackage;
             }
@@ -199,10 +192,10 @@
 
         for (IntervalStats stats : mCurrentStats) {
             switch (event.mEventType) {
-                case UsageEvents.Event.CONFIGURATION_CHANGE: {
+                case Event.CONFIGURATION_CHANGE: {
                     stats.updateConfigurationStats(newFullConfig, event.mTimeStamp);
                 } break;
-                case UsageEvents.Event.CHOOSER_ACTION: {
+                case Event.CHOOSER_ACTION: {
                     stats.updateChooserCounts(event.mPackage, event.mContentType, event.mAction);
                     String[] annotations = event.mContentAnnotations;
                     if (annotations != null) {
@@ -211,21 +204,21 @@
                         }
                     }
                 } break;
-                case UsageEvents.Event.SCREEN_INTERACTIVE: {
+                case Event.SCREEN_INTERACTIVE: {
                     stats.updateScreenInteractive(event.mTimeStamp);
                 } break;
-                case UsageEvents.Event.SCREEN_NON_INTERACTIVE: {
+                case Event.SCREEN_NON_INTERACTIVE: {
                     stats.updateScreenNonInteractive(event.mTimeStamp);
                 } break;
-                case UsageEvents.Event.KEYGUARD_SHOWN: {
+                case Event.KEYGUARD_SHOWN: {
                     stats.updateKeyguardShown(event.mTimeStamp);
                 } break;
-                case UsageEvents.Event.KEYGUARD_HIDDEN: {
+                case Event.KEYGUARD_HIDDEN: {
                     stats.updateKeyguardHidden(event.mTimeStamp);
                 } break;
                 default: {
                     stats.update(event.mPackage, event.getClassName(),
-                            event.mTimeStamp, event.mEventType);
+                            event.mTimeStamp, event.mEventType, event.mInstanceId);
                     if (incrementAppLaunch) {
                         stats.incrementAppLaunchCount(event.mPackage);
                     }
@@ -286,12 +279,12 @@
      */
     private <T> List<T> queryStats(int intervalType, final long beginTime, final long endTime,
             StatCombiner<T> combiner) {
-        if (intervalType == UsageStatsManager.INTERVAL_BEST) {
+        if (intervalType == INTERVAL_BEST) {
             intervalType = mDatabase.findBestFitBucket(beginTime, endTime);
             if (intervalType < 0) {
                 // Nothing saved to disk yet, so every stat is just as equal (no rollover has
                 // occurred.
-                intervalType = UsageStatsManager.INTERVAL_DAILY;
+                intervalType = INTERVAL_DAILY;
             }
         }
 
@@ -316,10 +309,10 @@
             }
 
             // STOPSHIP: Temporary logging for b/110930764.
-            if (intervalType == UsageStatsManager.INTERVAL_DAILY
+            if (intervalType == INTERVAL_DAILY
                     && mLastEvent != null && mLastEvent.mTimeStamp >= beginTime) {
                 final IntervalStats diskStats = mDatabase.getLatestUsageStats(
-                        UsageStatsManager.INTERVAL_DAILY);
+                        INTERVAL_DAILY);
                 StringBuilder sb = new StringBuilder(256);
                 sb.append("Last 24 hours of UsageStats missing! timeRange : ");
                 sb.append(beginTime);
@@ -395,11 +388,11 @@
     UsageEvents queryEvents(final long beginTime, final long endTime,
             boolean obfuscateInstantApps) {
         final ArraySet<String> names = new ArraySet<>();
-        List<UsageEvents.Event> results = queryStats(UsageStatsManager.INTERVAL_DAILY,
-                beginTime, endTime, new StatCombiner<UsageEvents.Event>() {
+        List<Event> results = queryStats(INTERVAL_DAILY,
+                beginTime, endTime, new StatCombiner<Event>() {
                     @Override
                     public void combine(IntervalStats stats, boolean mutable,
-                            List<UsageEvents.Event> accumulatedResult) {
+                            List<Event> accumulatedResult) {
                         if (stats.events == null) {
                             return;
                         }
@@ -411,11 +404,13 @@
                                 return;
                             }
 
-                            UsageEvents.Event event = stats.events.get(i);
+                            Event event = stats.events.get(i);
                             if (obfuscateInstantApps) {
                                 event = event.getObfuscatedIfInstantApp();
                             }
-                            names.add(event.mPackage);
+                            if (event.mPackage != null) {
+                                names.add(event.mPackage);
+                            }
                             if (event.mClass != null) {
                                 names.add(event.mClass);
                             }
@@ -437,7 +432,7 @@
             final String packageName) {
         final ArraySet<String> names = new ArraySet<>();
         names.add(packageName);
-        final List<UsageEvents.Event> results = queryStats(UsageStatsManager.INTERVAL_DAILY,
+        final List<Event> results = queryStats(INTERVAL_DAILY,
                 beginTime, endTime, (stats, mutable, accumulatedResult) -> {
                     if (stats.events == null) {
                         return;
@@ -450,7 +445,7 @@
                             return;
                         }
 
-                        final UsageEvents.Event event = stats.events.get(i);
+                        final Event event = stats.events.get(i);
                         if (!packageName.equals(event.mPackage)) {
                             continue;
                         }
@@ -492,33 +487,33 @@
         // Make a note of which components need a new CONTINUE_PREVIOUS_DAY or
         // CONTINUING_FOREGROUND_SERVICE entry.
         final Configuration previousConfig =
-                mCurrentStats[UsageStatsManager.INTERVAL_DAILY].activeConfiguration;
-        ArraySet<String> continuePreviousDay = new ArraySet<>();
-        ArrayMap<String, ArrayMap<String, Integer>> continuePreviousDayForegroundActivity =
+                mCurrentStats[INTERVAL_DAILY].activeConfiguration;
+        ArraySet<String> continuePkgs = new ArraySet<>();
+        ArrayMap<String, SparseIntArray> continueActivity =
                 new ArrayMap<>();
-        ArrayMap<String, ArrayMap<String, Integer>> continuePreviousDayForegroundService =
+        ArrayMap<String, ArrayMap<String, Integer>> continueForegroundService =
                 new ArrayMap<>();
         for (IntervalStats stat : mCurrentStats) {
             final int pkgCount = stat.packageStats.size();
             for (int i = 0; i < pkgCount; i++) {
                 final UsageStats pkgStats = stat.packageStats.valueAt(i);
-                if (!pkgStats.mLastForegroundActivityEventMap.isEmpty()
-                        || !pkgStats.mLastForegroundServiceEventMap.isEmpty()) {
-                    if (!pkgStats.mLastForegroundActivityEventMap.isEmpty()) {
-                        continuePreviousDayForegroundActivity.put(pkgStats.mPackageName,
-                                pkgStats.mLastForegroundActivityEventMap);
+                if (pkgStats.mActivities.size() > 0
+                        || !pkgStats.mForegroundServices.isEmpty()) {
+                    if (pkgStats.mActivities.size() > 0) {
+                        continueActivity.put(pkgStats.mPackageName,
+                                pkgStats.mActivities);
                         stat.update(pkgStats.mPackageName, null,
                                 mDailyExpiryDate.getTimeInMillis() - 1,
-                                UsageEvents.Event.END_OF_DAY);
+                                Event.END_OF_DAY, 0);
                     }
-                    if (!pkgStats.mLastForegroundServiceEventMap.isEmpty()) {
-                        continuePreviousDayForegroundService.put(pkgStats.mPackageName,
-                                pkgStats.mLastForegroundServiceEventMap);
+                    if (!pkgStats.mForegroundServices.isEmpty()) {
+                        continueForegroundService.put(pkgStats.mPackageName,
+                                pkgStats.mForegroundServices);
                         stat.update(pkgStats.mPackageName, null,
                                 mDailyExpiryDate.getTimeInMillis() - 1,
-                                UsageEvents.Event.ROLLOVER_FOREGROUND_SERVICE);
+                                Event.ROLLOVER_FOREGROUND_SERVICE, 0);
                     }
-                    continuePreviousDay.add(pkgStats.mPackageName);
+                    continuePkgs.add(pkgStats.mPackageName);
                     notifyStatsChanged();
                 }
             }
@@ -532,27 +527,27 @@
         mDatabase.prune(currentTimeMillis);
         loadActiveStats(currentTimeMillis);
 
-        final int continueCount = continuePreviousDay.size();
+        final int continueCount = continuePkgs.size();
         for (int i = 0; i < continueCount; i++) {
-            String pkgName = continuePreviousDay.valueAt(i);
-            final long beginTime = mCurrentStats[UsageStatsManager.INTERVAL_DAILY].beginTime;
+            String pkgName = continuePkgs.valueAt(i);
+            final long beginTime = mCurrentStats[INTERVAL_DAILY].beginTime;
             for (IntervalStats stat : mCurrentStats) {
-                if (continuePreviousDayForegroundActivity.containsKey(pkgName)) {
-                    final ArrayMap<String, Integer> foregroundActivityEventMap =
-                            continuePreviousDayForegroundActivity.get(pkgName);
-                    final int size = foregroundActivityEventMap.size();
+                if (continueActivity.containsKey(pkgName)) {
+                    final SparseIntArray eventMap =
+                            continueActivity.get(pkgName);
+                    final int size = eventMap.size();
                     for (int j = 0; j < size; j++) {
-                        stat.update(pkgName, foregroundActivityEventMap.keyAt(j), beginTime,
-                                UsageEvents.Event.CONTINUE_PREVIOUS_DAY);
+                        stat.update(pkgName, null, beginTime,
+                                eventMap.valueAt(j), eventMap.keyAt(j));
                     }
                 }
-                if (continuePreviousDayForegroundService.containsKey(pkgName)) {
-                    final ArrayMap<String, Integer> foregroundServiceEventMap =
-                            continuePreviousDayForegroundService.get(pkgName);
-                    final int size = foregroundServiceEventMap.size();
+                if (continueForegroundService.containsKey(pkgName)) {
+                    final ArrayMap<String, Integer> eventMap =
+                            continueForegroundService.get(pkgName);
+                    final int size = eventMap.size();
                     for (int j = 0; j < size; j++) {
-                        stat.update(pkgName, foregroundServiceEventMap.keyAt(j), beginTime,
-                                UsageEvents.Event.CONTINUING_FOREGROUND_SERVICE);
+                        stat.update(pkgName, eventMap.keyAt(j), beginTime,
+                                eventMap.valueAt(j), 0);
                     }
                 }
                 stat.updateConfigurationStats(previousConfig, beginTime);
@@ -611,7 +606,7 @@
 
     private void updateRolloverDeadline() {
         mDailyExpiryDate.setTimeInMillis(
-                mCurrentStats[UsageStatsManager.INTERVAL_DAILY].beginTime);
+                mCurrentStats[INTERVAL_DAILY].beginTime);
         mDailyExpiryDate.addDays(1);
         Slog.i(TAG, mLogPrefix + "Rollover scheduled @ " +
                 sDateFormat.format(mDailyExpiryDate.getTimeInMillis()) + "(" +
@@ -660,7 +655,7 @@
     }
 
 
-    void printEvent(IndentingPrintWriter pw, UsageEvents.Event event, boolean prettyDates) {
+    void printEvent(IndentingPrintWriter pw, Event event, boolean prettyDates) {
         pw.printPair("time", formatDateTime(event.mTimeStamp, prettyDates));
         pw.printPair("type", eventToString(event.mEventType));
         pw.printPair("package", event.mPackage);
@@ -673,10 +668,15 @@
         if (event.mShortcutId != null) {
             pw.printPair("shortcutId", event.mShortcutId);
         }
-        if (event.mEventType == UsageEvents.Event.STANDBY_BUCKET_CHANGED) {
+        if (event.mEventType == Event.STANDBY_BUCKET_CHANGED) {
             pw.printPair("standbyBucket", event.getStandbyBucket());
             pw.printPair("reason", UsageStatsManager.reasonToString(event.getStandbyReason()));
+        } else if (event.mEventType == Event.ACTIVITY_RESUMED
+                || event.mEventType == Event.ACTIVITY_PAUSED
+                || event.mEventType == Event.ACTIVITY_STOPPED) {
+            pw.printPair("instanceId", event.getInstanceId());
         }
+
         if (event.mNotificationChannelId != null) {
             pw.printPair("channelId", event.mNotificationChannelId);
         }
@@ -691,11 +691,11 @@
 
         final long beginTime = yesterday.getTimeInMillis();
 
-        List<UsageEvents.Event> events = queryStats(UsageStatsManager.INTERVAL_DAILY,
-                beginTime, endTime, new StatCombiner<UsageEvents.Event>() {
+        List<Event> events = queryStats(INTERVAL_DAILY,
+                beginTime, endTime, new StatCombiner<Event>() {
                     @Override
                     public void combine(IntervalStats stats, boolean mutable,
-                            List<UsageEvents.Event> accumulatedResult) {
+                            List<Event> accumulatedResult) {
                         if (stats.events == null) {
                             return;
                         }
@@ -707,7 +707,7 @@
                                 return;
                             }
 
-                            UsageEvents.Event event = stats.events.get(i);
+                            Event event = stats.events.get(i);
                             if (pkg != null && !pkg.equals(event.mPackage)) {
                                 continue;
                             }
@@ -727,7 +727,7 @@
         pw.println(")");
         if (events != null) {
             pw.increaseIndent();
-            for (UsageEvents.Event event : events) {
+            for (Event event : events) {
                 printEvent(pw, event, prettyDates);
             }
             pw.decreaseIndent();
@@ -772,9 +772,17 @@
                 continue;
             }
             pw.printPair("package", usageStats.mPackageName);
-            pw.printPair("totalTime",
+            pw.printPair("totalTimeUsed",
                     formatElapsedTime(usageStats.mTotalTimeInForeground, prettyDates));
-            pw.printPair("lastTime", formatDateTime(usageStats.mLastTimeUsed, prettyDates));
+            pw.printPair("lastTimeUsed", formatDateTime(usageStats.mLastTimeUsed, prettyDates));
+            pw.printPair("totalTimeVisible",
+                    formatElapsedTime(usageStats.mTotalTimeVisible, prettyDates));
+            pw.printPair("lastTimeVisible",
+                    formatDateTime(usageStats.mLastTimeVisible, prettyDates));
+            pw.printPair("totalTimeFS",
+                    formatElapsedTime(usageStats.mTotalTimeForegroundServiceUsed, prettyDates));
+            pw.printPair("lastTimeFS",
+                    formatDateTime(usageStats.mLastTimeForegroundServiceUsed, prettyDates));
             pw.printPair("appLaunchCount", usageStats.mAppLaunchCount);
             pw.println();
         }
@@ -845,7 +853,7 @@
             final EventList events = stats.events;
             final int eventCount = events != null ? events.size() : 0;
             for (int i = 0; i < eventCount; i++) {
-                final UsageEvents.Event event = events.get(i);
+                final Event event = events.get(i);
                 if (pkg != null && !pkg.equals(event.mPackage)) {
                     continue;
                 }
@@ -858,13 +866,13 @@
 
     private static String intervalToString(int interval) {
         switch (interval) {
-            case UsageStatsManager.INTERVAL_DAILY:
+            case INTERVAL_DAILY:
                 return "daily";
-            case UsageStatsManager.INTERVAL_WEEKLY:
+            case INTERVAL_WEEKLY:
                 return "weekly";
-            case UsageStatsManager.INTERVAL_MONTHLY:
+            case INTERVAL_MONTHLY:
                 return "monthly";
-            case UsageStatsManager.INTERVAL_YEARLY:
+            case INTERVAL_YEARLY:
                 return "yearly";
             default:
                 return "?";
@@ -873,47 +881,49 @@
 
     private static String eventToString(int eventType) {
         switch (eventType) {
-            case UsageEvents.Event.NONE:
+            case Event.NONE:
                 return "NONE";
-            case UsageEvents.Event.MOVE_TO_BACKGROUND:
-                return "MOVE_TO_BACKGROUND";
-            case UsageEvents.Event.MOVE_TO_FOREGROUND:
-                return "MOVE_TO_FOREGROUND";
-            case UsageEvents.Event.FOREGROUND_SERVICE_START:
+            case Event.ACTIVITY_PAUSED:
+                return "ACTIVITY_PAUSED";
+            case Event.ACTIVITY_RESUMED:
+                return "ACTIVITY_RESUMED";
+            case Event.FOREGROUND_SERVICE_START:
                 return "FOREGROUND_SERVICE_START";
-            case UsageEvents.Event.FOREGROUND_SERVICE_STOP:
+            case Event.FOREGROUND_SERVICE_STOP:
                 return "FOREGROUND_SERVICE_STOP";
-            case UsageEvents.Event.END_OF_DAY:
+            case Event.ACTIVITY_STOPPED:
+                return "ACTIVITY_STOPPED";
+            case Event.END_OF_DAY:
                 return "END_OF_DAY";
-            case UsageEvents.Event.ROLLOVER_FOREGROUND_SERVICE:
+            case Event.ROLLOVER_FOREGROUND_SERVICE:
                 return "ROLLOVER_FOREGROUND_SERVICE";
-            case UsageEvents.Event.CONTINUE_PREVIOUS_DAY:
+            case Event.CONTINUE_PREVIOUS_DAY:
                 return "CONTINUE_PREVIOUS_DAY";
-            case UsageEvents.Event.CONTINUING_FOREGROUND_SERVICE:
+            case Event.CONTINUING_FOREGROUND_SERVICE:
                 return "CONTINUING_FOREGROUND_SERVICE";
-            case UsageEvents.Event.CONFIGURATION_CHANGE:
+            case Event.CONFIGURATION_CHANGE:
                 return "CONFIGURATION_CHANGE";
-            case UsageEvents.Event.SYSTEM_INTERACTION:
+            case Event.SYSTEM_INTERACTION:
                 return "SYSTEM_INTERACTION";
-            case UsageEvents.Event.USER_INTERACTION:
+            case Event.USER_INTERACTION:
                 return "USER_INTERACTION";
-            case UsageEvents.Event.SHORTCUT_INVOCATION:
+            case Event.SHORTCUT_INVOCATION:
                 return "SHORTCUT_INVOCATION";
-            case UsageEvents.Event.CHOOSER_ACTION:
+            case Event.CHOOSER_ACTION:
                 return "CHOOSER_ACTION";
-            case UsageEvents.Event.NOTIFICATION_SEEN:
+            case Event.NOTIFICATION_SEEN:
                 return "NOTIFICATION_SEEN";
-            case UsageEvents.Event.STANDBY_BUCKET_CHANGED:
+            case Event.STANDBY_BUCKET_CHANGED:
                 return "STANDBY_BUCKET_CHANGED";
-            case UsageEvents.Event.NOTIFICATION_INTERRUPTION:
+            case Event.NOTIFICATION_INTERRUPTION:
                 return "NOTIFICATION_INTERRUPTION";
-            case UsageEvents.Event.SLICE_PINNED:
+            case Event.SLICE_PINNED:
                 return "SLICE_PINNED";
-            case UsageEvents.Event.SLICE_PINNED_PRIV:
+            case Event.SLICE_PINNED_PRIV:
                 return "SLICE_PINNED_PRIV";
-            case UsageEvents.Event.SCREEN_INTERACTIVE:
+            case Event.SCREEN_INTERACTIVE:
                 return "SCREEN_INTERACTIVE";
-            case UsageEvents.Event.SCREEN_NON_INTERACTIVE:
+            case Event.SCREEN_NON_INTERACTIVE:
                 return "SCREEN_NON_INTERACTIVE";
             case UsageEvents.Event.KEYGUARD_SHOWN:
                 return "KEYGUARD_SHOWN";
diff --git a/tests/UsageStatsPerfTests/src/com/android/frameworks/perftests/usage/tests/UsageStatsDatabasePerfTest.java b/tests/UsageStatsPerfTests/src/com/android/frameworks/perftests/usage/tests/UsageStatsDatabasePerfTest.java
index be74a6d..7a5e732 100644
--- a/tests/UsageStatsPerfTests/src/com/android/frameworks/perftests/usage/tests/UsageStatsDatabasePerfTest.java
+++ b/tests/UsageStatsPerfTests/src/com/android/frameworks/perftests/usage/tests/UsageStatsDatabasePerfTest.java
@@ -92,11 +92,11 @@
             event.mPackage = "fake.package.name" + pkg;
             event.mClass = event.mPackage + ".class1";
             event.mTimeStamp = 1;
-            event.mEventType = UsageEvents.Event.MOVE_TO_FOREGROUND;
+            event.mEventType = UsageEvents.Event.ACTIVITY_RESUMED;
             for (int evt = 0; evt < eventsPerPackage; evt++) {
                 intervalStats.events.insert(event);
                 intervalStats.update(event.mPackage, event.mClass, event.mTimeStamp,
-                        event.mEventType);
+                        event.mEventType, 1);
             }
         }
     }
diff --git a/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageLogActivity.java b/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageLogActivity.java
index 3480e96..53afa26 100644
--- a/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageLogActivity.java
+++ b/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageLogActivity.java
@@ -21,13 +21,14 @@
 import android.content.Context;
 import android.os.Bundle;
 import android.os.Handler;
-import androidx.collection.CircularArray;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.BaseAdapter;
 import android.widget.TextView;
 
+import androidx.collection.CircularArray;
+
 public class UsageLogActivity extends ListActivity implements Runnable {
     private static final long USAGE_STATS_PERIOD = 1000 * 60 * 60 * 24 * 14;
 
@@ -155,10 +156,10 @@
 
         private String eventToString(int eventType) {
             switch (eventType) {
-                case UsageEvents.Event.MOVE_TO_FOREGROUND:
+                case UsageEvents.Event.ACTIVITY_RESUMED:
                     return "Foreground";
 
-                case UsageEvents.Event.MOVE_TO_BACKGROUND:
+                case UsageEvents.Event.ACTIVITY_PAUSED:
                     return "Background";
 
                 case UsageEvents.Event.CONFIGURATION_CHANGE: