Query usage event for a longer time period and then trim the usage
events outside the expected period to make sure the app usage calculation near the boundaries are correct.

Test: make RunSettingsRoboTests + manual
Bug: 264858898
Change-Id: I9f6aa5a09a537f48a26a08b7dff8ae81e8a16e2a
diff --git a/src/com/android/settings/fuelgauge/batteryusage/DataProcessManager.java b/src/com/android/settings/fuelgauge/batteryusage/DataProcessManager.java
index 762ea24..4506922 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/DataProcessManager.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/DataProcessManager.java
@@ -376,7 +376,7 @@
         // Generates the indexed AppUsagePeriod list data for each corresponding time slot for
         // further use.
         mAppUsagePeriodMap = DataProcessor.generateAppUsagePeriodMap(
-                mHourlyBatteryLevelsPerDay, mAppUsageEventList, mStartTimestampOfLevelData);
+                mHourlyBatteryLevelsPerDay, mAppUsageEventList);
     }
 
     private void tryToGenerateFinalDataAndApplyCallback() {
diff --git a/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java b/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
index 874dc11..3b04f90 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
@@ -72,7 +72,6 @@
  * usage UI.
  */
 public final class DataProcessor {
-    private static final boolean DEBUG = false;
     private static final String TAG = "DataProcessor";
     private static final int POWER_COMPONENT_SYSTEM_SERVICES = 7;
     private static final int POWER_COMPONENT_WAKELOCK = 12;
@@ -99,6 +98,9 @@
     static long sFakeCurrentTimeMillis = 0;
 
     @VisibleForTesting
+    static boolean sDebug = false;
+
+    @VisibleForTesting
     static IUsageStatsManager sUsageStatsManager =
             IUsageStatsManager.Stub.asInterface(
                     ServiceManager.getService(Context.USAGE_STATS_SERVICE));
@@ -250,8 +252,7 @@
     public static Map<Integer, Map<Integer, Map<Long, Map<String, List<AppUsagePeriod>>>>>
             generateAppUsagePeriodMap(
             final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay,
-            final List<AppUsageEvent> appUsageEventList,
-            final long startTimestampOfLevelData) {
+            final List<AppUsageEvent> appUsageEventList) {
         if (appUsageEventList.isEmpty()) {
             Log.w(TAG, "appUsageEventList is empty");
             return null;
@@ -261,12 +262,8 @@
         Collections.sort(appUsageEventList, TIMESTAMP_COMPARATOR);
         final Map<Integer, Map<Integer, Map<Long, Map<String, List<AppUsagePeriod>>>>> resultMap =
                 new HashMap<>();
-        // Starts from the first index within expected time range. The events before the time range
-        // will be bypassed directly.
-        int currentAppUsageEventIndex =
-                getFirstUsageEventIndex(appUsageEventList, startTimestampOfLevelData);
-        final int appUsageEventSize = appUsageEventList.size();
 
+        final long dailySize = hourlyBatteryLevelsPerDay.size();
         for (int dailyIndex = 0; dailyIndex < hourlyBatteryLevelsPerDay.size(); dailyIndex++) {
             final Map<Integer, Map<Long, Map<String, List<AppUsagePeriod>>>> dailyMap =
                     new HashMap<>();
@@ -275,32 +272,21 @@
                 continue;
             }
             final List<Long> timestamps = hourlyBatteryLevelsPerDay.get(dailyIndex).getTimestamps();
+            final long hourlySize = timestamps.size() - 1;
             for (int hourlyIndex = 0; hourlyIndex < timestamps.size() - 1; hourlyIndex++) {
                 // The start and end timestamps of this slot should be the adjacent timestamps.
                 final long startTimestamp = timestamps.get(hourlyIndex);
-                final long endTimestamp = timestamps.get(hourlyIndex + 1);
+                // The final slot is to show the data from last even hour until now but the
+                // timestamp in hourlyBatteryLevelsPerDay is not the real value. So use current
+                // timestamp instead of reading the timestamp from hourlyBatteryLevelsPerDay here.
+                final long endTimestamp =
+                        dailyIndex == dailySize - 1 && hourlyIndex == hourlySize - 1 && !sDebug
+                                ? System.currentTimeMillis() : timestamps.get(hourlyIndex + 1);
 
                 // Gets the app usage event list for this hourly slot first.
-                final List<AppUsageEvent> hourlyAppUsageEventList = new ArrayList<>();
-                while (currentAppUsageEventIndex < appUsageEventSize) {
-                    // If current event is null, go for next directly.
-                    if (appUsageEventList.get(currentAppUsageEventIndex) == null) {
-                        currentAppUsageEventIndex++;
-                        continue;
-                    }
-                    final long timestamp =
-                            appUsageEventList.get(currentAppUsageEventIndex).getTimestamp();
-                    // If the timestamp is already later than the end time, stop the loop.
-                    if (timestamp >= endTimestamp) {
-                        break;
-                    }
-                    // If timestamp is within the time range, add it into the list.
-                    if (timestamp >= startTimestamp) {
-                        hourlyAppUsageEventList.add(
-                                appUsageEventList.get(currentAppUsageEventIndex));
-                    }
-                    currentAppUsageEventIndex++;
-                }
+                final List<AppUsageEvent> hourlyAppUsageEventList =
+                        getAppUsageEventListWithinTimeRangeWithBuffer(
+                                appUsageEventList, startTimestamp, endTimestamp);
 
                 // The value could be null when there is no data in the hourly slot.
                 dailyMap.put(
@@ -785,13 +771,11 @@
             final List<AppUsageEvent> usageEvents, final long startTime, final long endTime) {
         final List<AppUsagePeriod> usagePeriodList = new ArrayList<>();
         AppUsagePeriod.Builder pendingUsagePeriod = AppUsagePeriod.newBuilder();
-        boolean hasMetStartEvent = false;
 
         for (final AppUsageEvent event : usageEvents) {
             final long eventTime = event.getTimestamp();
 
             if (event.getType() == AppUsageEventType.ACTIVITY_RESUMED) {
-                hasMetStartEvent = true;
                 // If there is an existing start time, simply ignore this start event.
                 // If there was no start time, then start a new period.
                 if (!pendingUsagePeriod.hasStartTime()) {
@@ -800,37 +784,31 @@
             } else if (event.getType() == AppUsageEventType.ACTIVITY_STOPPED) {
                 pendingUsagePeriod.setEndTime(eventTime);
                 if (!pendingUsagePeriod.hasStartTime()) {
-                    // If we haven't met start event in this list, the start event might happen
-                    // in the previous time slot. use the startTime for this period.
-                    // Otherwise, add one for the default duration.
-                    if (!hasMetStartEvent) {
-                        hasMetStartEvent = true;
-                        pendingUsagePeriod.setStartTime(startTime);
-                    } else {
-                        pendingUsagePeriod.setStartTime(
-                                getStartTimeForIncompleteUsagePeriod(pendingUsagePeriod));
-                    }
+                    pendingUsagePeriod.setStartTime(
+                            getStartTimeForIncompleteUsagePeriod(pendingUsagePeriod));
                 }
                 // If we already have start time, add it directly.
-                addToPeriodList(usagePeriodList, pendingUsagePeriod.build());
+                validateAndAddToPeriodList(
+                        usagePeriodList, pendingUsagePeriod.build(), startTime, endTime);
                 pendingUsagePeriod.clear();
             } else if (event.getType() == AppUsageEventType.DEVICE_SHUTDOWN) {
-                hasMetStartEvent = true;
                 // The end event might be lost when device is shutdown. Use the estimated end
                 // time for the period.
                 if (pendingUsagePeriod.hasStartTime()) {
                     pendingUsagePeriod.setEndTime(
                             getEndTimeForIncompleteUsagePeriod(pendingUsagePeriod, eventTime));
-                    addToPeriodList(usagePeriodList, pendingUsagePeriod.build());
+                    validateAndAddToPeriodList(
+                            usagePeriodList, pendingUsagePeriod.build(), startTime, endTime);
                     pendingUsagePeriod.clear();
                 }
             }
         }
         // If there exists unclosed period, the stop event might happen in the next time
         // slot. Use the endTime for the period.
-        if (pendingUsagePeriod.hasStartTime()) {
+        if (pendingUsagePeriod.hasStartTime() && pendingUsagePeriod.getStartTime() < endTime) {
             pendingUsagePeriod.setEndTime(endTime);
-            addToPeriodList(usagePeriodList, pendingUsagePeriod.build());
+            validateAndAddToPeriodList(
+                    usagePeriodList, pendingUsagePeriod.build(), startTime, endTime);
             pendingUsagePeriod.clear();
         }
         return usagePeriodList;
@@ -881,12 +859,56 @@
         }
     }
 
-    private static void addToPeriodList(
-            final List<AppUsagePeriod> appUsagePeriodList, final AppUsagePeriod appUsagePeriod) {
-        // Only when the period is valid, add it into the list.
-        if (appUsagePeriod.getStartTime() < appUsagePeriod.getEndTime()) {
-            appUsagePeriodList.add(appUsagePeriod);
+    /**
+     * Generates the list of {@link AppUsageEvent} within the specific time range.
+     * The buffer is added to make sure the app usage calculation near the boundaries is correct.
+     *
+     * Note: The appUsageEventList should have been sorted when calling this function.
+     */
+    private static List<AppUsageEvent> getAppUsageEventListWithinTimeRangeWithBuffer(
+            final List<AppUsageEvent> appUsageEventList, final long startTime, final long endTime) {
+        final long start = startTime - DatabaseUtils.USAGE_QUERY_BUFFER_HOURS;
+        final long end = endTime + DatabaseUtils.USAGE_QUERY_BUFFER_HOURS;
+        final List<AppUsageEvent> resultList = new ArrayList<>();
+        for (final AppUsageEvent event : appUsageEventList) {
+            final long eventTime = event.getTimestamp();
+            // Because the appUsageEventList has been sorted, if any event is already after the end
+            // time, all the following events should be able to drop directly.
+            if (eventTime > end) {
+                break;
+            }
+            // If the event timestamp is in [start, end], add it into the result list.
+            if (eventTime >= start) {
+                resultList.add(event);
+            }
         }
+        return resultList;
+    }
+
+    private static void validateAndAddToPeriodList(
+            final List<AppUsagePeriod> appUsagePeriodList,
+            final AppUsagePeriod appUsagePeriod,
+            final long startTime,
+            final long endTime) {
+        final long periodStartTime =
+                trimPeriodTime(appUsagePeriod.getStartTime(), startTime, endTime);
+        final long periodEndTime = trimPeriodTime(appUsagePeriod.getEndTime(), startTime, endTime);
+        // Only when the period is valid, add it into the list.
+        if (periodStartTime < periodEndTime) {
+            final AppUsagePeriod period =
+                    AppUsagePeriod.newBuilder()
+                            .setStartTime(periodStartTime)
+                            .setEndTime(periodEndTime)
+                            .build();
+            appUsagePeriodList.add(period);
+        }
+    }
+
+    private static long trimPeriodTime(
+            final long originalTime, final long startTime, final long endTime) {
+        long finalTime = Math.max(originalTime, startTime);
+        finalTime = Math.min(finalTime, endTime);
+        return finalTime;
     }
 
     private static void addToUsagePeriodMap(
@@ -918,19 +940,6 @@
                 eventTime);
     }
 
-    private static int getFirstUsageEventIndex(
-            final List<AppUsageEvent> appUsageEventList,
-            final long startTimestampOfLevelData) {
-        int currentIndex = 0;
-        while (currentIndex < appUsageEventList.size()
-                && (appUsageEventList.get(currentIndex) == null
-                || appUsageEventList.get(currentIndex).getTimestamp()
-                < startTimestampOfLevelData)) {
-            currentIndex++;
-        }
-        return currentIndex;
-    }
-
     private static void insertHourlyDeviceScreenOnTime(
             final Map<Integer, Map<Integer, Map<Long, Map<String, List<AppUsagePeriod>>>>>
                     appUsagePeriodMap,
@@ -1520,7 +1529,7 @@
                     foregroundUsageTimeInMs + backgroundUsageTimeInMs;
             if (totalUsageTimeInMs > TOTAL_HOURLY_TIME_THRESHOLD) {
                 final float ratio = TOTAL_HOURLY_TIME_THRESHOLD / totalUsageTimeInMs;
-                if (DEBUG) {
+                if (sDebug) {
                     Log.w(TAG, String.format("abnormal usage time %d|%d for:\n%s",
                             Duration.ofMillis(foregroundUsageTimeInMs).getSeconds(),
                             Duration.ofMillis(backgroundUsageTimeInMs).getSeconds(),
@@ -1876,7 +1885,7 @@
 
     private static void log(Context context, final String content, final long timestamp,
             final BatteryHistEntry entry) {
-        if (DEBUG) {
+        if (sDebug) {
             Log.d(TAG, String.format(entry != null ? "%s %s:\n%s" : "%s %s:%s",
                     utcToLocalTime(context, timestamp), content, entry));
         }
diff --git a/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtils.java b/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtils.java
index 516645e..1227686 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtils.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtils.java
@@ -74,6 +74,11 @@
     public static final String QUERY_KEY_USERID = "userid";
 
     public static final long INVALID_USER_ID = Integer.MIN_VALUE;
+    /**
+     * The buffer hours to query app usage events that may have begun or ended out of the final
+     * desired time frame.
+     */
+    public static final long USAGE_QUERY_BUFFER_HOURS = Duration.ofHours(3).toMillis();
 
     /** A content URI to access battery usage states data. */
     public static final Uri BATTERY_CONTENT_URI =
@@ -138,7 +143,10 @@
             final long startTimestampOfLevelData) {
         final long startTime = System.currentTimeMillis();
         final long sixDaysAgoTimestamp = getTimestampSixDaysAgo(calendar);
-        final long queryTimestamp = Math.max(startTimestampOfLevelData, sixDaysAgoTimestamp);
+        // Query a longer time period and then trim to the original time period in order to make
+        // sure the app usage calculation near the boundaries is correct.
+        final long queryTimestamp =
+                Math.max(startTimestampOfLevelData, sixDaysAgoTimestamp) - USAGE_QUERY_BUFFER_HOURS;
         Log.d(TAG, "sixDayAgoTimestamp: " + sixDaysAgoTimestamp);
         final String queryUserIdString = userIds.stream()
                 .map(userId -> String.valueOf(userId))
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
index 9eaf1b6..576184d 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
@@ -178,22 +178,22 @@
 
     @Test
     public void generateAppUsagePeriodMap_returnExpectedResult() {
+        DataProcessor.sDebug = true;
         final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay =
                 new ArrayList<>();
         final String packageName = "com.android.settings";
         // Adds the day 1 data.
-        final List<Long> timestamps1 = List.of(10000L, 20000L, 30000L);
+        final List<Long> timestamps1 = List.of(14400000L, 18000000L, 21600000L);
         final List<Integer> levels1 = List.of(100, 100, 100);
         hourlyBatteryLevelsPerDay.add(
                 new BatteryLevelData.PeriodBatteryLevelData(timestamps1, levels1));
         // Adds the day 2 data.
         hourlyBatteryLevelsPerDay.add(null);
         // Adds the day 3 data.
-        final List<Long> timestamps2 = List.of(40000L, 50000L);
+        final List<Long> timestamps2 = List.of(45200000L, 48800000L);
         final List<Integer> levels2 = List.of(100, 100);
         hourlyBatteryLevelsPerDay.add(
                 new BatteryLevelData.PeriodBatteryLevelData(timestamps2, levels2));
-        final long startTimestampOfLevelData = 10000L;
         final List<AppUsageEvent> appUsageEventList = new ArrayList<>();
         // Adds some events before the start timestamp.
         appUsageEventList.add(buildAppUsageEvent(
@@ -204,39 +204,48 @@
                 /*instanceId=*/ 2, packageName));
         // Adds the valid app usage events.
         appUsageEventList.add(buildAppUsageEvent(
-                AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 10000L, /*userId=*/ 1,
+                AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 4200000L, /*userId=*/ 1,
                 /*instanceId=*/ 2, packageName));
         appUsageEventList.add(buildAppUsageEvent(
-                AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 15000L, /*userId=*/ 1,
+                AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 4500000L, /*userId=*/ 1,
                 /*instanceId=*/ 2, packageName));
         appUsageEventList.add(buildAppUsageEvent(
-                AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 12000L, /*userId=*/ 2,
+                AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 12600000L, /*userId=*/ 2,
                 /*instanceId=*/ 3, packageName));
         appUsageEventList.add(buildAppUsageEvent(
-                AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 18000L, /*userId=*/ 2,
+                AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 15600000L, /*userId=*/ 2,
                 /*instanceId=*/ 3, packageName));
         appUsageEventList.add(buildAppUsageEvent(
-                AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 35000L, /*userId=*/ 1,
+                AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 16200000L, /*userId=*/ 2,
+                /*instanceId=*/ 3, packageName));
+        appUsageEventList.add(buildAppUsageEvent(
+                AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 18000000L, /*userId=*/ 2,
+                /*instanceId=*/ 3, packageName));
+        appUsageEventList.add(buildAppUsageEvent(
+                AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 17200000L, /*userId=*/ 1,
                 /*instanceId=*/ 2, packageName));
         appUsageEventList.add(buildAppUsageEvent(
-                AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 45000L, /*userId=*/ 1,
+                AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 17800000L, /*userId=*/ 1,
                 /*instanceId=*/ 2, packageName));
         appUsageEventList.add(buildAppUsageEvent(
-                AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 42000L, /*userId=*/ 1,
+                AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 46000000L, /*userId=*/ 1,
+                /*instanceId=*/ 2, packageName));
+        appUsageEventList.add(buildAppUsageEvent(
+                AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 47800000L, /*userId=*/ 1,
+                /*instanceId=*/ 2, packageName));
+        appUsageEventList.add(buildAppUsageEvent(
+                AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 49000000L, /*userId=*/ 1,
+                /*instanceId=*/ 2, packageName));
+        appUsageEventList.add(buildAppUsageEvent(
+                AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 59600000L, /*userId=*/ 1,
                 /*instanceId=*/ 4, packageName));
         appUsageEventList.add(buildAppUsageEvent(
-                AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 52000L, /*userId=*/ 1,
-                /*instanceId=*/ 4, packageName));
-        appUsageEventList.add(buildAppUsageEvent(
-                AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 55000L, /*userId=*/ 1,
-                /*instanceId=*/ 4, packageName));
-        appUsageEventList.add(buildAppUsageEvent(
-                AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 58000L, /*userId=*/ 1,
+                AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 61200000L, /*userId=*/ 1,
                 /*instanceId=*/ 4, packageName));
 
         final Map<Integer, Map<Integer, Map<Long, Map<String, List<AppUsagePeriod>>>>> periodMap =
                 DataProcessor.generateAppUsagePeriodMap(
-                        hourlyBatteryLevelsPerDay, appUsageEventList, startTimestampOfLevelData);
+                        hourlyBatteryLevelsPerDay, appUsageEventList);
 
         assertThat(periodMap.size()).isEqualTo(3);
         // Day 1
@@ -246,11 +255,12 @@
         Map<String, List<AppUsagePeriod>> userMap = hourlyMap.get(1L);
         assertThat(userMap.size()).isEqualTo(1);
         assertThat(userMap.get(packageName).size()).isEqualTo(1);
-        assertAppUsagePeriod(userMap.get(packageName).get(0), 10000, 15000);
+        assertAppUsagePeriod(userMap.get(packageName).get(0), 17200000L, 17800000L);
         userMap = hourlyMap.get(2L);
         assertThat(userMap.size()).isEqualTo(1);
-        assertThat(userMap.get(packageName).size()).isEqualTo(1);
-        assertAppUsagePeriod(userMap.get(packageName).get(0), 12000, 18000);
+        assertThat(userMap.get(packageName).size()).isEqualTo(2);
+        assertAppUsagePeriod(userMap.get(packageName).get(0), 14400000L, 15600000L);
+        assertAppUsagePeriod(userMap.get(packageName).get(1), 16200000L, 18000000L);
         hourlyMap = periodMap.get(0).get(1);
         assertThat(hourlyMap).isNull();
         // Day 2
@@ -262,8 +272,8 @@
         userMap = hourlyMap.get(1L);
         assertThat(userMap.size()).isEqualTo(1);
         assertThat(userMap.get(packageName).size()).isEqualTo(2);
-        assertAppUsagePeriod(userMap.get(packageName).get(0), 40000, 45000);
-        assertAppUsagePeriod(userMap.get(packageName).get(1), 42000, 50000);
+        assertAppUsagePeriod(userMap.get(packageName).get(0), 45970000L, 46000000L);
+        assertAppUsagePeriod(userMap.get(packageName).get(1), 47800000L, 48800000L);
     }
 
     @Test
@@ -273,7 +283,7 @@
         hourlyBatteryLevelsPerDay.add(
                 new BatteryLevelData.PeriodBatteryLevelData(new ArrayList<>(), new ArrayList<>()));
         assertThat(DataProcessor.generateAppUsagePeriodMap(
-                hourlyBatteryLevelsPerDay, new ArrayList<>(), 0)).isNull();
+                hourlyBatteryLevelsPerDay, new ArrayList<>())).isNull();
     }
 
     @Test
@@ -1508,9 +1518,19 @@
     @Test
     public void buildAppUsagePeriodListPerInstance_returnExpectedResult() {
         final List<AppUsageEvent> appUsageEvents = new ArrayList<>();
+        // Fake data earlier than time range.
+        appUsageEvents.add(buildAppUsageEvent(
+                AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 1));
+        appUsageEvents.add(buildAppUsageEvent(
+                AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 2));
+        // Fake resume event earlier than time range.
+        appUsageEvents.add(buildAppUsageEvent(
+                AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 3));
+        appUsageEvents.add(buildAppUsageEvent(
+                AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 120000));
         // Fake normal data.
         appUsageEvents.add(buildAppUsageEvent(
-                AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 100000));
+                AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 150000));
         appUsageEvents.add(buildAppUsageEvent(
                 AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 200000));
         // Fake two adjacent resume events.
@@ -1540,29 +1560,16 @@
                 AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 1000000));
 
         final List<AppUsagePeriod> appUsagePeriodList =
-                DataProcessor.buildAppUsagePeriodListPerInstance(appUsageEvents, 0, 1100000);
+                DataProcessor.buildAppUsagePeriodListPerInstance(appUsageEvents, 100000, 1100000);
 
-        assertThat(appUsagePeriodList.size()).isEqualTo(6);
-        assertAppUsagePeriod(appUsagePeriodList.get(0), 100000, 200000);
-        assertAppUsagePeriod(appUsagePeriodList.get(1), 300000, 500000);
-        assertAppUsagePeriod(appUsagePeriodList.get(2), 570000, 600000);
-        assertAppUsagePeriod(appUsagePeriodList.get(3), 700000, 730000);
-        assertAppUsagePeriod(appUsagePeriodList.get(4), 900000, 910000);
-        assertAppUsagePeriod(appUsagePeriodList.get(5), 1000000, 1100000);
-    }
-
-    @Test
-    public void buildAppUsagePeriodListPerInstance_notMetStart_returnExpectedResult() {
-        final List<AppUsageEvent> appUsageEvents = new ArrayList<>();
-        // Start with stop event.
-        appUsageEvents.add(buildAppUsageEvent(
-                AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 100000));
-
-        final List<AppUsagePeriod> appUsagePeriodList =
-                DataProcessor.buildAppUsagePeriodListPerInstance(appUsageEvents, 0, 200000);
-
-        assertThat(appUsageEvents.size()).isEqualTo(1);
-        assertAppUsagePeriod(appUsagePeriodList.get(0), 0, 100000);
+        assertThat(appUsagePeriodList.size()).isEqualTo(7);
+        assertAppUsagePeriod(appUsagePeriodList.get(0), 100000, 120000);
+        assertAppUsagePeriod(appUsagePeriodList.get(1), 150000, 200000);
+        assertAppUsagePeriod(appUsagePeriodList.get(2), 300000, 500000);
+        assertAppUsagePeriod(appUsagePeriodList.get(3), 570000, 600000);
+        assertAppUsagePeriod(appUsagePeriodList.get(4), 700000, 730000);
+        assertAppUsagePeriod(appUsagePeriodList.get(5), 900000, 910000);
+        assertAppUsagePeriod(appUsagePeriodList.get(6), 1000000, 1100000);
     }
 
     @Test